UNPKG

7.84 kBJavaScriptView Raw
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
7import {requireNonNull} from '../assert';
8import {Instant} from '../Instant';
9import {LocalDate} from '../LocalDate';
10import {MathUtil} from '../MathUtil';
11
12import {ChronoUnit} from '../temporal/ChronoUnit';
13import {DefaultInterfaceTemporal} from '../temporal/DefaultInterfaceTemporal';
14import {TemporalQueries} from '../temporal/TemporalQueries';
15
16export 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
186function strcmp(a, b){
187 if (a < b) {
188 return -1;
189 }
190 if (a > b) {
191 return 1;
192 }
193 return 0;
194}