atomic-fns 0.3.3 → 0.3.5
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 +18 -4
- package/core/collections/LRUCache.d.ts +22 -1
- package/core/collections/LRUCache.js +22 -1
- package/core/collections/LRUCache.ts +22 -1
- package/core/collections/SortedMap.d.ts +1 -1
- package/core/collections/SortedMap.js +1 -1
- package/core/collections/SortedMap.ts +1 -1
- package/core/collections/SortedSet.d.ts +6 -0
- package/core/collections/SortedSet.js +6 -0
- package/core/collections/SortedSet.ts +6 -0
- package/core/collections/SortedTree.d.ts +3 -3
- package/core/collections/SortedTree.js +3 -3
- package/core/collections/SortedTree.ts +3 -3
- package/core/collections/abc.d.ts +1 -1
- package/core/collections/abc.ts +1 -1
- package/core/collections/deque.d.ts +55 -48
- package/core/collections/deque.js +61 -53
- package/core/collections/deque.ts +63 -54
- package/core/collections/index.d.ts +2 -0
- package/core/collections/index.js +7 -5
- package/core/collections/index.ts +7 -5
- package/core/functools/index.d.ts +3 -2
- package/core/functools/index.ts +8 -3
- package/core/globals/index.d.ts +23 -4
- package/core/globals/index.js +29 -6
- package/core/globals/index.ts +40 -7
- package/core/i18n/date/format.d.ts +16 -0
- package/core/i18n/date/format.js +307 -0
- package/core/i18n/date/format.ts +343 -0
- package/core/i18n/date/index.d.ts +224 -0
- package/core/i18n/date/index.js +387 -0
- package/core/i18n/date/index.ts +471 -0
- package/core/i18n/date/test.html +67 -0
- package/core/i18n/index.d.ts +7 -0
- package/core/i18n/index.js +7 -0
- package/core/i18n/index.ts +8 -0
- package/core/index.d.ts +1 -0
- package/core/index.js +1 -0
- package/core/index.ts +1 -0
- package/core/operators/index.d.ts +1 -1
- package/core/operators/index.js +35 -5
- package/core/operators/index.ts +34 -6
- package/package.json +11 -11
- package/tests/globals.spec.ts +12 -12
- package/tsconfig.json +2 -1
- package/core/datetime/index.d.ts +0 -45
- package/core/datetime/index.js +0 -71
- package/core/datetime/index.ts +0 -128
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
import { isObject } from '../../globals/index.js'
|
|
2
|
+
import { format, getDate } from './format.js'
|
|
3
|
+
|
|
4
|
+
let globalOptions
|
|
5
|
+
|
|
6
|
+
const systemOptions = () => {
|
|
7
|
+
if (!globalOptions) globalOptions = Intl.DateTimeFormat().resolvedOptions()
|
|
8
|
+
return globalOptions
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const FORMAT_DEFAULT = 'YYYY-MM-DDTHH:mm:ssZ'
|
|
12
|
+
|
|
13
|
+
const INVALID_DATE_STRING = 'Invalid Date'
|
|
14
|
+
|
|
15
|
+
export type DateParts = {
|
|
16
|
+
year?: number
|
|
17
|
+
month?: number
|
|
18
|
+
day?: number
|
|
19
|
+
hour?: number
|
|
20
|
+
minute?: number
|
|
21
|
+
second?: number
|
|
22
|
+
millisecond?: number
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type DateLike = number | string | Date | DateParts
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 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 compatible with `strftime`.
|
|
29
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl Intl Apis}
|
|
30
|
+
* @see {@link https://strftime.org/ strftime format}
|
|
31
|
+
*/
|
|
32
|
+
export class IntlDate {
|
|
33
|
+
private self: Date
|
|
34
|
+
readonly year: number
|
|
35
|
+
readonly M: number
|
|
36
|
+
readonly day: number
|
|
37
|
+
readonly weekDay: number
|
|
38
|
+
readonly hour: number
|
|
39
|
+
readonly minute: number
|
|
40
|
+
readonly second: number
|
|
41
|
+
readonly millisecond: number
|
|
42
|
+
readonly locale: string
|
|
43
|
+
|
|
44
|
+
/** Returns the current UTC date and time. */
|
|
45
|
+
static UTC(obj: DateLike = {}) {
|
|
46
|
+
return new IntlDate(obj, { utc: true })
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Returns the current local date and time.*/
|
|
50
|
+
static now() {
|
|
51
|
+
return new IntlDate()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Creates a new `IntlDate` tied to the specified locale (default is system locale).
|
|
56
|
+
* **Note:** The allowed values for `month` start at 1, which is different from legacy `Date`
|
|
57
|
+
* @param {DateLike | IntlDate} obj The date value (default is now)
|
|
58
|
+
* @param {{locale?: string, utc?: boolean}} opts
|
|
59
|
+
* @returns
|
|
60
|
+
*/
|
|
61
|
+
constructor(obj?: DateLike | IntlDate, { locale, utc }: any = {}) {
|
|
62
|
+
// Set the default DateTime locale
|
|
63
|
+
this.locale = locale || systemOptions().locale
|
|
64
|
+
if (obj instanceof IntlDate) obj = obj.self
|
|
65
|
+
|
|
66
|
+
if (typeof obj === 'string' || typeof obj === 'number' || obj instanceof Date) {
|
|
67
|
+
this.self = getDate(obj, utc)
|
|
68
|
+
} else if (isObject(obj)) {
|
|
69
|
+
let { year, month, day, hour, minute, second, millisecond } = obj
|
|
70
|
+
// NOTE month is from 1-12, not from 0-11
|
|
71
|
+
if (typeof month === 'number') month -= 1
|
|
72
|
+
if (utc) {
|
|
73
|
+
// from UTC to current
|
|
74
|
+
this.self = new Date(Date.UTC(year!, month!, day, hour, minute, second, millisecond))
|
|
75
|
+
} else {
|
|
76
|
+
this.self = new Date(year!, month!, day, hour, minute, second, millisecond)
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
this.self = new Date()
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
this.year = this.self.getFullYear()
|
|
83
|
+
this.M = this.self.getMonth()
|
|
84
|
+
this.weekDay = this.self.getDay()
|
|
85
|
+
this.day = this.self.getDate()
|
|
86
|
+
this.hour = this.self.getHours()
|
|
87
|
+
this.minute = this.self.getMinutes()
|
|
88
|
+
this.second = this.self.getSeconds()
|
|
89
|
+
this.millisecond = this.self.getMilliseconds()
|
|
90
|
+
return this
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
isValid() {
|
|
94
|
+
return this.self.toString() !== INVALID_DATE_STRING
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Get the this date's month as a number from 1-12. */
|
|
98
|
+
get month() {
|
|
99
|
+
return this.M + 1
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Get the number of days in this date's month. */
|
|
103
|
+
daysInMonth() {
|
|
104
|
+
return daysInMonth(this.year, this.M)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Get the number of days in this date's year. */
|
|
108
|
+
daysInYear() {
|
|
109
|
+
return daysInYear(this.year)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Returns `true` if this date's year is a leap year, otherwise `false`. */
|
|
113
|
+
isLeapYear() {
|
|
114
|
+
return isLeapYear(this.year)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Gets the number of weeks according to locale in the current moment's year. */
|
|
118
|
+
weeksInYear() {
|
|
119
|
+
return weeksInYear(this.year)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Returns a localized string representation of this date.
|
|
124
|
+
* @param {Intl.DateTimeFormatOptions} opts The options to use for the format
|
|
125
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat Intl.DateTimeFormat()}
|
|
126
|
+
*/
|
|
127
|
+
toString(opts?: Intl.DateTimeFormatOptions) {
|
|
128
|
+
return this.self.toLocaleDateString(this.locale, opts)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Returns a localized string representation of this date, according to the given format string. Format codes use the same specification as C / Python's strftime().
|
|
133
|
+
* @param {string} str The format string to use
|
|
134
|
+
* @see {@link https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes Format Codes}
|
|
135
|
+
* @example
|
|
136
|
+
```js
|
|
137
|
+
new IntlDate().format('%m/%d/%y') // '10/31/2022'
|
|
138
|
+
```
|
|
139
|
+
*/
|
|
140
|
+
format(str: string) {
|
|
141
|
+
return format(str, this.self, this.locale)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Returns a new copy of the native `Date` object used by this instance.
|
|
146
|
+
* @returns {Date} A new `Date` object
|
|
147
|
+
*/
|
|
148
|
+
toDate() {
|
|
149
|
+
return new Date(this.isValid() ? this.self : NaN)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Returns the timestamp representing the UTC equivalent of this date.
|
|
154
|
+
* @returns {number} The UTC timestamp of this date.
|
|
155
|
+
*/
|
|
156
|
+
toUTC() {
|
|
157
|
+
return dateToUTC(this.self)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Returns the number of seconds since the Unix Epoch (January 1, 1970 UTC).
|
|
162
|
+
* @see {@link IntlDate.timestamp}
|
|
163
|
+
* @see {@link IntlDate.unix}
|
|
164
|
+
* @example
|
|
165
|
+
```js
|
|
166
|
+
new IntlDate().toSeconds() // 1318874398
|
|
167
|
+
```
|
|
168
|
+
*/
|
|
169
|
+
toSeconds() {
|
|
170
|
+
return Math.trunc(this.valueOf() / 1000)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Returns the number of seconds since the Unix Epoch (January 1, 1970 UTC).
|
|
175
|
+
* @see {@link IntlDate.toSeconds}
|
|
176
|
+
* @see {@link IntlDate.unix}
|
|
177
|
+
* @example
|
|
178
|
+
```js
|
|
179
|
+
new IntlDate().timestamp() // 1318874398
|
|
180
|
+
```
|
|
181
|
+
*/
|
|
182
|
+
timestamp() {
|
|
183
|
+
return this.toSeconds()
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Returns the number of seconds since the Unix Epoch (January 1, 1970 UTC).
|
|
188
|
+
* @see {@link IntlDate.toSeconds}
|
|
189
|
+
* @see {@link IntlDate.timestamp}
|
|
190
|
+
* @example
|
|
191
|
+
```js
|
|
192
|
+
new IntlDate().unix() // 1318874398
|
|
193
|
+
```
|
|
194
|
+
*/
|
|
195
|
+
unix() {
|
|
196
|
+
return this.toSeconds()
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** Formats a string to the ISO8601 standard.
|
|
200
|
+
* @example
|
|
201
|
+
```js
|
|
202
|
+
new IntlDate().toISOString() // '2022-10-31T22:44:30.652Z'
|
|
203
|
+
```
|
|
204
|
+
*/
|
|
205
|
+
toISOString() {
|
|
206
|
+
return this.self.toISOString()
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** Returns the date part formatted as ISO8601.
|
|
210
|
+
* @example
|
|
211
|
+
```js
|
|
212
|
+
new IntlDate().toISODate() // '2022-10-31'
|
|
213
|
+
```
|
|
214
|
+
*/
|
|
215
|
+
toISODate() {
|
|
216
|
+
return this.self.toISOString().slice(0, 10)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** Returns the time part formatted as ISO8601.
|
|
220
|
+
* @example
|
|
221
|
+
```js
|
|
222
|
+
new IntlDate().toISOTime() // 'T22:44:30.652Z'
|
|
223
|
+
```
|
|
224
|
+
*/
|
|
225
|
+
toISOTime() {
|
|
226
|
+
return this.self.toISOString().slice(11)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Returns an object containing year, month, day-of-month, hours, minutes, seconds, milliseconds.
|
|
231
|
+
* @returns {Object} An object like `{year, month, date, hours, minutes, seconds, ms}`
|
|
232
|
+
*/
|
|
233
|
+
toObject(): DateParts {
|
|
234
|
+
return {
|
|
235
|
+
year: this.year,
|
|
236
|
+
month: this.month,
|
|
237
|
+
day: this.day,
|
|
238
|
+
hour: this.hour,
|
|
239
|
+
minute: this.M,
|
|
240
|
+
second: this.second,
|
|
241
|
+
millisecond: this.millisecond
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** Returns the number of milliseconds since the Unix Epoch (January 1, 1970 UTC) */
|
|
246
|
+
valueOf() {
|
|
247
|
+
return this.isValid() ? this.self.getTime() : NaN
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** Returns the timezone string name */
|
|
251
|
+
zoneName() {
|
|
252
|
+
return this.format('%Z')
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/** Returns the timezone GMT offset name */
|
|
256
|
+
offset() {
|
|
257
|
+
return this.format('%z')
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Check if this date is before another date. The other value will be parsed as an `IntlDate` if not already so.
|
|
262
|
+
* @param {string | number | Object | Date | IntlDate} other Another date or date like object
|
|
263
|
+
* @returns {boolean} Returns `true` if this date is before the given value
|
|
264
|
+
*/
|
|
265
|
+
isBefore(other: DateLike | IntlDate) {
|
|
266
|
+
if (!this.isValid()) return false
|
|
267
|
+
|
|
268
|
+
if (other instanceof IntlDate) {
|
|
269
|
+
return this.valueOf() < other.valueOf()
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return this.valueOf() < new IntlDate(other).valueOf()
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* 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.
|
|
277
|
+
* @param {string | number | Object | Date | IntlDate} start The smaller date
|
|
278
|
+
* @param {string | number | Object | Date | IntlDate} stop The larger date
|
|
279
|
+
* @returns {boolean} Returns `true` if this date is greater than `start` and less than `stop`.
|
|
280
|
+
*/
|
|
281
|
+
isBetween(start: DateLike | IntlDate, stop: DateLike | IntlDate) {
|
|
282
|
+
return this.isAfter(start) && this.isBefore(stop)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Check if this date is after another date. The other value will be parsed as an `IntlDate` if not already so.
|
|
287
|
+
* @param {string | number | DateParts | Date | IntlDate} other Another date or date like object
|
|
288
|
+
* @returns {boolean} Returns `true` if this date is after the given value
|
|
289
|
+
*/
|
|
290
|
+
isAfter(other: DateLike | IntlDate) {
|
|
291
|
+
if (!this.isValid()) return false
|
|
292
|
+
|
|
293
|
+
if (other instanceof IntlDate) {
|
|
294
|
+
return this.valueOf() > other.valueOf()
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return this.valueOf() > new IntlDate(other).valueOf()
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Check if this date is the same as `other`.
|
|
302
|
+
* @param other Another date object
|
|
303
|
+
* @returns {boolean} Returns `true` if this date is the same as other
|
|
304
|
+
*/
|
|
305
|
+
isSame(other: Date | IntlDate) {
|
|
306
|
+
if (other instanceof IntlDate) {
|
|
307
|
+
return (
|
|
308
|
+
this.isValid() &&
|
|
309
|
+
other.isValid() &&
|
|
310
|
+
this.valueOf() === other.valueOf() &&
|
|
311
|
+
this.locale === other.locale
|
|
312
|
+
)
|
|
313
|
+
}
|
|
314
|
+
return this.valueOf() === other.valueOf()
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Returns the minimum (most distant past) of the given date values.
|
|
319
|
+
* @param {Array<Date | IntlDate>} dates
|
|
320
|
+
* @returns {Date | IntlDate} The smallest date of `dates`
|
|
321
|
+
* @see {@link minDate}
|
|
322
|
+
*/
|
|
323
|
+
static min(...dates: Array<Date | IntlDate>) {
|
|
324
|
+
return minDate(...dates)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Returns the maximum (most distant future) of the given date values.
|
|
329
|
+
* @param {Array<Date | IntlDate>} dates
|
|
330
|
+
* @returns {Date | IntlDate} The largest date of `dates`
|
|
331
|
+
* @see {@link maxDate}
|
|
332
|
+
*/
|
|
333
|
+
static max(...dates: Array<Date | IntlDate>) {
|
|
334
|
+
return maxDate(...dates)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
lt(other: Date | IntlDate) {
|
|
338
|
+
return this.isBefore(other)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
eq(other: Date | IntlDate) {
|
|
342
|
+
return this.isSame(other)
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
compare(other: Date | IntlDate) {
|
|
346
|
+
if (this.isBefore(other)) return -1
|
|
347
|
+
if (this.isAfter(other)) return 1
|
|
348
|
+
return 0
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// TODO:
|
|
352
|
+
// Display
|
|
353
|
+
// Time from now
|
|
354
|
+
// Time from X
|
|
355
|
+
// Difference
|
|
356
|
+
|
|
357
|
+
// Parsing
|
|
358
|
+
// Parse String + Date Format
|
|
359
|
+
// Parse String + Time Format
|
|
360
|
+
// Parse String + Format + locale
|
|
361
|
+
|
|
362
|
+
// Manipulate
|
|
363
|
+
// Add
|
|
364
|
+
// Subtract
|
|
365
|
+
// Start of Time
|
|
366
|
+
// End of Time
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Converts the given date to a UTC timestamp.
|
|
371
|
+
* @param {Date} date
|
|
372
|
+
* @returns {number} The milliseconds between the specified date and the UTC Epoch date.
|
|
373
|
+
*/
|
|
374
|
+
export function dateToUTC(date: Date) {
|
|
375
|
+
return Date.UTC(
|
|
376
|
+
date.getUTCFullYear(),
|
|
377
|
+
date.getUTCMonth(),
|
|
378
|
+
date.getUTCDate(),
|
|
379
|
+
date.getUTCHours(),
|
|
380
|
+
date.getUTCMinutes(),
|
|
381
|
+
date.getUTCSeconds(),
|
|
382
|
+
date.getUTCMilliseconds()
|
|
383
|
+
)
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Returns the minimum (most distant past) of the given date values.
|
|
388
|
+
* @param {Array<Date | IntlDate>} dates
|
|
389
|
+
* @returns {Date | IntlDate} The smallest date of `dates`
|
|
390
|
+
*/
|
|
391
|
+
export function minDate(...dates: Array<Date | IntlDate>) {
|
|
392
|
+
let result = dates[0]
|
|
393
|
+
for (let i = 1; i < dates.length; i++) {
|
|
394
|
+
if (dates[i].valueOf() < result.valueOf()) {
|
|
395
|
+
result = dates[i]
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return result
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Returns the maximum (most distant future) of the given date values.
|
|
403
|
+
* @param {Array<Date | IntlDate>} dates
|
|
404
|
+
* @returns {Date | IntlDate} The largest date of `dates`
|
|
405
|
+
*/
|
|
406
|
+
export function maxDate(...dates: Array<Date | IntlDate>) {
|
|
407
|
+
let result = dates[0]
|
|
408
|
+
for (let i = 1; i < dates.length; i++) {
|
|
409
|
+
if (dates[i].valueOf() > result.valueOf()) {
|
|
410
|
+
result = dates[i]
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return result
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Returns `true` if the year is a leap year, otherwise `false`.
|
|
418
|
+
* @param year The date year
|
|
419
|
+
* @returns {boolean} `true` if is a leap year
|
|
420
|
+
*/
|
|
421
|
+
export function isLeapYear(year: number) {
|
|
422
|
+
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Get the number of days in the given year.
|
|
427
|
+
* @param year The date year
|
|
428
|
+
* @returns {number} Number of days in year
|
|
429
|
+
*/
|
|
430
|
+
export function daysInYear(year: number) {
|
|
431
|
+
return isLeapYear(year) ? 366 : 365
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Get the number of days in the given month and year.
|
|
436
|
+
* @param year The date year
|
|
437
|
+
* @param month The date month
|
|
438
|
+
* @returns {number} Number of days in month
|
|
439
|
+
*/
|
|
440
|
+
export function daysInMonth(year: number, month: number) {
|
|
441
|
+
const modMonth = floorMod(month - 1, 12) + 1,
|
|
442
|
+
modYear = year + (month - modMonth) / 12
|
|
443
|
+
|
|
444
|
+
if (modMonth === 2) {
|
|
445
|
+
return isLeapYear(modYear) ? 29 : 28
|
|
446
|
+
} else {
|
|
447
|
+
return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][modMonth - 1]
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Gets the number of weeks according to locale in the current moment's year.
|
|
453
|
+
* @param {number} weekYear The the date year
|
|
454
|
+
* @returns {number}
|
|
455
|
+
*/
|
|
456
|
+
export function weeksInYear(weekYear: number) {
|
|
457
|
+
const p1 =
|
|
458
|
+
(weekYear +
|
|
459
|
+
Math.floor(weekYear / 4) -
|
|
460
|
+
Math.floor(weekYear / 100) +
|
|
461
|
+
Math.floor(weekYear / 400)) %
|
|
462
|
+
7,
|
|
463
|
+
last = weekYear - 1,
|
|
464
|
+
p2 = (last + Math.floor(last / 4) - Math.floor(last / 100) + Math.floor(last / 400)) % 7
|
|
465
|
+
return p1 === 4 || p2 === 3 ? 53 : 52
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// x % n but takes the sign of n instead of x
|
|
469
|
+
function floorMod(x: number, n: number) {
|
|
470
|
+
return x - n * Math.floor(x / n)
|
|
471
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script type="module">
|
|
2
|
+
import { IntlDate } from './index.js'
|
|
3
|
+
window.IntlDate = IntlDate
|
|
4
|
+
|
|
5
|
+
let d = new IntlDate('', { locale: 'en' })
|
|
6
|
+
console.log('toString', d.toString())
|
|
7
|
+
|
|
8
|
+
console.log('%A', d.format('%A'))
|
|
9
|
+
console.log('%a', d.format('%a'))
|
|
10
|
+
|
|
11
|
+
console.log('%%d', d.format('%d'))
|
|
12
|
+
console.log('%-d', d.format('%-d'))
|
|
13
|
+
|
|
14
|
+
console.log('%m', d.format('%m'))
|
|
15
|
+
console.log('%-m', d.format('%-m'))
|
|
16
|
+
console.log('%B', d.format('%B'))
|
|
17
|
+
console.log('%b', d.format('%b'))
|
|
18
|
+
console.log('%bb', d.format('%bb'))
|
|
19
|
+
|
|
20
|
+
console.log('%Y', d.format('%Y'))
|
|
21
|
+
console.log('%y', d.format('%y'))
|
|
22
|
+
|
|
23
|
+
console.log('%N', d.format('%N'))
|
|
24
|
+
console.log('%n', d.format('%n'))
|
|
25
|
+
|
|
26
|
+
console.log('%I', d.format('%I'))
|
|
27
|
+
console.log('%-I', d.format('%-I'))
|
|
28
|
+
console.log('%H', d.format('%H'))
|
|
29
|
+
console.log('%-H', d.format('%-H'))
|
|
30
|
+
console.log('%K', d.format('%K'))
|
|
31
|
+
console.log('%k', d.format('%k'))
|
|
32
|
+
|
|
33
|
+
console.log('%M', d.format('%M'))
|
|
34
|
+
console.log('%-M', d.format('%-M'))
|
|
35
|
+
|
|
36
|
+
console.log('%S', d.format('%S'))
|
|
37
|
+
console.log('%-S', d.format('%-S'))
|
|
38
|
+
|
|
39
|
+
console.log('%P', d.format('%P'))
|
|
40
|
+
console.log('%p', d.format('%p'))
|
|
41
|
+
console.log('%pp', d.format('%pp'))
|
|
42
|
+
|
|
43
|
+
console.log('%Z', d.format('%Z'))
|
|
44
|
+
console.log('%-Z', d.format('%-Z'))
|
|
45
|
+
console.log('%z', d.format('%z'))
|
|
46
|
+
console.log('%-z', d.format('%-z'))
|
|
47
|
+
console.log('%ZZ', d.format('%ZZ'))
|
|
48
|
+
console.log('%-ZZ', d.format('%-ZZ'))
|
|
49
|
+
|
|
50
|
+
console.log(d.format('%A, %d/%m/%y'))
|
|
51
|
+
console.log(d.format('%y-%m-%d, %A'))
|
|
52
|
+
console.log(d.format('%y %B %d %A %I:%M:%S %P'))
|
|
53
|
+
console.log(d.format('%y %B %d %A %-I:%-M:%-S %p'))
|
|
54
|
+
console.log(d.format('%y %b %d %a %H:%M:%S'))
|
|
55
|
+
console.log(d.format('%y %b %d %a %-H:%-M:%S'))
|
|
56
|
+
console.log(d.format('%y %b %d %a %K:%M:%S %P')) // %p shows on 12h clock
|
|
57
|
+
console.log(d.format('%y %b %d %a %k:%-M:%S %p')) // %p No effect on 24h
|
|
58
|
+
console.log(d.format('%a, %b %d, %y %N, %K:%M:%S %P'))
|
|
59
|
+
console.log(d.format('%a, %b %d, %y %n, %K:%M:%S %P'))
|
|
60
|
+
console.log(d.format('%a, %b %d, %y %k:%M:%S %P')) // %p No effect on 24h
|
|
61
|
+
console.log(d.format('%y %b %d %a %-I:%M:%S %P %Z'))
|
|
62
|
+
console.log(d.format('%y %b %d %a %-I:%M:%S %P %-Z'))
|
|
63
|
+
console.log(d.format('%y %b %d %a %-I:%M:%S %P %z'))
|
|
64
|
+
console.log(d.format('%y %b %d %a %-I:%M:%S %P %-z'))
|
|
65
|
+
console.log(d.format('%y %b %d %a %-I:%M:%S %P %ZZ'))
|
|
66
|
+
console.log(d.format('%a, %b %d, %y %-I:%M:%S %-ZZ'))
|
|
67
|
+
</script>
|
package/core/index.d.ts
CHANGED
package/core/index.js
CHANGED
package/core/index.ts
CHANGED
|
@@ -145,4 +145,4 @@ export declare function shallowEqual(obj: any, other: any): boolean;
|
|
|
145
145
|
* @param other
|
|
146
146
|
* @returns `true` if the objects are considered equal.
|
|
147
147
|
*/
|
|
148
|
-
export declare function deepEqual(obj: any, other: any, checker?: typeof eq): boolean;
|
|
148
|
+
export declare function deepEqual(obj: any, other: any, checker?: typeof eq, seen?: WeakSet<object>): boolean;
|
package/core/operators/index.js
CHANGED
|
@@ -57,7 +57,7 @@ export function compare(x, y) {
|
|
|
57
57
|
* @returns {boolean} `true` if `x` and `y` are equal or `false` otherwise.
|
|
58
58
|
*/
|
|
59
59
|
export function eq(x, y) {
|
|
60
|
-
return x
|
|
60
|
+
return Object.is(x, y) || call(x, 'eq', y) != null;
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
63
|
* Compares two values to check if `x` is strictly less than `y`. If `x` is an object with a `lt` method, it returns `x.lt(y)`.
|
|
@@ -237,11 +237,15 @@ export function shallowEqual(obj, other) {
|
|
|
237
237
|
* @param other
|
|
238
238
|
* @returns `true` if the objects are considered equal.
|
|
239
239
|
*/
|
|
240
|
-
export function deepEqual(obj, other, checker = eq) {
|
|
240
|
+
export function deepEqual(obj, other, checker = eq, seen = new WeakSet()) {
|
|
241
241
|
if (checker(obj, other))
|
|
242
242
|
return true;
|
|
243
243
|
if (!obj || !other)
|
|
244
244
|
return false;
|
|
245
|
+
if (obj.prototype !== other.prototype)
|
|
246
|
+
return false;
|
|
247
|
+
if (seen.has(obj) && seen.has(other))
|
|
248
|
+
return false;
|
|
245
249
|
if (Array.isArray(obj)) {
|
|
246
250
|
// compare the arrays
|
|
247
251
|
if (obj.length !== other.length)
|
|
@@ -253,15 +257,41 @@ export function deepEqual(obj, other, checker = eq) {
|
|
|
253
257
|
}
|
|
254
258
|
return true;
|
|
255
259
|
}
|
|
256
|
-
|
|
257
|
-
|
|
260
|
+
if (obj instanceof Set) {
|
|
261
|
+
if (obj.size !== other.size)
|
|
262
|
+
return false;
|
|
263
|
+
for (const value of obj.values()) {
|
|
264
|
+
if (!other.has(value))
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
if (obj instanceof Map) {
|
|
270
|
+
// compare keys and values
|
|
271
|
+
if (obj.size !== other.size)
|
|
272
|
+
return false;
|
|
273
|
+
seen.add(obj);
|
|
274
|
+
seen.add(other);
|
|
275
|
+
for (const key of obj.keys()) {
|
|
276
|
+
if (!other.has(key))
|
|
277
|
+
return false;
|
|
278
|
+
if (!deepEqual(obj.get(key), other.get(key), checker, seen)) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
if (isObject(obj)) {
|
|
285
|
+
// compare the object own enumerable keys
|
|
258
286
|
const objKeys = Object.keys(obj);
|
|
259
287
|
const otherKeys = Object.keys(other);
|
|
260
288
|
if (objKeys.length !== otherKeys.length)
|
|
261
289
|
return false;
|
|
290
|
+
seen.add(obj);
|
|
291
|
+
seen.add(other);
|
|
262
292
|
for (const key of objKeys) {
|
|
263
293
|
if (!Object.prototype.hasOwnProperty.call(other, key) ||
|
|
264
|
-
!deepEqual(obj[key], other[key], checker)) {
|
|
294
|
+
!deepEqual(obj[key], other[key], checker, seen)) {
|
|
265
295
|
return false;
|
|
266
296
|
}
|
|
267
297
|
}
|