1 | /*
|
2 | * @copyright (c) 2016, Philipp Thürwächter & Pattrick Hüper
|
3 | * @copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos
|
4 | * @license BSD-3-Clause (see LICENSE in the root directory of this source tree)
|
5 | */
|
6 |
|
7 | import {requireNonNull} from '../assert';
|
8 | import {Instant} from '../Instant';
|
9 | import {LocalDate} from '../LocalDate';
|
10 | import {MathUtil} from '../MathUtil';
|
11 |
|
12 | import {ChronoUnit} from '../temporal/ChronoUnit';
|
13 | import {DefaultInterfaceTemporal} from '../temporal/DefaultInterfaceTemporal';
|
14 | import {TemporalQueries} from '../temporal/TemporalQueries';
|
15 |
|
16 | export class ChronoZonedDateTime extends DefaultInterfaceTemporal {
|
17 | query(query) {
|
18 | if (query === TemporalQueries.zoneId() || query === TemporalQueries.zone()) {
|
19 | return this.zone();
|
20 | } else if (query === TemporalQueries.chronology()) {
|
21 | return this.toLocalDate().chronology();
|
22 | } else if (query === TemporalQueries.precision()) {
|
23 | return ChronoUnit.NANOS;
|
24 | } else if (query === TemporalQueries.offset()) {
|
25 | return this.offset();
|
26 | } else if (query === TemporalQueries.localDate()) {
|
27 | return LocalDate.ofEpochDay(this.toLocalDate().toEpochDay());
|
28 | } else if (query === TemporalQueries.localTime()) {
|
29 | return this.toLocalTime();
|
30 | }
|
31 | return super.query(query);
|
32 | }
|
33 |
|
34 | /**
|
35 | * Outputs this date-time as a string using the formatter.
|
36 | *
|
37 | * @param {DateTimeFormatter} formatter - the formatter to use, not null
|
38 | * @return {string} the formatted date-time string, not null
|
39 | * @throws DateTimeException if an error occurs during printing
|
40 | */
|
41 | format(formatter) {
|
42 | requireNonNull(formatter, 'formatter');
|
43 | return formatter.format(this);
|
44 | }
|
45 |
|
46 | /**
|
47 | * Converts this date-time to an {@link Instant}.
|
48 | *
|
49 | * This returns an {@link Instant} representing the same point on the
|
50 | * time-line as this date-time. The calculation combines the
|
51 | * local date-time (see {@link toLocalDateTime}) and
|
52 | * offset (see {@link getOffset}).
|
53 | *
|
54 | * @return {Instant} an {@link Instant} representing the same instant, not null
|
55 | */
|
56 | toInstant() {
|
57 | return Instant.ofEpochSecond(this.toEpochSecond(), this.toLocalTime().nano());
|
58 | }
|
59 |
|
60 | /**
|
61 | * Converts this date-time to the number of seconds from the epoch
|
62 | * of 1970-01-01T00:00:00Z.
|
63 | *
|
64 | * This uses the local date-time (see {@link toLocalDateTime}) and
|
65 | * offset (see {@link getOffset}) to calculate the epoch-second value,
|
66 | * which is the number of elapsed seconds from 1970-01-01T00:00:00Z.
|
67 | * Instants on the time-line after the epoch are positive, earlier are negative.
|
68 | *
|
69 | * @return {number} the number of seconds from the epoch of 1970-01-01T00:00:00Z
|
70 | */
|
71 | toEpochSecond() {
|
72 | const epochDay = this.toLocalDate().toEpochDay();
|
73 | let secs = epochDay * 86400 + this.toLocalTime().toSecondOfDay();
|
74 | secs -= this.offset().totalSeconds();
|
75 | return secs;
|
76 | }
|
77 |
|
78 | /**
|
79 | * Compares this date-time to another date-time, including the chronology.
|
80 | *
|
81 | * The comparison is based first on the instant, then on the local date-time,
|
82 | * then on the zone ID, then on the chronology.
|
83 | * It is "consistent with equals", as defined by {@link Comparable}.
|
84 | *
|
85 | * If all the date-time objects being compared are in the same chronology, then the
|
86 | * additional chronology stage is not required.
|
87 | *
|
88 | * @param {ChronoZonedDateTime} other - the other date-time to compare to, not null
|
89 | * @return {number} the comparator value, negative if less, positive if greater
|
90 | */
|
91 | compareTo(other) {
|
92 | requireNonNull(other, 'other');
|
93 | let cmp = MathUtil.compareNumbers(this.toEpochSecond(), other.toEpochSecond());
|
94 | if (cmp === 0) {
|
95 | cmp = this.toLocalTime().nano() - other.toLocalTime().nano();
|
96 | if (cmp === 0) {
|
97 | cmp = this.toLocalDateTime().compareTo(other.toLocalDateTime());
|
98 | if (cmp === 0) {
|
99 | cmp = strcmp(this.zone().id(), other.zone().id());
|
100 | // we only support iso for now
|
101 | //if (cmp === 0) {
|
102 | // cmp = toLocalDate().getChronology().compareTo(other.toLocalDate().getChronology());
|
103 | //}
|
104 | }
|
105 | }
|
106 | }
|
107 | return cmp;
|
108 | }
|
109 |
|
110 | //-----------------------------------------------------------------------
|
111 | /**
|
112 | * Checks if the instant of this date-time is after that of the specified date-time.
|
113 | *
|
114 | * This method differs from the comparison in {@link compareTo} in that it
|
115 | * only compares the instant of the date-time. This is equivalent to using
|
116 | * `dateTime1.toInstant().isAfter(dateTime2.toInstant())`.
|
117 | *
|
118 | * @param {!ChronoZonedDateTime} other - the other date-time to compare to, not null
|
119 | * @return {boolean} true if this is after the specified date-time
|
120 | */
|
121 | isAfter(other) {
|
122 | requireNonNull(other, 'other');
|
123 | const thisEpochSec = this.toEpochSecond();
|
124 | const otherEpochSec = other.toEpochSecond();
|
125 | return thisEpochSec > otherEpochSec ||
|
126 | (thisEpochSec === otherEpochSec && this.toLocalTime().nano() > other.toLocalTime().nano());
|
127 | }
|
128 |
|
129 | /**
|
130 | * Checks if the instant of this date-time is before that of the specified date-time.
|
131 | *
|
132 | * This method differs from the comparison in {@link compareTo} in that it
|
133 | * only compares the instant of the date-time. This is equivalent to using
|
134 | * `dateTime1.toInstant().isBefore(dateTime2.toInstant())`.
|
135 | *
|
136 | * @param {!ChronoZonedDateTime} other - the other date-time to compare to, not null
|
137 | * @return {boolean} true if this point is before the specified date-time
|
138 | */
|
139 | isBefore(other) {
|
140 | requireNonNull(other, 'other');
|
141 | const thisEpochSec = this.toEpochSecond();
|
142 | const otherEpochSec = other.toEpochSecond();
|
143 | return thisEpochSec < otherEpochSec ||
|
144 | (thisEpochSec === otherEpochSec && this.toLocalTime().nano() < other.toLocalTime().nano());
|
145 | }
|
146 |
|
147 | /**
|
148 | * Checks if the instant of this date-time is equal to that of the specified date-time.
|
149 | *
|
150 | * This method differs from the comparison in {@link compareTo} and {@link equals}
|
151 | * in that it only compares the instant of the date-time. This is equivalent to using
|
152 | * `dateTime1.toInstant().equals(dateTime2.toInstant())`.
|
153 | *
|
154 | * @param {!ChronoZonedDateTime} other - the other date-time to compare to, not null
|
155 | * @return {boolean} true if the instant equals the instant of the specified date-time
|
156 | */
|
157 | isEqual(other) {
|
158 | requireNonNull(other, 'other');
|
159 | return this.toEpochSecond() === other.toEpochSecond() &&
|
160 | this.toLocalTime().nano() === other.toLocalTime().nano();
|
161 | }
|
162 |
|
163 | //-----------------------------------------------------------------------
|
164 | /**
|
165 | * Checks if this date-time is equal to another date-time.
|
166 | *
|
167 | * The comparison is based on the offset date-time and the zone.
|
168 | * To compare for the same instant on the time-line, use {@link compareTo}.
|
169 | * Only objects of type {@link ChronoZoneDateTime} are compared, other types return false.
|
170 | *
|
171 | * @param {*} other the object to check, null returns false
|
172 | * @return {boolean} true if this is equal to the other date-time
|
173 | */
|
174 | equals(other) {
|
175 | if (this === other) {
|
176 | return true;
|
177 | }
|
178 | if (other instanceof ChronoZonedDateTime) {
|
179 | return this.compareTo(other) === 0;
|
180 | }
|
181 | return false;
|
182 | }
|
183 |
|
184 | }
|
185 |
|
186 | function strcmp(a, b){
|
187 | if (a < b) {
|
188 | return -1;
|
189 | }
|
190 | if (a > b) {
|
191 | return 1;
|
192 | }
|
193 | return 0;
|
194 | }
|