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