atomic-fns 0.3.5 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/{core → dist}/collections/BTree.d.ts +6 -6
- package/{core → dist}/collections/BTree.js +17 -17
- package/{core → dist}/collections/Heap.d.ts +3 -3
- package/{core → dist}/collections/Heap.js +0 -0
- package/dist/collections/LRUCache.d.ts +80 -0
- package/dist/collections/LRUCache.js +126 -0
- package/{core → dist}/collections/SortedMap.d.ts +2 -2
- package/{core → dist}/collections/SortedMap.js +0 -0
- package/{core → dist}/collections/SortedSet.d.ts +3 -3
- package/{core → dist}/collections/SortedSet.js +1 -1
- package/{core → dist}/collections/SortedTree.d.ts +3 -3
- package/{core → dist}/collections/SortedTree.js +1 -1
- package/{core → dist}/collections/SplayTree.d.ts +5 -5
- package/{core → dist}/collections/SplayTree.js +0 -0
- package/{core → dist}/collections/abc.d.ts +0 -0
- package/{core → dist}/collections/abc.js +0 -0
- package/{core → dist}/collections/deque.d.ts +6 -6
- package/{core → dist}/collections/deque.js +0 -0
- package/{core → dist}/collections/frozenset.d.ts +0 -0
- package/{core → dist}/collections/frozenset.js +3 -6
- package/{core → dist}/collections/index.d.ts +4 -4
- package/{core → dist}/collections/index.js +0 -0
- package/{core → dist}/functools/index.d.ts +27 -13
- package/{core → dist}/functools/index.js +34 -12
- package/{core → dist}/globals/index.d.ts +7 -10
- package/{core → dist}/globals/index.js +7 -14
- package/dist/i18n/date/index.d.ts +204 -0
- package/dist/i18n/date/index.js +530 -0
- package/dist/i18n/date/utils.d.ts +65 -0
- package/dist/i18n/date/utils.js +312 -0
- package/dist/i18n/duration.d.ts +112 -0
- package/dist/i18n/duration.js +392 -0
- package/dist/i18n/format.d.ts +26 -0
- package/dist/i18n/format.js +495 -0
- package/{core → dist}/i18n/index.d.ts +1 -1
- package/{core → dist}/i18n/index.js +1 -1
- package/{core → dist}/index.d.ts +0 -0
- package/{core → dist}/index.js +0 -0
- package/{core → dist}/itertools/index.d.ts +27 -27
- package/{core → dist}/itertools/index.js +24 -24
- package/{core → dist}/math/index.d.ts +3 -3
- package/{core → dist}/math/index.js +0 -0
- package/{core → dist}/operators/index.d.ts +2 -2
- package/{core → dist}/operators/index.js +2 -2
- package/{core → dist}/random/index.d.ts +1 -1
- package/{core → dist}/random/index.js +3 -3
- package/package.json +28 -42
- package/.editorconfig +0 -12
- package/.esdoc.json +0 -27
- package/.eslintignore +0 -1
- package/.eslintrc.json +0 -35
- package/.firebaserc +0 -5
- package/.prettierrc +0 -19
- package/core/collections/BTree.ts +0 -1340
- package/core/collections/Heap.ts +0 -189
- package/core/collections/LRUCache.d.ts +0 -152
- package/core/collections/LRUCache.js +0 -409
- package/core/collections/LRUCache.ts +0 -486
- package/core/collections/SortedMap.ts +0 -146
- package/core/collections/SortedSet.ts +0 -110
- package/core/collections/SortedTree.ts +0 -160
- package/core/collections/SplayTree.ts +0 -354
- package/core/collections/abc.ts +0 -176
- package/core/collections/deque.ts +0 -338
- package/core/collections/frozenset.ts +0 -37
- package/core/collections/index.ts +0 -1024
- package/core/collections/test.html +0 -10
- package/core/collections/typedArrays.d.ts +0 -31
- package/core/collections/typedArrays.js +0 -143
- package/core/collections/typedArrays.ts +0 -163
- package/core/functools/index.ts +0 -260
- package/core/globals/index.ts +0 -481
- package/core/i18n/date/format.d.ts +0 -16
- package/core/i18n/date/format.js +0 -307
- package/core/i18n/date/format.ts +0 -343
- package/core/i18n/date/index.d.ts +0 -224
- package/core/i18n/date/index.js +0 -387
- package/core/i18n/date/index.ts +0 -471
- package/core/i18n/date/test.html +0 -67
- package/core/i18n/index.ts +0 -8
- package/core/index.ts +0 -8
- package/core/itertools/index.ts +0 -494
- package/core/math/index.ts +0 -152
- package/core/operators/index.ts +0 -310
- package/core/random/index.ts +0 -66
- package/firebase.json +0 -10
- package/jasmine.json +0 -14
- package/tests/BTree.spec.ts +0 -143
- package/tests/Cache.spec.ts +0 -161
- package/tests/Heap.spec.ts +0 -66
- package/tests/SortedMap.spec.ts +0 -144
- package/tests/SortedSet.spec.ts +0 -84
- package/tests/SortedTree.spec.ts +0 -164
- package/tests/SplayTree.spec.ts +0 -121
- package/tests/collections.spec.ts +0 -288
- package/tests/deque.spec.ts +0 -107
- package/tests/globals.spec.ts +0 -270
- package/tests/itertools.spec.ts +0 -266
- package/tests/math.spec.ts +0 -25
- package/tests/operators.spec.ts +0 -40
- package/tests/random.spec.ts +0 -46
- package/tsconfig.json +0 -126
- package/tsconfig.node.json +0 -18
- package/tsconfig.xo.json +0 -9
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
import { isObject, ValueError } from '../../globals/index.js';
|
|
2
|
+
import { Duration, UNITS_PLURAL } from '../duration.js';
|
|
3
|
+
import { asDate, formatDate, strftime } from '../format.js';
|
|
4
|
+
import { asNumber, dayOfYear, daysInMonth, daysInYear, isLeapYear, maxDate, minDate, weekOfYear, weeksInYear } from './utils.js';
|
|
5
|
+
// Export date functions
|
|
6
|
+
export { asDate, daysInMonth, daysInYear, formatDate, isLeapYear, maxDate, minDate, strftime, weeksInYear };
|
|
7
|
+
const INVALID_DATE_STRING = 'Invalid Date';
|
|
8
|
+
/**
|
|
9
|
+
* Creates a date tied to a given locale (default system locale) which can be formatted in that locale's language using the native {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl Intl Apis} directly or using a formatting string.
|
|
10
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl Intl Apis}
|
|
11
|
+
*/
|
|
12
|
+
export class IntlDate {
|
|
13
|
+
_date;
|
|
14
|
+
locale;
|
|
15
|
+
intlRelativeFormat;
|
|
16
|
+
/** Parses the provided value as UTC date or returns the current UTC date. */
|
|
17
|
+
static UTC(value, locale) {
|
|
18
|
+
return new IntlDate(value, { utc: true, locale });
|
|
19
|
+
}
|
|
20
|
+
/** Returns the current local date and time.*/
|
|
21
|
+
static now() {
|
|
22
|
+
return new IntlDate();
|
|
23
|
+
}
|
|
24
|
+
/** Creates a new date from a Unix timestamp (seconds since the unix epoch) */
|
|
25
|
+
static unix(seconds) {
|
|
26
|
+
return new IntlDate(seconds * 1000);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Creates a new `IntlDate` in local time and specified locale (default is system locale).
|
|
30
|
+
* **Note:** The allowed values for `month` start at 1, which is different from legacy `Date`
|
|
31
|
+
* @param {DateLike} obj The date value (default is current local time)
|
|
32
|
+
* @param {Object} opts The options for this date
|
|
33
|
+
* @param {boolean?} opts.utc Converts input or current time to UTC
|
|
34
|
+
* @param {string?} opts.locale A locale string to use for this date
|
|
35
|
+
* @returns
|
|
36
|
+
*/
|
|
37
|
+
constructor(obj, { locale, utc } = {}) {
|
|
38
|
+
this.locale = locale;
|
|
39
|
+
if (obj instanceof IntlDate) {
|
|
40
|
+
obj = obj._date;
|
|
41
|
+
}
|
|
42
|
+
if (typeof obj === 'string' || typeof obj === 'number' || obj instanceof Date) {
|
|
43
|
+
this._date = asDate(obj, utc);
|
|
44
|
+
}
|
|
45
|
+
else if (isObject(obj)) {
|
|
46
|
+
let { year, month, day, hour, minute, second, millisecond } = obj;
|
|
47
|
+
// NOTE month is from 1-12, not from 0-11
|
|
48
|
+
if (typeof month === 'number') {
|
|
49
|
+
month -= 1;
|
|
50
|
+
}
|
|
51
|
+
if (utc) {
|
|
52
|
+
// from UTC to current
|
|
53
|
+
this._date = new Date(Date.UTC(year, month, day || 1, hour || 0, minute || 0, second || 0, millisecond || 0));
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this._date = new Date(year, month, day || 1, hour || 0, minute || 0, second || 0, millisecond || 0);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
this._date = asDate(obj, utc);
|
|
61
|
+
}
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
/** Get the date's year. */
|
|
65
|
+
get year() {
|
|
66
|
+
return this._date.getFullYear();
|
|
67
|
+
}
|
|
68
|
+
/** Get the this date's month as a number from 1 to 12, inclusive. */
|
|
69
|
+
get month() {
|
|
70
|
+
return this._date.getMonth() + 1;
|
|
71
|
+
}
|
|
72
|
+
/** Returns the weekday as a number between 1 and 7, inclusive, where Monday is 1 and Sunday is 7. */
|
|
73
|
+
get dayOfWeek() {
|
|
74
|
+
if (this._date.getDay() === 0)
|
|
75
|
+
return 7;
|
|
76
|
+
return this._date.getDay();
|
|
77
|
+
}
|
|
78
|
+
/** Get the this date's current day of the month. */
|
|
79
|
+
get day() {
|
|
80
|
+
return this._date.getDate();
|
|
81
|
+
}
|
|
82
|
+
/** Get the this date's current hour. */
|
|
83
|
+
get hour() {
|
|
84
|
+
return this._date.getHours();
|
|
85
|
+
}
|
|
86
|
+
/** Get the this date's current minute. */
|
|
87
|
+
get minute() {
|
|
88
|
+
return this._date.getMinutes();
|
|
89
|
+
}
|
|
90
|
+
/** Get the this date's current second. */
|
|
91
|
+
get second() {
|
|
92
|
+
return this._date.getSeconds();
|
|
93
|
+
}
|
|
94
|
+
/** Get the this date's current millisecond. */
|
|
95
|
+
get millisecond() {
|
|
96
|
+
return this._date.getMilliseconds();
|
|
97
|
+
}
|
|
98
|
+
isValid() {
|
|
99
|
+
return this._date.toString() !== INVALID_DATE_STRING;
|
|
100
|
+
}
|
|
101
|
+
/** Get the number of days in this date's month. */
|
|
102
|
+
daysInMonth() {
|
|
103
|
+
return daysInMonth(this._date);
|
|
104
|
+
}
|
|
105
|
+
/** Get the number of days in this date's year. */
|
|
106
|
+
daysInYear() {
|
|
107
|
+
return daysInYear(this.year);
|
|
108
|
+
}
|
|
109
|
+
dayOfYear() {
|
|
110
|
+
return dayOfYear(this._date);
|
|
111
|
+
}
|
|
112
|
+
/** Returns `true` if this date's year is a leap year. */
|
|
113
|
+
isLeapYear() {
|
|
114
|
+
return isLeapYear(this.year);
|
|
115
|
+
}
|
|
116
|
+
/** Gets the number of weeks according to locale in the current year. */
|
|
117
|
+
weeksInYear() {
|
|
118
|
+
return weeksInYear(this.year);
|
|
119
|
+
}
|
|
120
|
+
/** Gets the number of weeks in the current year, according to ISO weeks. */
|
|
121
|
+
isoWeeksInYear() {
|
|
122
|
+
return weeksInYear(this.year, 1, 4);
|
|
123
|
+
}
|
|
124
|
+
/** Returns the current week of the year. */
|
|
125
|
+
week() {
|
|
126
|
+
return weekOfYear(this._date).week;
|
|
127
|
+
}
|
|
128
|
+
/** Returns the ISO week of the year. */
|
|
129
|
+
isoWeek() {
|
|
130
|
+
return weekOfYear(this._date, 1, 4).week;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Returns a localized string representation of this date.
|
|
134
|
+
* @param {Intl.DateTimeFormatOptions} opts The options to use for the format
|
|
135
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat Intl.DateTimeFormat()}
|
|
136
|
+
*/
|
|
137
|
+
toString(opts) {
|
|
138
|
+
return this._date.toLocaleString(this.locale, opts);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Returns a localized string representation of this date, according to the given format string. Format codes use the same specification as {@link https://momentjs.com/docs/#/displaying/format/ moment}.
|
|
142
|
+
* @param {string} str The format string to use
|
|
143
|
+
* @see {@link https://momentjs.com/docs/#/displaying/format/ List of formats}
|
|
144
|
+
* @example
|
|
145
|
+
```js
|
|
146
|
+
new IntlDate().format('MM/DD/YYYY') // '10/31/2022'
|
|
147
|
+
```
|
|
148
|
+
*/
|
|
149
|
+
format(str) {
|
|
150
|
+
return formatDate(str, this._date, this.locale);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Returns a new copy of the native `Date` object used by this instance.
|
|
154
|
+
* @returns {Date} A new `Date` object
|
|
155
|
+
*/
|
|
156
|
+
toDate() {
|
|
157
|
+
return new Date(this.isValid() ? this._date : NaN);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Returns the number of seconds since the Unix Epoch (January 1, 1970 UTC).
|
|
161
|
+
* @see {@link IntlDate.timestamp}
|
|
162
|
+
* @see {@link IntlDate.unix}
|
|
163
|
+
* @example
|
|
164
|
+
```js
|
|
165
|
+
new IntlDate().toSeconds() // 1318874398
|
|
166
|
+
```
|
|
167
|
+
*/
|
|
168
|
+
toSeconds() {
|
|
169
|
+
return Math.trunc(this.getTime() / 1000);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Returns the number of seconds since the Unix Epoch (January 1, 1970 UTC).
|
|
173
|
+
* @see {@link IntlDate.toSeconds}
|
|
174
|
+
* @see {@link IntlDate.unix}
|
|
175
|
+
* @example
|
|
176
|
+
```js
|
|
177
|
+
new IntlDate().timestamp() // 1318874398
|
|
178
|
+
```
|
|
179
|
+
*/
|
|
180
|
+
timestamp() {
|
|
181
|
+
return this.toSeconds();
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Returns the number of seconds since the Unix Epoch (January 1, 1970 UTC).
|
|
185
|
+
* @see {@link IntlDate.toSeconds}
|
|
186
|
+
* @see {@link IntlDate.timestamp}
|
|
187
|
+
* @example
|
|
188
|
+
```js
|
|
189
|
+
new IntlDate().unix() // 1318874398
|
|
190
|
+
```
|
|
191
|
+
*/
|
|
192
|
+
unix() {
|
|
193
|
+
return this.toSeconds();
|
|
194
|
+
}
|
|
195
|
+
/** Formats a string to the ISO8601 standard.
|
|
196
|
+
* @example
|
|
197
|
+
```js
|
|
198
|
+
new IntlDate().toISOString() // '2022-10-31T22:44:30.652Z'
|
|
199
|
+
```
|
|
200
|
+
*/
|
|
201
|
+
toISOString() {
|
|
202
|
+
return this._date.toISOString();
|
|
203
|
+
}
|
|
204
|
+
/** Returns the date part formatted as ISO8601.
|
|
205
|
+
* @example
|
|
206
|
+
```js
|
|
207
|
+
new IntlDate().toISODate() // '2022-10-31'
|
|
208
|
+
```
|
|
209
|
+
*/
|
|
210
|
+
toISODate() {
|
|
211
|
+
return this._date.toISOString().slice(0, 10);
|
|
212
|
+
}
|
|
213
|
+
/** Returns the time part formatted as ISO8601.
|
|
214
|
+
* @example
|
|
215
|
+
```js
|
|
216
|
+
new IntlDate().toISOTime() // 'T22:44:30.652Z'
|
|
217
|
+
```
|
|
218
|
+
*/
|
|
219
|
+
toISOTime() {
|
|
220
|
+
return this._date.toISOString().slice(11);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Returns an object containing year, month, day-of-month, hours, minutes, seconds, milliseconds.
|
|
224
|
+
* @returns {Object} An object like `{year, month, date, hours, minutes, seconds, ms}`
|
|
225
|
+
*/
|
|
226
|
+
toObject() {
|
|
227
|
+
return {
|
|
228
|
+
year: this.year,
|
|
229
|
+
month: this.month,
|
|
230
|
+
day: this.day,
|
|
231
|
+
hour: this.hour,
|
|
232
|
+
minute: this.minute,
|
|
233
|
+
second: this.second,
|
|
234
|
+
millisecond: this.millisecond
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
/** Returns the number of milliseconds since the Unix Epoch (January 1, 1970 UTC) */
|
|
238
|
+
getTime() {
|
|
239
|
+
return this.isValid() ? this._date.getTime() : NaN;
|
|
240
|
+
}
|
|
241
|
+
/** Alias of {@link IntlDate.getTime} */
|
|
242
|
+
valueOf() {
|
|
243
|
+
return this.getTime();
|
|
244
|
+
}
|
|
245
|
+
/** Returns the timezone string name */
|
|
246
|
+
zoneName() {
|
|
247
|
+
return this.format('zzz');
|
|
248
|
+
}
|
|
249
|
+
/** Returns the timezone GMT offset as a string */
|
|
250
|
+
zone() {
|
|
251
|
+
return this.format('ZZ');
|
|
252
|
+
}
|
|
253
|
+
/** Returns the difference in `minutes` between this date and UTC */
|
|
254
|
+
utcOffset() {
|
|
255
|
+
return this._date.getTimezoneOffset();
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Check if this date is before another date. The other value will be parsed as an `IntlDate` if not already so.
|
|
259
|
+
* @param {DateLike} other Another date or date like object
|
|
260
|
+
* @returns {boolean} Returns `true` if this date is before the given value
|
|
261
|
+
*/
|
|
262
|
+
isBefore(other) {
|
|
263
|
+
if (other instanceof IntlDate) {
|
|
264
|
+
return this.getTime() < other.getTime();
|
|
265
|
+
}
|
|
266
|
+
return this.getTime() < new IntlDate(other).getTime();
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Check if this date is strictly after the given `start` and before `stop` dates. The values will be parsed as an `IntlDate` if not already so.
|
|
270
|
+
* @param {DateLike} start The smaller date
|
|
271
|
+
* @param {DateLike} stop The larger date
|
|
272
|
+
* @returns {boolean} Returns `true` if this date is greater than `start` and less than `stop`.
|
|
273
|
+
*/
|
|
274
|
+
isBetween(start, stop) {
|
|
275
|
+
return this.isAfter(start) && this.isBefore(stop);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Check if this date is after another date. The other value will be parsed as an `IntlDate` if not already so.
|
|
279
|
+
* @param {DateLike} other Another date or date like object
|
|
280
|
+
* @returns {boolean} Returns `true` if this date is after the given value
|
|
281
|
+
*/
|
|
282
|
+
isAfter(other) {
|
|
283
|
+
if (other instanceof IntlDate) {
|
|
284
|
+
return this.getTime() > other.getTime();
|
|
285
|
+
}
|
|
286
|
+
return this.getTime() > new IntlDate(other).getTime();
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Check if this date is the same as `other`.
|
|
290
|
+
* @param other Another date object
|
|
291
|
+
* @returns {boolean} Returns `true` if this date is the same as other
|
|
292
|
+
*/
|
|
293
|
+
isSame(other) {
|
|
294
|
+
if (other instanceof IntlDate) {
|
|
295
|
+
return (this.isValid() &&
|
|
296
|
+
other.isValid() &&
|
|
297
|
+
this.getTime() === other.getTime() &&
|
|
298
|
+
this.locale === other.locale);
|
|
299
|
+
}
|
|
300
|
+
return this.getTime() === other.getTime();
|
|
301
|
+
}
|
|
302
|
+
lt(other) {
|
|
303
|
+
return this.isBefore(other);
|
|
304
|
+
}
|
|
305
|
+
eq(other) {
|
|
306
|
+
return this.isSame(other);
|
|
307
|
+
}
|
|
308
|
+
compare(other) {
|
|
309
|
+
if (!this.isValid())
|
|
310
|
+
return 1;
|
|
311
|
+
let dt = new IntlDate(other);
|
|
312
|
+
if (!dt.isValid())
|
|
313
|
+
return -1;
|
|
314
|
+
return this.getTime() - dt.getTime();
|
|
315
|
+
}
|
|
316
|
+
set(values) {
|
|
317
|
+
if (!this.isValid())
|
|
318
|
+
return this;
|
|
319
|
+
const normalized = normalizeObject(values, normalizeUnit);
|
|
320
|
+
let mixed = { ...this.toObject(), ...normalized };
|
|
321
|
+
// if we didn't set the day but we ended up on an overflow date,
|
|
322
|
+
// use the last day of the right month
|
|
323
|
+
if (normalized.day === undefined) {
|
|
324
|
+
mixed.day = Math.min(daysInMonth(this._date), mixed.day);
|
|
325
|
+
}
|
|
326
|
+
return this.clone(mixed);
|
|
327
|
+
}
|
|
328
|
+
get relativeFormat() {
|
|
329
|
+
if (this.intlRelativeFormat)
|
|
330
|
+
return this.intlRelativeFormat;
|
|
331
|
+
this.intlRelativeFormat = new Intl.RelativeTimeFormat(this.locale);
|
|
332
|
+
return new Intl.RelativeTimeFormat(this.locale);
|
|
333
|
+
}
|
|
334
|
+
relativeTime(n, unit = 'seconds') {
|
|
335
|
+
return this.relativeFormat.format(n, unit);
|
|
336
|
+
}
|
|
337
|
+
fromNow(unit = 'seconds') {
|
|
338
|
+
let diff = this.diff(new Date(), unit);
|
|
339
|
+
return this.relativeTime(diff, unit);
|
|
340
|
+
}
|
|
341
|
+
from(other, unit = 'seconds') {
|
|
342
|
+
let diff = this.diff(other, unit);
|
|
343
|
+
return this.relativeTime(diff, unit);
|
|
344
|
+
}
|
|
345
|
+
toNow(unit = 'seconds') {
|
|
346
|
+
let diff = this.diff(new Date(), unit);
|
|
347
|
+
return this.relativeTime(-diff, unit);
|
|
348
|
+
}
|
|
349
|
+
to(other, unit = 'seconds') {
|
|
350
|
+
let diff = this.diff(other, unit);
|
|
351
|
+
return this.relativeTime(-diff, unit);
|
|
352
|
+
}
|
|
353
|
+
diff(other, unit = 'milliseconds', exact = false) {
|
|
354
|
+
let dt = new IntlDate(other);
|
|
355
|
+
let dur = new Duration(this.getTime() - dt.getTime(), exact);
|
|
356
|
+
let total = dur.total(unit);
|
|
357
|
+
if (!exact)
|
|
358
|
+
total = Math.trunc(total);
|
|
359
|
+
return total;
|
|
360
|
+
}
|
|
361
|
+
add(duration, exact = false) {
|
|
362
|
+
return this.clone(addDuration(this._date, duration, exact));
|
|
363
|
+
}
|
|
364
|
+
subtract(duration, exact = false) {
|
|
365
|
+
return this.clone(subDuration(this._date, duration, exact));
|
|
366
|
+
}
|
|
367
|
+
startOf(unit) {
|
|
368
|
+
if (!this.isValid())
|
|
369
|
+
return this;
|
|
370
|
+
const obj = {}, normalizedUnit = UNITS_PLURAL[unit.toLowerCase()];
|
|
371
|
+
switch (normalizedUnit) {
|
|
372
|
+
case 'years':
|
|
373
|
+
obj.month = 1;
|
|
374
|
+
// falls through
|
|
375
|
+
case 'quarters':
|
|
376
|
+
case 'months':
|
|
377
|
+
obj.day = 1;
|
|
378
|
+
// falls through
|
|
379
|
+
case 'weeks':
|
|
380
|
+
case 'days':
|
|
381
|
+
obj.hour = 0;
|
|
382
|
+
// falls through
|
|
383
|
+
case 'hours':
|
|
384
|
+
obj.minute = 0;
|
|
385
|
+
// falls through
|
|
386
|
+
case 'minutes':
|
|
387
|
+
obj.second = 0;
|
|
388
|
+
// falls through
|
|
389
|
+
case 'seconds':
|
|
390
|
+
obj.millisecond = 0;
|
|
391
|
+
break;
|
|
392
|
+
case 'milliseconds':
|
|
393
|
+
break;
|
|
394
|
+
// no default, invalid units throw in normalizeUnit()
|
|
395
|
+
}
|
|
396
|
+
if (normalizedUnit === 'weeks') {
|
|
397
|
+
obj.weekday = 1;
|
|
398
|
+
}
|
|
399
|
+
if (normalizedUnit === 'quarters') {
|
|
400
|
+
const q = Math.ceil(this.month / 3);
|
|
401
|
+
obj.month = (q - 1) * 3 + 1;
|
|
402
|
+
}
|
|
403
|
+
return this.set(obj);
|
|
404
|
+
}
|
|
405
|
+
endOf(unit) {
|
|
406
|
+
return this.isValid()
|
|
407
|
+
? this.add({ [unit]: 1 })
|
|
408
|
+
.startOf(unit)
|
|
409
|
+
.subtract({ milliseconds: 1 })
|
|
410
|
+
: this;
|
|
411
|
+
}
|
|
412
|
+
clone(date) {
|
|
413
|
+
return new IntlDate(date ?? this, { locale: this.locale });
|
|
414
|
+
}
|
|
415
|
+
static max(...args) {
|
|
416
|
+
return maxDate.apply(undefined, args);
|
|
417
|
+
}
|
|
418
|
+
static min(...args) {
|
|
419
|
+
return minDate.apply(undefined, args);
|
|
420
|
+
}
|
|
421
|
+
inspect() {
|
|
422
|
+
return `new IntlDate("${this.toISOString()}")`;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
// Check if the new offset is different because we crossed to DST
|
|
426
|
+
function fixOffset(startDate, endDate) {
|
|
427
|
+
let startOffset = startDate.getTimezoneOffset();
|
|
428
|
+
let endOffset = endDate.getTimezoneOffset();
|
|
429
|
+
if (startOffset === endOffset)
|
|
430
|
+
return new Date(endDate);
|
|
431
|
+
let postoffset = (startOffset - endOffset) * 60 * 1000;
|
|
432
|
+
return new Date(+endDate + postoffset);
|
|
433
|
+
}
|
|
434
|
+
export function addDuration(date, duration, exact = false) {
|
|
435
|
+
// Get the current offset of this date timezone
|
|
436
|
+
let newDate = new Date(date);
|
|
437
|
+
// Get the number of ticks forward
|
|
438
|
+
let { values } = new Duration(duration, exact).normalize();
|
|
439
|
+
// Apply any time changes that may have happened
|
|
440
|
+
for (const unit in values) {
|
|
441
|
+
setDateUnit(newDate, unit, Math.floor(values[unit]));
|
|
442
|
+
}
|
|
443
|
+
return fixOffset(new Date(date), newDate);
|
|
444
|
+
}
|
|
445
|
+
function setDateUnit(date, unit, value) {
|
|
446
|
+
switch (unit) {
|
|
447
|
+
case 'years':
|
|
448
|
+
date.setFullYear(date.getFullYear() + value);
|
|
449
|
+
break;
|
|
450
|
+
case 'quarters':
|
|
451
|
+
date.setMonth(date.getMonth() + value * 3);
|
|
452
|
+
break;
|
|
453
|
+
case 'months':
|
|
454
|
+
date.setMonth(date.getMonth() + value);
|
|
455
|
+
break;
|
|
456
|
+
case 'weeks':
|
|
457
|
+
date.setDate(date.getDate() + value * 7);
|
|
458
|
+
break;
|
|
459
|
+
case 'days':
|
|
460
|
+
date.setDate(date.getDate() + value);
|
|
461
|
+
break;
|
|
462
|
+
case 'hours':
|
|
463
|
+
date.setHours(date.getHours() + value);
|
|
464
|
+
break;
|
|
465
|
+
case 'minutes':
|
|
466
|
+
date.setMinutes(date.getMinutes() + value);
|
|
467
|
+
break;
|
|
468
|
+
case 'seconds':
|
|
469
|
+
date.setSeconds(date.getSeconds() + value);
|
|
470
|
+
break;
|
|
471
|
+
case 'milliseconds':
|
|
472
|
+
date.setMilliseconds(date.getMilliseconds() + value);
|
|
473
|
+
break;
|
|
474
|
+
default:
|
|
475
|
+
break;
|
|
476
|
+
}
|
|
477
|
+
return date;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Subtract the specified years, months, weeks, days, hours, minutes and seconds from the given date.
|
|
481
|
+
* @param date
|
|
482
|
+
* @param duration
|
|
483
|
+
* @param exact
|
|
484
|
+
* @returns
|
|
485
|
+
*/
|
|
486
|
+
export function subDuration(date, duration, exact = false) {
|
|
487
|
+
return addDuration(date, new Duration(duration, exact).negated(), exact);
|
|
488
|
+
}
|
|
489
|
+
const UNITS_SINGULAR = {
|
|
490
|
+
year: 'year',
|
|
491
|
+
years: 'year',
|
|
492
|
+
month: 'month',
|
|
493
|
+
months: 'month',
|
|
494
|
+
day: 'day',
|
|
495
|
+
days: 'day',
|
|
496
|
+
hour: 'hour',
|
|
497
|
+
hours: 'hour',
|
|
498
|
+
minute: 'minute',
|
|
499
|
+
minutes: 'minute',
|
|
500
|
+
quarter: 'quarter',
|
|
501
|
+
quarters: 'quarter',
|
|
502
|
+
second: 'second',
|
|
503
|
+
seconds: 'second',
|
|
504
|
+
millisecond: 'millisecond',
|
|
505
|
+
milliseconds: 'millisecond',
|
|
506
|
+
weekday: 'weekday',
|
|
507
|
+
weekdays: 'weekday',
|
|
508
|
+
weeknumber: 'weekNumber',
|
|
509
|
+
weeksnumber: 'weekNumber',
|
|
510
|
+
weeknumbers: 'weekNumber',
|
|
511
|
+
weekyear: 'weekYear',
|
|
512
|
+
weekyears: 'weekYear',
|
|
513
|
+
ordinal: 'ordinal'
|
|
514
|
+
};
|
|
515
|
+
function normalizeUnit(unit) {
|
|
516
|
+
const normalized = UNITS_SINGULAR[unit.toLowerCase()];
|
|
517
|
+
if (!normalized)
|
|
518
|
+
throw new ValueError(`Invalid unit ${unit}`);
|
|
519
|
+
return normalized;
|
|
520
|
+
}
|
|
521
|
+
function normalizeObject(obj, normalizer) {
|
|
522
|
+
const normalized = {};
|
|
523
|
+
for (const key of Object.keys(obj)) {
|
|
524
|
+
const value = obj[key];
|
|
525
|
+
if (value == null)
|
|
526
|
+
continue;
|
|
527
|
+
normalized[normalizer(key)] = asNumber(value);
|
|
528
|
+
}
|
|
529
|
+
return normalized;
|
|
530
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export declare type DateParts = {
|
|
2
|
+
year?: number;
|
|
3
|
+
month?: number;
|
|
4
|
+
day?: number;
|
|
5
|
+
weekday?: number;
|
|
6
|
+
hour?: number;
|
|
7
|
+
minute?: number;
|
|
8
|
+
second?: number;
|
|
9
|
+
millisecond?: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Returns the minimum (most distant past) of the given date values.
|
|
13
|
+
* @template T
|
|
14
|
+
* @param {Array<T>} dates
|
|
15
|
+
* @returns {T} The smallest date of `dates`
|
|
16
|
+
*/
|
|
17
|
+
export declare function minDate<T>(dates: Array<T>): T;
|
|
18
|
+
/**
|
|
19
|
+
* Returns the maximum (most distant future) of the given date values.
|
|
20
|
+
* @template T
|
|
21
|
+
* @param {Array<T>} dates
|
|
22
|
+
* @returns {T} The largest date of `dates`
|
|
23
|
+
*/
|
|
24
|
+
export declare function maxDate<T>(dates: Array<T>): T;
|
|
25
|
+
/**
|
|
26
|
+
* Returns `true` if the year is a leap year, otherwise `false`.
|
|
27
|
+
* @param year The date year
|
|
28
|
+
* @returns {boolean} `true` if is a leap year
|
|
29
|
+
*/
|
|
30
|
+
export declare function isLeapYear(year: number): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Get the number of days in the given year.
|
|
33
|
+
* @param year The date year
|
|
34
|
+
* @returns {number} Number of days in year
|
|
35
|
+
*/
|
|
36
|
+
export declare function daysInYear(year: number): 366 | 365;
|
|
37
|
+
/**
|
|
38
|
+
* Get the number of days in the given date's month and year.
|
|
39
|
+
* @param date The specified date
|
|
40
|
+
* @returns {number} Number of days in month
|
|
41
|
+
*/
|
|
42
|
+
export declare function daysInMonth(date: string | number | Date): number;
|
|
43
|
+
export declare function asNumber(value: any): number;
|
|
44
|
+
export declare function parseISODuration(s: any): any;
|
|
45
|
+
/**
|
|
46
|
+
* Returns the number of weeks in the specified year.
|
|
47
|
+
* @param year
|
|
48
|
+
* @param firstDayOfWeek
|
|
49
|
+
* @param firstDayOfYear
|
|
50
|
+
*/
|
|
51
|
+
export declare function weeksInYear(year: number, firstDayOfWeek?: number, firstDayOfYear?: number): number;
|
|
52
|
+
/**
|
|
53
|
+
* Returns the week of the year for the specified date
|
|
54
|
+
* @param year
|
|
55
|
+
* @param dayOfYear
|
|
56
|
+
* @param firstDayOfWeek
|
|
57
|
+
* @param firstDayOfYear
|
|
58
|
+
* @returns
|
|
59
|
+
*/
|
|
60
|
+
export declare function weekOfYear(date: string | number | Date, firstDayOfWeek?: number, firstDayOfYear?: number): {
|
|
61
|
+
week: any;
|
|
62
|
+
year: any;
|
|
63
|
+
};
|
|
64
|
+
export declare function isoWeeksInYear(year: any): number;
|
|
65
|
+
export declare function dayOfYear(input: string | number | Date): number;
|