jdk/src/share/classes/sun/util/calendar/LocalGregorianCalendar.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/util/calendar/LocalGregorianCalendar.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.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();
+                    props.load(new FileInputStream(fname));
+                    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<Era> eras = new ArrayList<Era>();
+        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);
+    }
+}