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