|
1 /* |
|
2 * Copyright (c) 2012, 2013, 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 /* |
|
27 * Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos |
|
28 * |
|
29 * All rights reserved. |
|
30 * |
|
31 * Redistribution and use in source and binary forms, with or without |
|
32 * modification, are permitted provided that the following conditions are met: |
|
33 * |
|
34 * * Redistributions of source code must retain the above copyright notice, |
|
35 * this list of conditions and the following disclaimer. |
|
36 * |
|
37 * * Redistributions in binary form must reproduce the above copyright notice, |
|
38 * this list of conditions and the following disclaimer in the documentation |
|
39 * and/or other materials provided with the distribution. |
|
40 * |
|
41 * * Neither the name of JSR-310 nor the names of its contributors |
|
42 * may be used to endorse or promote products derived from this software |
|
43 * without specific prior written permission. |
|
44 * |
|
45 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
46 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
47 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
48 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
|
49 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
50 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
52 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
|
53 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
|
54 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
55 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
56 */ |
|
57 package java.time.chrono; |
|
58 |
|
59 import java.io.DataInput; |
|
60 import java.io.DataOutput; |
|
61 import java.io.IOException; |
|
62 import java.io.InvalidObjectException; |
|
63 import java.io.ObjectStreamException; |
|
64 import java.io.Serializable; |
|
65 import java.time.DateTimeException; |
|
66 import java.time.LocalDate; |
|
67 import java.util.Arrays; |
|
68 |
|
69 import sun.util.calendar.CalendarDate; |
|
70 |
|
71 /** |
|
72 * An era in the Japanese Imperial calendar system. |
|
73 * <p> |
|
74 * This class defines the valid eras for the Japanese chronology. |
|
75 * Only Meiji (1868-09-08 - 1912-07-29) and later eras are supported. |
|
76 * Japan introduced the Gregorian calendar since Meiji 6. The dates |
|
77 * between Meiji 1 - 5 are not historically correct. |
|
78 * The older eras are recognized as Seireki (Western calendar) era, |
|
79 * and the year of era of Seireki is proleptic Gregorian year. |
|
80 * (The Julian to Gregorian transition is not supported.) |
|
81 * |
|
82 * <h3>Specification for implementors</h3> |
|
83 * This class is immutable and thread-safe. |
|
84 * |
|
85 * @since 1.8 |
|
86 */ |
|
87 final class JapaneseEra |
|
88 implements Era, Serializable { |
|
89 |
|
90 // The offset value to 0-based index from the era value. |
|
91 // i.e., getValue() + ERA_OFFSET == 0-based index; except that -999 is mapped to zero |
|
92 static final int ERA_OFFSET = 2; |
|
93 |
|
94 static final sun.util.calendar.Era[] ERA_CONFIG; |
|
95 |
|
96 /** |
|
97 * The singleton instance for the before Meiji era ( - 1868-09-07) |
|
98 * which has the value -999. |
|
99 */ |
|
100 public static final JapaneseEra SEIREKI = new JapaneseEra(-999, LocalDate.MIN); |
|
101 /** |
|
102 * The singleton instance for the 'Meiji' era (1868-09-08 - 1912-07-29) |
|
103 * which has the value -1. |
|
104 */ |
|
105 public static final JapaneseEra MEIJI = new JapaneseEra(-1, LocalDate.of(1868, 9, 8)); |
|
106 /** |
|
107 * The singleton instance for the 'Taisho' era (1912-07-30 - 1926-12-24) |
|
108 * which has the value 0. |
|
109 */ |
|
110 public static final JapaneseEra TAISHO = new JapaneseEra(0, LocalDate.of(1912, 7, 30)); |
|
111 /** |
|
112 * The singleton instance for the 'Showa' era (1926-12-25 - 1989-01-07) |
|
113 * which has the value 1. |
|
114 */ |
|
115 public static final JapaneseEra SHOWA = new JapaneseEra(1, LocalDate.of(1926, 12, 25)); |
|
116 /** |
|
117 * The singleton instance for the 'Heisei' era (1989-01-08 - current) |
|
118 * which has the value 2. |
|
119 */ |
|
120 public static final JapaneseEra HEISEI = new JapaneseEra(2, LocalDate.of(1989, 1, 8)); |
|
121 |
|
122 // the number of defined JapaneseEra constants. |
|
123 // There could be an extra era defined in its configuration. |
|
124 private static final int N_ERA_CONSTANTS = HEISEI.getValue() + ERA_OFFSET + 1; |
|
125 |
|
126 /** |
|
127 * Serialization version. |
|
128 */ |
|
129 private static final long serialVersionUID = 1466499369062886794L; |
|
130 |
|
131 // array for the singleton JapaneseEra instances |
|
132 private static final JapaneseEra[] KNOWN_ERAS; |
|
133 |
|
134 static { |
|
135 sun.util.calendar.Era[] sunEras = JapaneseChronology.JCAL.getEras(); |
|
136 ERA_CONFIG = new sun.util.calendar.Era[sunEras.length + 1]; |
|
137 for (int i = 1; i < ERA_CONFIG.length; i++) { |
|
138 ERA_CONFIG[i] = sunEras[i - 1]; |
|
139 } |
|
140 KNOWN_ERAS = new JapaneseEra[ERA_CONFIG.length]; |
|
141 KNOWN_ERAS[0] = SEIREKI; |
|
142 KNOWN_ERAS[1] = MEIJI; |
|
143 KNOWN_ERAS[2] = TAISHO; |
|
144 KNOWN_ERAS[3] = SHOWA; |
|
145 KNOWN_ERAS[4] = HEISEI; |
|
146 for (int i = N_ERA_CONSTANTS; i < ERA_CONFIG.length; i++) { |
|
147 CalendarDate date = ERA_CONFIG[i].getSinceDate(); |
|
148 LocalDate isoDate = LocalDate.of(date.getYear(), date.getMonth(), date.getDayOfMonth()); |
|
149 KNOWN_ERAS[i] = new JapaneseEra(i - ERA_OFFSET, isoDate); |
|
150 } |
|
151 }; |
|
152 |
|
153 /** |
|
154 * The era value. |
|
155 * @serial |
|
156 */ |
|
157 private final int eraValue; |
|
158 |
|
159 // the first day of the era |
|
160 private final transient LocalDate since; |
|
161 |
|
162 /** |
|
163 * Creates an instance. |
|
164 * |
|
165 * @param eraValue the era value, validated |
|
166 * @param since the date representing the first date of the era, validated not null |
|
167 */ |
|
168 private JapaneseEra(int eraValue, LocalDate since) { |
|
169 this.eraValue = eraValue; |
|
170 this.since = since; |
|
171 } |
|
172 |
|
173 /** |
|
174 * Returns the singleton {@code JapaneseEra} corresponding to this object. |
|
175 * It's possible that this version of {@code JapaneseEra} doesn't support the latest era value. |
|
176 * In that case, this method throws an {@code ObjectStreamException}. |
|
177 * |
|
178 * @return the singleton {@code JapaneseEra} for this object |
|
179 * @throws ObjectStreamException if the deserialized object has any unknown numeric era value. |
|
180 */ |
|
181 private Object readResolve() throws ObjectStreamException { |
|
182 try { |
|
183 return of(eraValue); |
|
184 } catch (DateTimeException e) { |
|
185 InvalidObjectException ex = new InvalidObjectException("Invalid era"); |
|
186 ex.initCause(e); |
|
187 throw ex; |
|
188 } |
|
189 } |
|
190 |
|
191 //----------------------------------------------------------------------- |
|
192 /** |
|
193 * Returns the Sun private Era instance corresponding to this {@code JapaneseEra}. |
|
194 * SEIREKI doesn't have its corresponding one. |
|
195 * |
|
196 * @return the Sun private Era instance for this {@code JapaneseEra}, |
|
197 * or null for SEIREKI. |
|
198 */ |
|
199 sun.util.calendar.Era getPrivateEra() { |
|
200 return ERA_CONFIG[ordinal(eraValue)]; |
|
201 } |
|
202 |
|
203 //----------------------------------------------------------------------- |
|
204 /** |
|
205 * Obtains an instance of {@code JapaneseEra} from a value. |
|
206 * <p> |
|
207 * The {@link #SHOWA} era that contains 1970-01-01 (ISO calendar system) has the value 1 |
|
208 * Later era is numbered 2 ({@link #HEISEI}). Earlier eras are numbered 0 ({@link #TAISHO}), |
|
209 * -1 ({@link #MEIJI}), only Meiji and later eras are supported. The prior to Meiji, |
|
210 * {@link #SEIREKI} is used. |
|
211 * |
|
212 * @param japaneseEra the era to represent |
|
213 * @return the {@code JapaneseEra} singleton, never null |
|
214 * @throws DateTimeException if {@code japaneseEra} is invalid |
|
215 */ |
|
216 public static JapaneseEra of(int japaneseEra) { |
|
217 if (japaneseEra != SEIREKI.eraValue && |
|
218 (japaneseEra < MEIJI.eraValue || japaneseEra > HEISEI.eraValue)) { |
|
219 throw new DateTimeException("japaneseEra is invalid"); |
|
220 } |
|
221 return KNOWN_ERAS[ordinal(japaneseEra)]; |
|
222 } |
|
223 |
|
224 /** |
|
225 * Returns an array of JapaneseEras. |
|
226 * @return an array of JapaneseEras |
|
227 */ |
|
228 static JapaneseEra[] values() { |
|
229 return Arrays.copyOf(KNOWN_ERAS, KNOWN_ERAS.length); |
|
230 } |
|
231 |
|
232 //----------------------------------------------------------------------- |
|
233 /** |
|
234 * Obtains an instance of {@code JapaneseEra} from a date. |
|
235 * |
|
236 * @param date the date, not null |
|
237 * @return the Era singleton, never null |
|
238 */ |
|
239 static JapaneseEra from(LocalDate date) { |
|
240 for (int i = KNOWN_ERAS.length - 1; i > 0; i--) { |
|
241 JapaneseEra era = KNOWN_ERAS[i]; |
|
242 if (date.compareTo(era.since) >= 0) { |
|
243 return era; |
|
244 } |
|
245 } |
|
246 return SEIREKI; |
|
247 } |
|
248 |
|
249 static JapaneseEra toJapaneseEra(sun.util.calendar.Era privateEra) { |
|
250 for (int i = ERA_CONFIG.length - 1; i > 0; i--) { |
|
251 if (ERA_CONFIG[i].equals(privateEra)) { |
|
252 return KNOWN_ERAS[i]; |
|
253 } |
|
254 } |
|
255 return SEIREKI; |
|
256 } |
|
257 |
|
258 static sun.util.calendar.Era privateEraFrom(LocalDate isoDate) { |
|
259 for (int i = KNOWN_ERAS.length - 1; i > 0; i--) { |
|
260 JapaneseEra era = KNOWN_ERAS[i]; |
|
261 if (isoDate.compareTo(era.since) >= 0) { |
|
262 return ERA_CONFIG[i]; |
|
263 } |
|
264 } |
|
265 return null; |
|
266 } |
|
267 |
|
268 /** |
|
269 * Returns the index into the arrays from the Era value. |
|
270 * the eraValue is a valid Era number, -999, -1..2. |
|
271 * @param eravalue the era value to convert to the index |
|
272 * @return the index of the current Era |
|
273 */ |
|
274 private static int ordinal(int eravalue) { |
|
275 return (eravalue == SEIREKI.eraValue) ? 0 : eravalue + ERA_OFFSET; |
|
276 } |
|
277 |
|
278 //----------------------------------------------------------------------- |
|
279 /** |
|
280 * Returns the numeric value of this {@code JapaneseEra}. |
|
281 * <p> |
|
282 * The {@link #SHOWA} era that contains 1970-01-01 (ISO calendar system) has the value 1. |
|
283 * Later eras are numbered from 2 ({@link #HEISEI}). |
|
284 * Earlier eras are numbered 0 ({@link #TAISHO}), -1 ({@link #MEIJI}), and -999 ({@link #SEIREKI}). |
|
285 * |
|
286 * @return the era value |
|
287 */ |
|
288 @Override |
|
289 public int getValue() { |
|
290 return eraValue; |
|
291 } |
|
292 |
|
293 @Override |
|
294 public JapaneseChronology getChronology() { |
|
295 return JapaneseChronology.INSTANCE; |
|
296 } |
|
297 |
|
298 //----------------------------------------------------------------------- |
|
299 String getAbbreviation() { |
|
300 int index = ordinal(getValue()); |
|
301 if (index == 0) { |
|
302 return ""; |
|
303 } |
|
304 return ERA_CONFIG[index].getAbbreviation(); |
|
305 } |
|
306 |
|
307 String getName() { |
|
308 int index = ordinal(getValue()); |
|
309 if (index == 0) { |
|
310 return "Seireki"; |
|
311 } |
|
312 return ERA_CONFIG[index].getName(); |
|
313 } |
|
314 |
|
315 @Override |
|
316 public String toString() { |
|
317 return getName(); |
|
318 } |
|
319 |
|
320 //----------------------------------------------------------------------- |
|
321 private Object writeReplace() { |
|
322 return new Ser(Ser.JAPANESE_ERA_TYPE, this); |
|
323 } |
|
324 |
|
325 void writeExternal(DataOutput out) throws IOException { |
|
326 out.writeByte(this.getValue()); |
|
327 } |
|
328 |
|
329 static JapaneseEra readExternal(DataInput in) throws IOException { |
|
330 byte eraValue = in.readByte(); |
|
331 return JapaneseEra.of(eraValue); |
|
332 } |
|
333 |
|
334 } |