1 /*
2  * hunt-time: A time library for D programming language.
3  *
4  * Copyright (C) 2015-2018 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.time.chrono.MinguoDate;
13 
14 // import hunt.time.chrono.MinguoChronology;
15 // import hunt.time.temporal.ChronoField;
16 
17 // import hunt.stream.DataInput;
18 // import hunt.stream.DataOutput;
19 // import hunt.Exceptions;
20 
21 // //import hunt.io.ObjectInputStream;
22 // import hunt.stream.Common;
23 // import hunt.time.Clock;
24 // import hunt.time.Exceptions;
25 // import hunt.time.LocalDate;
26 // import hunt.time.LocalTime;
27 // import hunt.time.Period;
28 // import hunt.time.ZoneId;
29 // import hunt.time.temporal.ChronoField;
30 // import hunt.time.temporal.TemporalAccessor;
31 // import hunt.time.temporal.TemporalAdjuster;
32 // import hunt.time.temporal.TemporalAmount;
33 // import hunt.time.temporal.TemporalField;
34 // import hunt.time.temporal.TemporalQuery;
35 // import hunt.time.temporal.TemporalUnit;
36 // import hunt.time.Exceptions;
37 // import hunt.time.temporal.ValueRange;
38 // import hunt.time.chrono.ChronoLocalDate;
39 // import hunt.time.chrono.MinguoEra;
40 // import hunt.time.chrono.ChronoLocalDateImpl;
41 // import hunt.time.chrono.ChronoLocalDateTime;
42 // import hunt.time.chrono.ChronoPeriod;
43 
44 // /**
45 //  * A date _in the Minguo calendar system.
46 //  * !(p)
47 //  * This date operates using the {@linkplain MinguoChronology Minguo calendar}.
48 //  * This calendar system is primarily used _in the Republic of China, often known as Taiwan.
49 //  * Dates are aligned such that {@code 0001-01-01 (Minguo)} is {@code 1912-01-01 (ISO)}.
50 //  *
51 //  * !(p)
52 //  * This is a <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>
53 //  * class; use of identity-sensitive operations (including reference equality
54 //  * ({@code ==}), identity hash code, or synchronization) on instances of
55 //  * {@code MinguoDate} may have unpredictable results and should be avoided.
56 //  * The {@code equals} method should be used for comparisons.
57 //  *
58 //  * @implSpec
59 //  * This class is immutable and thread-safe.
60 //  *
61 //  * @since 1.8
62 //  */
63 // public final class MinguoDate
64 //         : ChronoLocalDateImpl!(MinguoDate)
65 //         , ChronoLocalDate, Serializable {
66 
67 //     /**
68 //      * Serialization version.
69 //      */
70 //     private enum long serialVersionUID = 1300372329181994526L;
71 
72 //     /**
73 //      * The underlying date.
74 //      */
75 //     private  /*transient*/ LocalDate isoDate;
76 
77 //     //-----------------------------------------------------------------------
78 //     /**
79 //      * Obtains the current {@code MinguoDate} from the system clock _in the default time-zone.
80 //      * !(p)
81 //      * This will query the {@link Clock#systemDefaultZone() system clock} _in the default
82 //      * time-zone to obtain the current date.
83 //      * !(p)
84 //      * Using this method will prevent the ability to use an alternate clock for testing
85 //      * because the clock is hard-coded.
86 //      *
87 //      * @return the current date using the system clock and default time-zone, not null
88 //      */
89 //     public static MinguoDate now() {
90 //         return now(Clock.systemDefaultZone());
91 //     }
92 
93 //     /**
94 //      * Obtains the current {@code MinguoDate} from the system clock _in the specified time-zone.
95 //      * !(p)
96 //      * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current date.
97 //      * Specifying the time-zone avoids dependence on the default time-zone.
98 //      * !(p)
99 //      * Using this method will prevent the ability to use an alternate clock for testing
100 //      * because the clock is hard-coded.
101 //      *
102 //      * @param zone  the zone ID to use, not null
103 //      * @return the current date using the system clock, not null
104 //      */
105 //     public static MinguoDate now(ZoneId zone) {
106 //         return now(Clock.system(zone));
107 //     }
108 
109 //     /**
110 //      * Obtains the current {@code MinguoDate} from the specified clock.
111 //      * !(p)
112 //      * This will query the specified clock to obtain the current date - today.
113 //      * Using this method allows the use of an alternate clock for testing.
114 //      * The alternate clock may be introduced using {@linkplain Clock dependency injection}.
115 //      *
116 //      * @param clock  the clock to use, not null
117 //      * @return the current date, not null
118 //      * @throws DateTimeException if the current date cannot be obtained
119 //      */
120 //     public static MinguoDate now(Clock clock) {
121 //         return new MinguoDate(LocalDate.now(clock));
122 //     }
123 
124 //     /**
125 //      * Obtains a {@code MinguoDate} representing a date _in the Minguo calendar
126 //      * system from the proleptic-year, month-of-year and day-of-month fields.
127 //      * !(p)
128 //      * This returns a {@code MinguoDate} with the specified fields.
129 //      * The day must be valid for the year and month, otherwise an exception will be thrown.
130 //      *
131 //      * @param prolepticYear  the Minguo proleptic-year
132 //      * @param month  the Minguo month-of-year, from 1 to 12
133 //      * @param dayOfMonth  the Minguo day-of-month, from 1 to 31
134 //      * @return the date _in Minguo calendar system, not null
135 //      * @throws DateTimeException if the value of any field is _out of range,
136 //      *  or if the day-of-month is invalid for the month-year
137 //      */
138 //     public static MinguoDate of(int prolepticYear, int month, int dayOfMonth) {
139 //         return new MinguoDate(LocalDate.of(prolepticYear + YEARS_DIFFERENCE, month, dayOfMonth));
140 //     }
141 
142 //     /**
143 //      * Obtains a {@code MinguoDate} from a temporal object.
144 //      * !(p)
145 //      * This obtains a date _in the Minguo calendar system based on the specified temporal.
146 //      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
147 //      * which this factory converts to an instance of {@code MinguoDate}.
148 //      * !(p)
149 //      * The conversion typically uses the {@link ChronoField#EPOCH_DAY EPOCH_DAY}
150 //      * field, which is standardized across calendar systems.
151 //      * !(p)
152 //      * This method matches the signature of the functional interface {@link TemporalQuery}
153 //      * allowing it to be used as a query via method reference, {@code MinguoDate::from}.
154 //      *
155 //      * @param temporal  the temporal object to convert, not null
156 //      * @return the date _in Minguo calendar system, not null
157 //      * @throws DateTimeException if unable to convert to a {@code MinguoDate}
158 //      */
159 //     public static MinguoDate from(TemporalAccessor temporal) {
160 //         return MinguoChronology.INSTANCE.date(temporal);
161 //     }
162 
163 //     //-----------------------------------------------------------------------
164 //     /**
165 //      * Creates an instance from an ISO date.
166 //      *
167 //      * @param isoDate  the standard local date, validated not null
168 //      */
169 //     this(LocalDate isoDate) {
170 //         assert(isoDate, "isoDate");
171 //         this.isoDate = isoDate;
172 //     }
173 
174 //     //-----------------------------------------------------------------------
175 //     /**
176 //      * Gets the chronology of this date, which is the Minguo calendar system.
177 //      * !(p)
178 //      * The {@code Chronology} represents the calendar system _in use.
179 //      * The era and other fields _in {@link ChronoField} are defined by the chronology.
180 //      *
181 //      * @return the Minguo chronology, not null
182 //      */
183 //     override
184 //     public MinguoChronology getChronology() {
185 //         return MinguoChronology.INSTANCE;
186 //     }
187 
188 //     /**
189 //      * Gets the era applicable at this date.
190 //      * !(p)
191 //      * The Minguo calendar system has two eras, 'ROC' and 'BEFORE_ROC',
192 //      * defined by {@link MinguoEra}.
193 //      *
194 //      * @return the era applicable at this date, not null
195 //      */
196 //     override
197 //     public MinguoEra getEra() {
198 //         return (getProlepticYear() >= 1 ? MinguoEra.ROC : MinguoEra.BEFORE_ROC);
199 //     }
200 
201 //     /**
202 //      * Returns the length of the month represented by this date.
203 //      * !(p)
204 //      * This returns the length of the month _in days.
205 //      * Month lengths match those of the ISO calendar system.
206 //      *
207 //      * @return the length of the month _in days
208 //      */
209 //     override
210 //     public int lengthOfMonth() {
211 //         return isoDate.lengthOfMonth();
212 //     }
213 
214 //     //-----------------------------------------------------------------------
215 //     override
216 //     public ValueRange range(TemporalField field) {
217 //         if (cast(ChronoField)(field) !is null) {
218 //             if (isSupported(field)) {
219 //                 ChronoField f = cast(ChronoField) field;
220 //                 switch (f) {
221 //                     case DAY_OF_MONTH:
222 //                     case DAY_OF_YEAR:
223 //                     case ALIGNED_WEEK_OF_MONTH:
224 //                         return isoDate.range(field);
225 //                     case YEAR_OF_ERA: {
226 //                         ValueRange range = YEAR.range();
227 //                         long max = (getProlepticYear() <= 0 ? -range.getMinimum() + 1 + YEARS_DIFFERENCE : range.getMaximum() - YEARS_DIFFERENCE);
228 //                         return ValueRange.of(1, max);
229 //                     }
230 //                 }
231 //                 return getChronology().range(f);
232 //             }
233 //             throw new UnsupportedTemporalTypeException("Unsupported field: " ~ field);
234 //         }
235 //         return field.rangeRefinedBy(this);
236 //     }
237 
238 //     override
239 //     public long getLong(TemporalField field) {
240 //         if (cast(ChronoField)(field) !is null) {
241 //             switch (cast(ChronoField) field) {
242 //                 case PROLEPTIC_MONTH:
243 //                     return getProlepticMonth();
244 //                 case YEAR_OF_ERA: {
245 //                     int prolepticYear = getProlepticYear();
246 //                     return (prolepticYear >= 1 ? prolepticYear : 1 - prolepticYear);
247 //                 }
248 //                 case YEAR:
249 //                     return getProlepticYear();
250 //                 case ERA:
251 //                     return (getProlepticYear() >= 1 ? 1 : 0);
252 //             }
253 //             return isoDate.getLong(field);
254 //         }
255 //         return field.getFrom(this);
256 //     }
257 
258 //     private long getProlepticMonth() {
259 //         return getProlepticYear() * 12L + isoDate.getMonthValue() - 1;
260 //     }
261 
262 //     private int getProlepticYear() {
263 //         return isoDate.getYear() - YEARS_DIFFERENCE;
264 //     }
265 
266 //     //-----------------------------------------------------------------------
267 //     override
268 //     public MinguoDate _with(TemporalField field, long newValue) {
269 //         if (cast(ChronoField)(field) !is null) {
270 //             ChronoField f = cast(ChronoField) field;
271 //             if (getLong(f) == newValue) {
272 //                 return this;
273 //             }
274 //             switch (f) {
275 //                 case PROLEPTIC_MONTH:
276 //                     getChronology().range(f).checkValidValue(newValue, f);
277 //                     return plusMonths(newValue - getProlepticMonth());
278 //                 case YEAR_OF_ERA:
279 //                 case YEAR:
280 //                 case ERA: {
281 //                     int nvalue = getChronology().range(f).checkValidIntValue(newValue, f);
282 //                     switch (f) {
283 //                         case YEAR_OF_ERA:
284 //                             return _with(isoDate.withYear(getProlepticYear() >= 1 ? nvalue + YEARS_DIFFERENCE : (1 - nvalue)  + YEARS_DIFFERENCE));
285 //                         case YEAR:
286 //                             return _with(isoDate.withYear(nvalue + YEARS_DIFFERENCE));
287 //                         case ERA:
288 //                             return _with(isoDate.withYear((1 - getProlepticYear()) + YEARS_DIFFERENCE));
289 //                     }
290 //                 }
291 //             }
292 //             return _with(isoDate._with(field, newValue));
293 //         }
294 //         return super._with(field, newValue);
295 //     }
296 
297 //     /**
298 //      * {@inheritDoc}
299 //      * @throws DateTimeException {@inheritDoc}
300 //      * @throws ArithmeticException {@inheritDoc}
301 //      */
302 //     override
303 //     public  MinguoDate _with(TemporalAdjuster adjuster) {
304 //         return super._with(adjuster);
305 //     }
306 
307 //     /**
308 //      * {@inheritDoc}
309 //      * @throws DateTimeException {@inheritDoc}
310 //      * @throws ArithmeticException {@inheritDoc}
311 //      */
312 //     override
313 //     public MinguoDate plus(TemporalAmount amount) {
314 //         return super.plus(amount);
315 //     }
316 
317 //     /**
318 //      * {@inheritDoc}
319 //      * @throws DateTimeException {@inheritDoc}
320 //      * @throws ArithmeticException {@inheritDoc}
321 //      */
322 //     override
323 //     public MinguoDate minus(TemporalAmount amount) {
324 //         return super.minus(amount);
325 //     }
326 
327 //     //-----------------------------------------------------------------------
328 //     // override
329 //     MinguoDate plusYears(long years) {
330 //         return _with(isoDate.plusYears(years));
331 //     }
332 
333 //     // override
334 //     MinguoDate plusMonths(long months) {
335 //         return _with(isoDate.plusMonths(months));
336 //     }
337 
338 //     // override
339 //     MinguoDate plusWeeks(long weeksToAdd) {
340 //         return super.plusWeeks(weeksToAdd);
341 //     }
342 
343 //     // override
344 //     MinguoDate plusDays(long days) {
345 //         return _with(isoDate.plusDays(days));
346 //     }
347 
348 //     // override
349 //     public MinguoDate plus(long amountToAdd, TemporalUnit unit) {
350 //         return super.plus(amountToAdd, unit);
351 //     }
352 
353 //     // override
354 //     public MinguoDate minus(long amountToAdd, TemporalUnit unit) {
355 //         return super.minus(amountToAdd, unit);
356 //     }
357 
358 //     // override
359 //     MinguoDate minusYears(long yearsToSubtract) {
360 //         return super.minusYears(yearsToSubtract);
361 //     }
362 
363 //     // override
364 //     MinguoDate minusMonths(long monthsToSubtract) {
365 //         return super.minusMonths(monthsToSubtract);
366 //     }
367 
368 //     // override
369 //     MinguoDate minusWeeks(long weeksToSubtract) {
370 //         return super.minusWeeks(weeksToSubtract);
371 //     }
372 
373 //     // override
374 //     MinguoDate minusDays(long daysToSubtract) {
375 //         return super.minusDays(daysToSubtract);
376 //     }
377 
378 //     private MinguoDate _with(LocalDate newDate) {
379 //         return (newDate.equals(isoDate) ? this : new MinguoDate(newDate));
380 //     }
381 
382 //     // override        // for javadoc and covariant return type
383 //     /*@SuppressWarnings("unchecked")*/
384 //     public final ChronoLocalDateTime!(MinguoDate) atTime(LocalTime localTime) {
385 //         return cast(ChronoLocalDateTime!(MinguoDate))super.atTime(localTime);
386 //     }
387 
388 //     override
389 //     public ChronoPeriod until(ChronoLocalDate endDate) {
390 //         Period period = isoDate.until(endDate);
391 //         return getChronology().period(period.getYears(), period.getMonths(), period.getDays());
392 //     }
393 
394 //     override  // override for performance
395 //     public long toEpochDay() {
396 //         return isoDate.toEpochDay();
397 //     }
398 
399 //     //-------------------------------------------------------------------------
400 //     /**
401 //      * Compares this date to another date, including the chronology.
402 //      * !(p)
403 //      * Compares this {@code MinguoDate} with another ensuring that the date is the same.
404 //      * !(p)
405 //      * Only objects of type {@code MinguoDate} are compared, other types return false.
406 //      * To compare the dates of two {@code TemporalAccessor} instances, including dates
407 //      * _in two different chronologies, use {@link ChronoField#EPOCH_DAY} as a comparator.
408 //      *
409 //      * @param obj  the object to check, null returns false
410 //      * @return true if this is equal to the other date
411 //      */
412 //     override  // override for performance
413 //     public bool opEquals(Object obj) {
414 //         if (this is obj) {
415 //             return true;
416 //         }
417 //         if (cast(MinguoDate)(obj) !is null) {
418 //             MinguoDate otherDate = cast(MinguoDate) obj;
419 //             return this.isoDate.equals(otherDate.isoDate);
420 //         }
421 //         return false;
422 //     }
423 
424 //     /**
425 //      * A hash code for this date.
426 //      *
427 //      * @return a suitable hash code based only on the Chronology and the date
428 //      */
429 //     override  // override for performance
430 //     public size_t toHash() @trusted nothrow {
431 //         return getChronology().getId().toHash() ^ isoDate.toHash();
432 //     }
433 
434 //     //-----------------------------------------------------------------------
435 //     /**
436 //      * Defend against malicious streams.
437 //      *
438 //      * @param s the stream to read
439 //      * @throws InvalidObjectException always
440 //      */
441 //     ///@gxc
442 //     // private void readObject(ObjectInputStream s) /*throws InvalidObjectException*/ {
443 //     //     throw new InvalidObjectException("Deserialization via serialization delegate");
444 //     // }
445 
446 //     /**
447 //      * Writes the object using a
448 //      * <a href="{@docRoot}/serialized-form.html#hunt.time.chrono.Ser">dedicated serialized form</a>.
449 //      * @serialData
450 //      * !(pre)
451 //      *  _out.writeByte(8);                 // identifies a MinguoDate
452 //      *  _out.writeInt(get(YEAR));
453 //      *  _out.writeByte(get(MONTH_OF_YEAR));
454 //      *  _out.writeByte(get(DAY_OF_MONTH));
455 //      * </pre>
456 //      *
457 //      * @return the instance of {@code Ser}, not null
458 //      */
459 //     private Object writeReplace() {
460 //         return new Ser(Ser.MINGUO_DATE_TYPE, this);
461 //     }
462 
463 //     void writeExternal(DataOutput _out) /*throws IOException*/ {
464 //         // MinguoChronology is implicit _in the MINGUO_DATE_TYPE
465 //         _out.writeInt(get(YEAR));
466 //         _out.writeByte(get(MONTH_OF_YEAR));
467 //         _out.writeByte(get(DAY_OF_MONTH));
468 //     }
469 
470 //     static MinguoDate readExternal(DataInput _in) /*throws IOException*/ {
471 //         int year = _in.readInt();
472 //         int month = _in.readByte();
473 //         int dayOfMonth = _in.readByte();
474 //         return MinguoChronology.INSTANCE.date(year, month, dayOfMonth);
475 //     }
476 
477 // }