/* * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.util.calendar; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.StringTokenizer; import java.util.TimeZone; /** * * @author Masayoshi Okutsu * @since 1.6 */ public class LocalGregorianCalendar extends BaseCalendar { private String name; private Era[] eras; public static class Date extends BaseCalendar.Date { protected Date() { super(); } protected Date(TimeZone zone) { super(zone); } private int gregorianYear = FIELD_UNDEFINED; public Date setEra(Era era) { if (getEra() != era) { super.setEra(era); gregorianYear = FIELD_UNDEFINED; } return this; } public Date addYear(int localYear) { super.addYear(localYear); gregorianYear += localYear; return this; } public Date setYear(int localYear) { if (getYear() != localYear) { super.setYear(localYear); gregorianYear = FIELD_UNDEFINED; } return this; } public int getNormalizedYear() { return gregorianYear; } public void setNormalizedYear(int normalizedYear) { this.gregorianYear = normalizedYear; } void setLocalEra(Era era) { super.setEra(era); } void setLocalYear(int year) { super.setYear(year); } public String toString() { String time = super.toString(); time = time.substring(time.indexOf('T')); StringBuffer sb = new StringBuffer(); Era era = getEra(); if (era != null) { String abbr = era.getAbbreviation(); if (abbr != null) { sb.append(abbr); } } sb.append(getYear()).append('.'); CalendarUtils.sprintf0d(sb, getMonth(), 2).append('.'); CalendarUtils.sprintf0d(sb, getDayOfMonth(), 2); sb.append(time); return sb.toString(); } } static LocalGregorianCalendar getLocalGregorianCalendar(String name) { Properties calendarProps = null; try { String homeDir = AccessController.doPrivileged( new sun.security.action.GetPropertyAction("java.home")); final String fname = homeDir + File.separator + "lib" + File.separator + "calendars.properties"; calendarProps = (Properties) AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws IOException { Properties props = new Properties(); try (FileInputStream fis = new FileInputStream(fname)) { props.load(fis); } return props; } }); } catch (PrivilegedActionException e) { throw new RuntimeException(e.getException()); } // Parse calendar.*.eras String props = calendarProps.getProperty("calendar." + name + ".eras"); if (props == null) { return null; } List eras = new ArrayList(); StringTokenizer eraTokens = new StringTokenizer(props, ";"); while (eraTokens.hasMoreTokens()) { String items = eraTokens.nextToken().trim(); StringTokenizer itemTokens = new StringTokenizer(items, ","); String eraName = null; boolean localTime = true; long since = 0; String abbr = null; while (itemTokens.hasMoreTokens()) { String item = itemTokens.nextToken(); int index = item.indexOf('='); // it must be in the key=value form. if (index == -1) { return null; } String key = item.substring(0, index); String value = item.substring(index + 1); if ("name".equals(key)) { eraName = value; } else if ("since".equals(key)) { if (value.endsWith("u")) { localTime = false; since = Long.parseLong(value.substring(0, value.length() - 1)); } else { since = Long.parseLong(value); } } else if ("abbr".equals(key)) { abbr = value; } else { throw new RuntimeException("Unknown key word: " + key); } } Era era = new Era(eraName, abbr, since, localTime); eras.add(era); } Era[] eraArray = new Era[eras.size()]; eras.toArray(eraArray); return new LocalGregorianCalendar(name, eraArray); } private LocalGregorianCalendar(String name, Era[] eras) { this.name = name; this.eras = eras; setEras(eras); } public String getName() { return name; } public Date getCalendarDate() { return getCalendarDate(System.currentTimeMillis(), newCalendarDate()); } public Date getCalendarDate(long millis) { return getCalendarDate(millis, newCalendarDate()); } public Date getCalendarDate(long millis, TimeZone zone) { return getCalendarDate(millis, newCalendarDate(zone)); } public Date getCalendarDate(long millis, CalendarDate date) { Date ldate = (Date) super.getCalendarDate(millis, date); return adjustYear(ldate, millis, ldate.getZoneOffset()); } private Date adjustYear(Date ldate, long millis, int zoneOffset) { int i; for (i = eras.length - 1; i >= 0; --i) { Era era = eras[i]; long since = era.getSince(null); if (era.isLocalTime()) { since -= zoneOffset; } if (millis >= since) { ldate.setLocalEra(era); int y = ldate.getNormalizedYear() - era.getSinceDate().getYear() + 1; ldate.setLocalYear(y); break; } } if (i < 0) { ldate.setLocalEra(null); ldate.setLocalYear(ldate.getNormalizedYear()); } ldate.setNormalized(true); return ldate; } public Date newCalendarDate() { return new Date(); } public Date newCalendarDate(TimeZone zone) { return new Date(zone); } public boolean validate(CalendarDate date) { Date ldate = (Date) date; Era era = ldate.getEra(); if (era != null) { if (!validateEra(era)) { return false; } ldate.setNormalizedYear(era.getSinceDate().getYear() + ldate.getYear()); } else { ldate.setNormalizedYear(ldate.getYear()); } return super.validate(ldate); } private boolean validateEra(Era era) { // Validate the era for (int i = 0; i < eras.length; i++) { if (era == eras[i]) { return true; } } return false; } public boolean normalize(CalendarDate date) { if (date.isNormalized()) { return true; } normalizeYear(date); Date ldate = (Date) date; // Normalize it as a Gregorian date and get its millisecond value super.normalize(ldate); boolean hasMillis = false; long millis = 0; int year = ldate.getNormalizedYear(); int i; Era era = null; for (i = eras.length - 1; i >= 0; --i) { era = eras[i]; if (era.isLocalTime()) { CalendarDate sinceDate = era.getSinceDate(); int sinceYear = sinceDate.getYear(); if (year > sinceYear) { break; } if (year == sinceYear) { int month = ldate.getMonth(); int sinceMonth = sinceDate.getMonth(); if (month > sinceMonth) { break; } if (month == sinceMonth) { int day = ldate.getDayOfMonth(); int sinceDay = sinceDate.getDayOfMonth(); if (day > sinceDay) { break; } if (day == sinceDay) { long timeOfDay = ldate.getTimeOfDay(); long sinceTimeOfDay = sinceDate.getTimeOfDay(); if (timeOfDay >= sinceTimeOfDay) { break; } --i; break; } } } } else { if (!hasMillis) { millis = super.getTime(date); hasMillis = true; } long since = era.getSince(date.getZone()); if (millis >= since) { break; } } } if (i >= 0) { ldate.setLocalEra(era); int y = ldate.getNormalizedYear() - era.getSinceDate().getYear() + 1; ldate.setLocalYear(y); } else { // Set Gregorian year with no era ldate.setEra(null); ldate.setLocalYear(year); ldate.setNormalizedYear(year); } ldate.setNormalized(true); return true; } void normalizeMonth(CalendarDate date) { normalizeYear(date); super.normalizeMonth(date); } void normalizeYear(CalendarDate date) { Date ldate = (Date) date; // Set the supposed-to-be-correct Gregorian year first // e.g., Showa 90 becomes 2015 (1926 + 90 - 1). Era era = ldate.getEra(); if (era == null || !validateEra(era)) { ldate.setNormalizedYear(ldate.getYear()); } else { ldate.setNormalizedYear(era.getSinceDate().getYear() + ldate.getYear() - 1); } } /** * Returns whether the specified Gregorian year is a leap year. * @see #isLeapYear(Era, int) */ public boolean isLeapYear(int gregorianYear) { return CalendarUtils.isGregorianLeapYear(gregorianYear); } public boolean isLeapYear(Era era, int year) { if (era == null) { return isLeapYear(year); } int gyear = era.getSinceDate().getYear() + year - 1; return isLeapYear(gyear); } public void getCalendarDateFromFixedDate(CalendarDate date, long fixedDate) { Date ldate = (Date) date; super.getCalendarDateFromFixedDate(ldate, fixedDate); adjustYear(ldate, (fixedDate - EPOCH_OFFSET) * DAY_IN_MILLIS, 0); } }