• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.util.calendar;
27 
28 import java.io.File;
29 import java.io.FileInputStream;
30 import java.io.IOException;
31 import java.security.AccessController;
32 import java.security.PrivilegedAction;
33 import java.security.PrivilegedActionException;
34 import java.security.PrivilegedExceptionAction;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.Properties;
38 import java.util.StringTokenizer;
39 import java.util.TimeZone;
40 
41 /**
42  *
43  * @author Masayoshi Okutsu
44  * @since 1.6
45  */
46 
47 public class LocalGregorianCalendar extends BaseCalendar {
48     private String name;
49     private Era[] eras;
50 
51     public static class Date extends BaseCalendar.Date {
52 
Date()53         protected Date() {
54             super();
55         }
56 
Date(TimeZone zone)57         protected Date(TimeZone zone) {
58             super(zone);
59         }
60 
61         private int gregorianYear = FIELD_UNDEFINED;
62 
setEra(Era era)63         public Date setEra(Era era) {
64             if (getEra() != era) {
65                 super.setEra(era);
66                 gregorianYear = FIELD_UNDEFINED;
67             }
68             return this;
69         }
70 
addYear(int localYear)71         public Date addYear(int localYear) {
72             super.addYear(localYear);
73             gregorianYear += localYear;
74             return this;
75         }
76 
setYear(int localYear)77         public Date setYear(int localYear) {
78             if (getYear() != localYear) {
79                 super.setYear(localYear);
80                 gregorianYear = FIELD_UNDEFINED;
81             }
82             return this;
83         }
84 
getNormalizedYear()85         public int getNormalizedYear() {
86             return gregorianYear;
87         }
88 
setNormalizedYear(int normalizedYear)89         public void setNormalizedYear(int normalizedYear) {
90             this.gregorianYear = normalizedYear;
91         }
92 
setLocalEra(Era era)93         void setLocalEra(Era era) {
94             super.setEra(era);
95         }
96 
setLocalYear(int year)97         void setLocalYear(int year) {
98             super.setYear(year);
99         }
100 
toString()101         public String toString() {
102             String time = super.toString();
103             time = time.substring(time.indexOf('T'));
104             StringBuffer sb = new StringBuffer();
105             Era era = getEra();
106             if (era != null) {
107                 String abbr = era.getAbbreviation();
108                 if (abbr != null) {
109                     sb.append(abbr);
110                 }
111             }
112             sb.append(getYear()).append('.');
113             CalendarUtils.sprintf0d(sb, getMonth(), 2).append('.');
114             CalendarUtils.sprintf0d(sb, getDayOfMonth(), 2);
115             sb.append(time);
116             return sb.toString();
117         }
118     }
119 
getLocalGregorianCalendar(String name)120     static LocalGregorianCalendar getLocalGregorianCalendar(String name) {
121         Properties calendarProps = null;
122         try {
123             String homeDir = AccessController.doPrivileged(
124                 new sun.security.action.GetPropertyAction("java.home"));
125             final String fname = homeDir + File.separator + "lib" + File.separator
126                                  + "calendars.properties";
127             calendarProps = (Properties) AccessController.doPrivileged(new PrivilegedExceptionAction() {
128                 public Object run() throws IOException {
129                     Properties props = new Properties();
130                     try (FileInputStream fis = new FileInputStream(fname)) {
131                         props.load(fis);
132                     }
133                     return props;
134                 }
135             });
136         } catch (PrivilegedActionException e) {
137             throw new RuntimeException(e.getException());
138         }
139 
140         // Parse calendar.*.eras
141         String props = calendarProps.getProperty("calendar." + name + ".eras");
142         if (props == null) {
143             return null;
144         }
145         List<Era> eras = new ArrayList<Era>();
146         StringTokenizer eraTokens = new StringTokenizer(props, ";");
147         while (eraTokens.hasMoreTokens()) {
148             String items = eraTokens.nextToken().trim();
149             StringTokenizer itemTokens = new StringTokenizer(items, ",");
150             String eraName = null;
151             boolean localTime = true;
152             long since = 0;
153             String abbr = null;
154 
155             while (itemTokens.hasMoreTokens()) {
156                 String item = itemTokens.nextToken();
157                 int index = item.indexOf('=');
158                 // it must be in the key=value form.
159                 if (index == -1) {
160                     return null;
161                 }
162                 String key = item.substring(0, index);
163                 String value = item.substring(index + 1);
164                 if ("name".equals(key)) {
165                     eraName = value;
166                 } else if ("since".equals(key)) {
167                     if (value.endsWith("u")) {
168                         localTime = false;
169                         since = Long.parseLong(value.substring(0, value.length() - 1));
170                     } else {
171                         since = Long.parseLong(value);
172                     }
173                 } else if ("abbr".equals(key)) {
174                     abbr = value;
175                 } else {
176                     throw new RuntimeException("Unknown key word: " + key);
177                 }
178             }
179             Era era = new Era(eraName, abbr, since, localTime);
180             eras.add(era);
181         }
182         Era[] eraArray = new Era[eras.size()];
183         eras.toArray(eraArray);
184 
185         return new LocalGregorianCalendar(name, eraArray);
186     }
187 
LocalGregorianCalendar(String name, Era[] eras)188     private LocalGregorianCalendar(String name, Era[] eras) {
189         this.name = name;
190         this.eras = eras;
191         setEras(eras);
192     }
193 
getName()194     public String getName() {
195         return name;
196     }
197 
getCalendarDate()198     public Date getCalendarDate() {
199         return getCalendarDate(System.currentTimeMillis(), newCalendarDate());
200     }
201 
getCalendarDate(long millis)202     public Date getCalendarDate(long millis) {
203         return getCalendarDate(millis, newCalendarDate());
204     }
205 
getCalendarDate(long millis, TimeZone zone)206     public Date getCalendarDate(long millis, TimeZone zone) {
207         return getCalendarDate(millis, newCalendarDate(zone));
208     }
209 
getCalendarDate(long millis, CalendarDate date)210     public Date getCalendarDate(long millis, CalendarDate date) {
211         Date ldate = (Date) super.getCalendarDate(millis, date);
212         return adjustYear(ldate, millis, ldate.getZoneOffset());
213     }
214 
adjustYear(Date ldate, long millis, int zoneOffset)215     private Date adjustYear(Date ldate, long millis, int zoneOffset) {
216         int i;
217         for (i = eras.length - 1; i >= 0; --i) {
218             Era era = eras[i];
219             long since = era.getSince(null);
220             if (era.isLocalTime()) {
221                 since -= zoneOffset;
222             }
223             if (millis >= since) {
224                 ldate.setLocalEra(era);
225                 int y = ldate.getNormalizedYear() - era.getSinceDate().getYear() + 1;
226                 ldate.setLocalYear(y);
227                 break;
228             }
229         }
230         if (i < 0) {
231             ldate.setLocalEra(null);
232             ldate.setLocalYear(ldate.getNormalizedYear());
233         }
234         ldate.setNormalized(true);
235         return ldate;
236     }
237 
newCalendarDate()238     public Date newCalendarDate() {
239         return new Date();
240     }
241 
newCalendarDate(TimeZone zone)242     public Date newCalendarDate(TimeZone zone) {
243         return new Date(zone);
244     }
245 
validate(CalendarDate date)246     public boolean validate(CalendarDate date) {
247         Date ldate = (Date) date;
248         Era era = ldate.getEra();
249         if (era != null) {
250             if (!validateEra(era)) {
251                 return false;
252             }
253             ldate.setNormalizedYear(era.getSinceDate().getYear() + ldate.getYear());
254         } else {
255             ldate.setNormalizedYear(ldate.getYear());
256         }
257         return super.validate(ldate);
258     }
259 
validateEra(Era era)260     private boolean validateEra(Era era) {
261         // Validate the era
262         for (int i = 0; i < eras.length; i++) {
263             if (era == eras[i]) {
264                 return true;
265             }
266         }
267         return false;
268     }
269 
normalize(CalendarDate date)270     public boolean normalize(CalendarDate date) {
271         if (date.isNormalized()) {
272             return true;
273         }
274 
275         normalizeYear(date);
276         Date ldate = (Date) date;
277 
278         // Normalize it as a Gregorian date and get its millisecond value
279         super.normalize(ldate);
280 
281         boolean hasMillis = false;
282         long millis = 0;
283         int year = ldate.getNormalizedYear();
284         int i;
285         Era era = null;
286         for (i = eras.length - 1; i >= 0; --i) {
287             era = eras[i];
288             if (era.isLocalTime()) {
289                 CalendarDate sinceDate = era.getSinceDate();
290                 int sinceYear = sinceDate.getYear();
291                 if (year > sinceYear) {
292                     break;
293                 }
294                 if (year == sinceYear) {
295                     int month = ldate.getMonth();
296                     int sinceMonth = sinceDate.getMonth();
297                     if (month > sinceMonth) {
298                         break;
299                     }
300                     if (month == sinceMonth) {
301                         int day = ldate.getDayOfMonth();
302                         int sinceDay = sinceDate.getDayOfMonth();
303                         if (day > sinceDay) {
304                             break;
305                         }
306                         if (day == sinceDay) {
307                             long timeOfDay = ldate.getTimeOfDay();
308                             long sinceTimeOfDay = sinceDate.getTimeOfDay();
309                             if (timeOfDay >= sinceTimeOfDay) {
310                                 break;
311                             }
312                             --i;
313                             break;
314                         }
315                     }
316                 }
317             } else {
318                 if (!hasMillis) {
319                     millis  = super.getTime(date);
320                     hasMillis = true;
321                 }
322 
323                 long since = era.getSince(date.getZone());
324                 if (millis >= since) {
325                     break;
326                 }
327             }
328         }
329         if (i >= 0) {
330             ldate.setLocalEra(era);
331             int y = ldate.getNormalizedYear() - era.getSinceDate().getYear() + 1;
332             ldate.setLocalYear(y);
333         } else {
334             // Set Gregorian year with no era
335             ldate.setEra(null);
336             ldate.setLocalYear(year);
337             ldate.setNormalizedYear(year);
338         }
339         ldate.setNormalized(true);
340         return true;
341     }
342 
normalizeMonth(CalendarDate date)343     void normalizeMonth(CalendarDate date) {
344         normalizeYear(date);
345         super.normalizeMonth(date);
346     }
347 
normalizeYear(CalendarDate date)348     void normalizeYear(CalendarDate date) {
349         Date ldate = (Date) date;
350         // Set the supposed-to-be-correct Gregorian year first
351         // e.g., Showa 90 becomes 2015 (1926 + 90 - 1).
352         Era era = ldate.getEra();
353         if (era == null || !validateEra(era)) {
354             ldate.setNormalizedYear(ldate.getYear());
355         } else {
356             ldate.setNormalizedYear(era.getSinceDate().getYear() + ldate.getYear() - 1);
357         }
358     }
359 
360     /**
361      * Returns whether the specified Gregorian year is a leap year.
362      * @see #isLeapYear(Era, int)
363      */
isLeapYear(int gregorianYear)364     public boolean isLeapYear(int gregorianYear) {
365         return CalendarUtils.isGregorianLeapYear(gregorianYear);
366     }
367 
isLeapYear(Era era, int year)368     public boolean isLeapYear(Era era, int year) {
369         if (era == null) {
370             return isLeapYear(year);
371         }
372         int gyear = era.getSinceDate().getYear() + year - 1;
373         return isLeapYear(gyear);
374     }
375 
getCalendarDateFromFixedDate(CalendarDate date, long fixedDate)376     public void getCalendarDateFromFixedDate(CalendarDate date, long fixedDate) {
377         Date ldate = (Date) date;
378         super.getCalendarDateFromFixedDate(ldate, fixedDate);
379         adjustYear(ldate, (fixedDate - EPOCH_OFFSET) * DAY_IN_MILLIS, 0);
380     }
381 }
382