@fr0st/datetime 5.0.0
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/LICENSE +21 -0
- package/README.md +962 -0
- package/package.json +51 -0
- package/src/date-time.js +213 -0
- package/src/factory.js +73 -0
- package/src/formatter/format.js +104 -0
- package/src/formatter/locales.js +2 -0
- package/src/formatter/parse.js +62 -0
- package/src/formatter/tokens.js +660 -0
- package/src/formatter/utility.js +96 -0
- package/src/formatter/values.js +142 -0
- package/src/helpers.js +272 -0
- package/src/index.js +89 -0
- package/src/prototype/attributes-get.js +163 -0
- package/src/prototype/attributes-set.js +281 -0
- package/src/prototype/manipulate.js +96 -0
- package/src/prototype/output.js +89 -0
- package/src/prototype/utility.js +346 -0
- package/src/static/create.js +222 -0
- package/src/static/utility.js +103 -0
- package/src/vars.js +46 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import DateTime from './../date-time.js';
|
|
2
|
+
import { getRelativeFormatter } from './../factory.js';
|
|
3
|
+
import { compensateDiff, getBiggestDiff } from './../helpers.js';
|
|
4
|
+
import { formatDay, formatDayPeriod, formatEra, formatMonth, formatOffset, formatTimeZoneName } from './../formatter/format.js';
|
|
5
|
+
import { minimumDays } from './../formatter/utility.js';
|
|
6
|
+
import { daysInMonth as _daysInMonth, daysInYear as _daysInYear, isLeapYear as _isLeapYear } from './../static/utility.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* DateTime Utility
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get the name of the day of the week in current timeZone.
|
|
14
|
+
* @param {string} [type=long] The type of day name to return.
|
|
15
|
+
* @return {string} The name of the day of the week.
|
|
16
|
+
*/
|
|
17
|
+
export function dayName(type = 'long') {
|
|
18
|
+
return formatDay(this.getLocale(), this.getDay(), type);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get the day period in current timeZone.
|
|
23
|
+
* @param {string} [type=long] The type of day period to return.
|
|
24
|
+
* @return {string} The day period.
|
|
25
|
+
*/
|
|
26
|
+
export function dayPeriod(type = 'long') {
|
|
27
|
+
return formatDayPeriod(
|
|
28
|
+
this.getLocale(),
|
|
29
|
+
this.getHours() < 12 ?
|
|
30
|
+
0 :
|
|
31
|
+
1,
|
|
32
|
+
type,
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get the number of days in the current month.
|
|
38
|
+
* @return {number} The number of days in the current month.
|
|
39
|
+
*/
|
|
40
|
+
export function daysInMonth() {
|
|
41
|
+
return _daysInMonth(
|
|
42
|
+
this.getYear(),
|
|
43
|
+
this.getMonth(),
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get the number of days in the current year.
|
|
49
|
+
* @return {number} The number of days in the current year.
|
|
50
|
+
*/
|
|
51
|
+
export function daysInYear() {
|
|
52
|
+
return _daysInYear(
|
|
53
|
+
this.getYear(),
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get the difference between this and another Date.
|
|
59
|
+
* @param {DateTime} [other] The date to compare to.
|
|
60
|
+
* @param {string} [timeUnit] The unit of time.
|
|
61
|
+
* @param {Boolean} [relative=true] Whether to use the relative difference.
|
|
62
|
+
* @return {number} The difference.
|
|
63
|
+
*/
|
|
64
|
+
export function diff(other, timeUnit, relative = true) {
|
|
65
|
+
if (!other) {
|
|
66
|
+
other = new this.constructor;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!timeUnit) {
|
|
70
|
+
return this - other;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (timeUnit) {
|
|
74
|
+
timeUnit = timeUnit.toLowerCase();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
other = other.setTimeZone(this.getTimeZone());
|
|
78
|
+
|
|
79
|
+
switch (timeUnit) {
|
|
80
|
+
case 'year':
|
|
81
|
+
case 'years':
|
|
82
|
+
const yearDiff = this.getYear() - other.getYear();
|
|
83
|
+
return compensateDiff(
|
|
84
|
+
this,
|
|
85
|
+
other.setYear(
|
|
86
|
+
this.getYear(),
|
|
87
|
+
),
|
|
88
|
+
yearDiff,
|
|
89
|
+
!relative,
|
|
90
|
+
-1,
|
|
91
|
+
);
|
|
92
|
+
case 'month':
|
|
93
|
+
case 'months':
|
|
94
|
+
const monthDiff = (this.getYear() - other.getYear()) *
|
|
95
|
+
12 +
|
|
96
|
+
this.getMonth() -
|
|
97
|
+
other.getMonth();
|
|
98
|
+
return compensateDiff(
|
|
99
|
+
this,
|
|
100
|
+
other.setYear(
|
|
101
|
+
this.getYear(),
|
|
102
|
+
this.getMonth(),
|
|
103
|
+
),
|
|
104
|
+
monthDiff,
|
|
105
|
+
!relative,
|
|
106
|
+
-1,
|
|
107
|
+
);
|
|
108
|
+
case 'week':
|
|
109
|
+
case 'weeks':
|
|
110
|
+
const weekDiff = (this - other) / 604800000;
|
|
111
|
+
return compensateDiff(
|
|
112
|
+
this,
|
|
113
|
+
other.setWeekYear(
|
|
114
|
+
this.getWeekYear(),
|
|
115
|
+
this.getWeek(),
|
|
116
|
+
),
|
|
117
|
+
weekDiff,
|
|
118
|
+
relative,
|
|
119
|
+
);
|
|
120
|
+
case 'day':
|
|
121
|
+
case 'days':
|
|
122
|
+
const dayDiff = (this - other) / 86400000;
|
|
123
|
+
return compensateDiff(
|
|
124
|
+
this,
|
|
125
|
+
other.setYear(
|
|
126
|
+
this.getYear(),
|
|
127
|
+
this.getMonth(),
|
|
128
|
+
this.getDate(),
|
|
129
|
+
),
|
|
130
|
+
dayDiff,
|
|
131
|
+
relative,
|
|
132
|
+
);
|
|
133
|
+
case 'hour':
|
|
134
|
+
case 'hours':
|
|
135
|
+
const hourDiff = (this - other) / 3600000;
|
|
136
|
+
return compensateDiff(
|
|
137
|
+
this,
|
|
138
|
+
other.setYear(
|
|
139
|
+
this.getYear(),
|
|
140
|
+
this.getMonth(),
|
|
141
|
+
this.getDate(),
|
|
142
|
+
).setHours(
|
|
143
|
+
this.getHours(),
|
|
144
|
+
),
|
|
145
|
+
hourDiff,
|
|
146
|
+
relative,
|
|
147
|
+
);
|
|
148
|
+
case 'minute':
|
|
149
|
+
case 'minutes':
|
|
150
|
+
const minuteDiff = (this - other) / 60000;
|
|
151
|
+
return compensateDiff(
|
|
152
|
+
this,
|
|
153
|
+
other.setYear(
|
|
154
|
+
this.getYear(),
|
|
155
|
+
this.getMonth(),
|
|
156
|
+
this.getDate(),
|
|
157
|
+
).setHours(
|
|
158
|
+
this.getHours(),
|
|
159
|
+
this.getMinutes(),
|
|
160
|
+
),
|
|
161
|
+
minuteDiff,
|
|
162
|
+
relative,
|
|
163
|
+
);
|
|
164
|
+
case 'second':
|
|
165
|
+
case 'seconds':
|
|
166
|
+
const secondDiff = (this - other) / 1000;
|
|
167
|
+
return compensateDiff(
|
|
168
|
+
this,
|
|
169
|
+
other.setYear(
|
|
170
|
+
this.getYear(),
|
|
171
|
+
this.getMonth(),
|
|
172
|
+
this.getDate(),
|
|
173
|
+
).setHours(
|
|
174
|
+
this.getHours(),
|
|
175
|
+
this.getMinutes(),
|
|
176
|
+
this.getSeconds(),
|
|
177
|
+
),
|
|
178
|
+
secondDiff,
|
|
179
|
+
relative,
|
|
180
|
+
);
|
|
181
|
+
default:
|
|
182
|
+
throw new Error('Invalid time unit supplied');
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Get the era in current timeZone.
|
|
188
|
+
* @param {string} [type=long] The type of era to return.
|
|
189
|
+
* @return {string} The era.
|
|
190
|
+
*/
|
|
191
|
+
export function era(type = 'long') {
|
|
192
|
+
return formatEra(
|
|
193
|
+
this.getLocale(),
|
|
194
|
+
this.getYear() < 0 ?
|
|
195
|
+
0 :
|
|
196
|
+
1,
|
|
197
|
+
type,
|
|
198
|
+
);
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Get the difference between this and another Date in human readable form.
|
|
203
|
+
* @param {DateTime} [other] The date to compare to.
|
|
204
|
+
* @param {string} [timeUnit] The unit of time.
|
|
205
|
+
* @return {string} The difference in human readable form.
|
|
206
|
+
*/
|
|
207
|
+
export function humanDiff(other, timeUnit) {
|
|
208
|
+
const relativeFormatter = getRelativeFormatter(this.getLocale());
|
|
209
|
+
|
|
210
|
+
if (!relativeFormatter) {
|
|
211
|
+
throw new Error('RelativeTimeFormat not supported');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (!other) {
|
|
215
|
+
other = new this.constructor;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
let amount;
|
|
219
|
+
if (timeUnit) {
|
|
220
|
+
amount = this.diff(other, timeUnit);
|
|
221
|
+
} else {
|
|
222
|
+
[amount, timeUnit] = getBiggestDiff(this, other);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return relativeFormatter.format(amount, timeUnit);
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Determine whether this DateTime is after another date (optionally to a granularity).
|
|
230
|
+
* @param {DateTime} [other] The date to compare to.
|
|
231
|
+
* @param {string} [granularity] The level of granularity to use for comparison.
|
|
232
|
+
* @return {Boolean} TRUE if this DateTime is after the other date, otherwise FALSE.
|
|
233
|
+
*/
|
|
234
|
+
export function isAfter(other, granularity) {
|
|
235
|
+
return this.diff(other, granularity) > 0;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Determine whether this DateTime is before another date (optionally to a granularity).
|
|
240
|
+
* @param {DateTime} [other] The date to compare to.
|
|
241
|
+
* @param {string} [granularity] The level of granularity to use for comparison.
|
|
242
|
+
* @return {Boolean} TRUE if this DateTime is before the other date, otherwise FALSE.
|
|
243
|
+
*/
|
|
244
|
+
export function isBefore(other, granularity) {
|
|
245
|
+
return this.diff(other, granularity) < 0;
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Determine whether this DateTime is between two other dates (optionally to a granularity).
|
|
250
|
+
* @param {DateTime} [start] The first date to compare to.
|
|
251
|
+
* @param {DateTime} [end] The second date to compare to.
|
|
252
|
+
* @param {string} [granularity] The level of granularity to use for comparison.
|
|
253
|
+
* @return {Boolean} TRUE if this DateTime is between the other dates, otherwise FALSE.
|
|
254
|
+
*/
|
|
255
|
+
export function isBetween(start, end, granularity) {
|
|
256
|
+
return this.diff(start, granularity) > 0 && this.diff(end, granularity) < 0;
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Return true if the DateTime is in daylight savings.
|
|
261
|
+
* @return {Boolean} TRUE if the current time is in daylight savings, otherwise FALSE.
|
|
262
|
+
*/
|
|
263
|
+
export function isDST() {
|
|
264
|
+
if (!this.isDynamicTimeZone()) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const year = this.getYear();
|
|
269
|
+
const dateA = DateTime.fromArray([year, 1, 1], {
|
|
270
|
+
timeZone: this.getTimeZone(),
|
|
271
|
+
});
|
|
272
|
+
const dateB = DateTime.fromArray([year, 6, 1], {
|
|
273
|
+
timeZone: this.getTimeZone(),
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
return this.getTimeZoneOffset() < Math.max(dateA.getTimeZoneOffset(), dateB.getTimeZoneOffset());
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Return true if the year is a leap year.
|
|
281
|
+
* @return {Boolean} TRUE if the current year is a leap year, otherwise FALSE.
|
|
282
|
+
*/
|
|
283
|
+
export function isLeapYear() {
|
|
284
|
+
return _isLeapYear(
|
|
285
|
+
this.getYear(),
|
|
286
|
+
);
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Determine whether this DateTime is the same as another date (optionally to a granularity).
|
|
291
|
+
* @param {DateTime} [other] The date to compare to.
|
|
292
|
+
* @param {string} [granularity] The level of granularity to use for comparison.
|
|
293
|
+
* @return {Boolean} TRUE if this DateTime is the same as the other date, otherwise FALSE.
|
|
294
|
+
*/
|
|
295
|
+
export function isSame(other, granularity) {
|
|
296
|
+
return this.diff(other, granularity) === 0;
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Determine whether this DateTime is the same or after another date (optionally to a granularity).
|
|
301
|
+
* @param {DateTime} [other] The date to compare to.
|
|
302
|
+
* @param {string} [granularity] The level of granularity to use for comparison.
|
|
303
|
+
* @return {Boolean} TRUE if this DateTime is the same or after the other date, otherwise FALSE.
|
|
304
|
+
*/
|
|
305
|
+
export function isSameOrAfter(other, granularity) {
|
|
306
|
+
return this.diff(other, granularity) >= 0;
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Determine whether this DateTime is the same or before another date.
|
|
311
|
+
* @param {DateTime} other The date to compare to.
|
|
312
|
+
* @param {string} [granularity] The level of granularity to use for comparison.
|
|
313
|
+
* @return {Boolean} TRUE if this DateTime is the same or before the other date, otherwise FALSE.
|
|
314
|
+
*/
|
|
315
|
+
export function isSameOrBefore(other, granularity) {
|
|
316
|
+
return this.diff(other, granularity) <= 0;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Get the name of the month in current timeZone.
|
|
321
|
+
* @param {string} [type=long] The type of month name to return.
|
|
322
|
+
* @return {string} The name of the month.
|
|
323
|
+
*/
|
|
324
|
+
export function monthName(type = 'long') {
|
|
325
|
+
return formatMonth(this.getLocale(), this.getMonth(), type);
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Get the name of the current timeZone.
|
|
330
|
+
* @param {string} [type=long] The formatting type.
|
|
331
|
+
* @return {string} The name of the time zone.
|
|
332
|
+
*/
|
|
333
|
+
export function timeZoneName(type = 'long') {
|
|
334
|
+
return this.isDynamicTimeZone() ?
|
|
335
|
+
formatTimeZoneName(this.getLocale(), this.getTime(), this.getTimeZone(), type) :
|
|
336
|
+
'GMT' + formatOffset(this.getTimeZoneOffset(), true, type === 'short');
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Get the number of weeks in the current year.
|
|
341
|
+
* @return {number} The number of weeks in the current year.
|
|
342
|
+
*/
|
|
343
|
+
export function weeksInYear() {
|
|
344
|
+
const minDays = minimumDays(this.getLocale());
|
|
345
|
+
return this.setMonth(12, 24 + minDays).getWeek();
|
|
346
|
+
};
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import DateTime from './../date-time.js';
|
|
2
|
+
import { parseCompare, parseFactory } from './../helpers.js';
|
|
3
|
+
import { config, formats, formatTokenRegExp, parseOrderKeys } from './../vars.js';
|
|
4
|
+
import tokens from './../formatter/tokens.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* DateTime (Static) Creation
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Create a new DateTime from an array.
|
|
12
|
+
* @param {number[]} dateArray The date to parse.
|
|
13
|
+
* @param {object} [options] Options for the new DateTime.
|
|
14
|
+
* @param {string} [options.timeZone] The timeZone to use.
|
|
15
|
+
* @param {string} [options.locale] The locale to use.
|
|
16
|
+
* @return {DateTime} A new DateTime object.
|
|
17
|
+
*/
|
|
18
|
+
export function fromArray(dateArray, options = {}) {
|
|
19
|
+
const dateValues = dateArray.slice(0, 3);
|
|
20
|
+
const timeValues = dateArray.slice(3);
|
|
21
|
+
|
|
22
|
+
if (dateValues.length < 3) {
|
|
23
|
+
dateValues.push(...new Array(3 - dateValues.length).fill(1));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (timeValues.length < 4) {
|
|
27
|
+
timeValues.push(...new Array(4 - timeValues.length).fill(0));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return new DateTime(null, options)
|
|
31
|
+
.setTimestamp(0)
|
|
32
|
+
.setYear(...dateValues)
|
|
33
|
+
.setHours(...timeValues);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Create a new DateTime from a Date.
|
|
38
|
+
* @param {Date} date The date.
|
|
39
|
+
* @param {object} [options] Options for the new DateTime.
|
|
40
|
+
* @param {string} [options.timeZone] The timeZone to use.
|
|
41
|
+
* @param {string} [options.locale] The locale to use.
|
|
42
|
+
* @return {DateTime} A new DateTime object.
|
|
43
|
+
*/
|
|
44
|
+
export function fromDate(date, options = {}) {
|
|
45
|
+
return new DateTime(date.getTime(), options);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Create a new DateTime from a format string.
|
|
50
|
+
* @param {string} formatString The format string.
|
|
51
|
+
* @param {string} dateString The date string.
|
|
52
|
+
* @param {object} [options] Options for the new DateTime.
|
|
53
|
+
* @param {string} [options.timeZone] The timeZone to use.
|
|
54
|
+
* @param {string} [options.locale] The locale to use.
|
|
55
|
+
* @return {DateTime} A new DateTime object.
|
|
56
|
+
*/
|
|
57
|
+
export function fromFormat(formatString, dateString, options = {}) {
|
|
58
|
+
if (!('locale' in options)) {
|
|
59
|
+
options.locale = config.defaultLocale;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const values = [];
|
|
63
|
+
|
|
64
|
+
let match;
|
|
65
|
+
while (formatString && (match = formatString.match(formatTokenRegExp))) {
|
|
66
|
+
const token = match[1];
|
|
67
|
+
const position = match.index;
|
|
68
|
+
const length = match[0].length;
|
|
69
|
+
|
|
70
|
+
if (position) {
|
|
71
|
+
const formatTest = formatString.substring(0, position);
|
|
72
|
+
parseCompare(formatTest, dateString);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
formatString = formatString.substring(position + length);
|
|
76
|
+
dateString = dateString.substring(position);
|
|
77
|
+
|
|
78
|
+
if (!token) {
|
|
79
|
+
const literal = match[0].slice(1, -1);
|
|
80
|
+
parseCompare(literal || `'`, dateString);
|
|
81
|
+
dateString = dateString.substring(literal.length);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!(token in tokens)) {
|
|
86
|
+
throw new Error(`Invalid token in DateTime format: ${token}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const regExp = tokens[token].regex(options.locale, length);
|
|
90
|
+
const matchedValue = dateString.match(new RegExp(`^${regExp}`));
|
|
91
|
+
|
|
92
|
+
if (!matchedValue) {
|
|
93
|
+
throw new Error(`Unmatched token in DateTime string: ${token}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const literal = matchedValue[0];
|
|
97
|
+
const value = tokens[token].input(options.locale, literal, length);
|
|
98
|
+
|
|
99
|
+
if (value !== null) {
|
|
100
|
+
const key = tokens[token].key;
|
|
101
|
+
values.push({ key, value, literal, token, length });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
dateString = dateString.substring(literal.length);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (formatString) {
|
|
108
|
+
parseCompare(formatString, dateString);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!('timeZone' in options)) {
|
|
112
|
+
options.timeZone = config.defaultTimeZone;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
let timeZone = options.timeZone;
|
|
116
|
+
for (const { key, value } of values) {
|
|
117
|
+
if (key !== 'timeZone') {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
timeZone = value;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let datetime = this.fromTimestamp(0, {
|
|
125
|
+
locale: options.locale,
|
|
126
|
+
}).setYear(1).setTimeZone(timeZone);
|
|
127
|
+
|
|
128
|
+
const methods = parseFactory();
|
|
129
|
+
|
|
130
|
+
const testValues = [];
|
|
131
|
+
|
|
132
|
+
for (const subKeys of parseOrderKeys) {
|
|
133
|
+
for (const subKey of subKeys) {
|
|
134
|
+
if (subKey === 'era' && !values.find((data) => data.key === 'year')) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
for (const data of values) {
|
|
139
|
+
const { key, value, literal, token, length } = data;
|
|
140
|
+
|
|
141
|
+
if (key !== subKey) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// skip narrow month and day names if output already matches
|
|
146
|
+
if (length === 5 && ['M', 'L', 'E', 'e', 'c'].includes(token)) {
|
|
147
|
+
const fullToken = token.repeat(length);
|
|
148
|
+
if (datetime.format(fullToken) === literal) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
datetime = methods[key].set(datetime, value);
|
|
154
|
+
testValues.push(data);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
let isValid = true;
|
|
160
|
+
for (const { key, value } of testValues) {
|
|
161
|
+
if (key in methods && methods[key].get(datetime) !== value) {
|
|
162
|
+
isValid = false;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (options.timeZone !== timeZone) {
|
|
168
|
+
datetime = datetime.setTimeZone(options.timeZone);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
datetime.isValid = isValid;
|
|
172
|
+
|
|
173
|
+
return datetime;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Create a new DateTime from an ISO format string.
|
|
178
|
+
* @param {string} dateString The date string.
|
|
179
|
+
* @param {object} [options] Options for the new DateTime.
|
|
180
|
+
* @param {string} [options.timeZone] The timeZone to use.
|
|
181
|
+
* @param {string} [options.locale] The locale to use.
|
|
182
|
+
* @return {DateTime} A new DateTime object.
|
|
183
|
+
*/
|
|
184
|
+
export function fromISOString(dateString, options = {}) {
|
|
185
|
+
let date = this.fromFormat(formats.rfc3339_extended, dateString, {
|
|
186
|
+
locale: 'en',
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
if ('timeZone' in options) {
|
|
190
|
+
date = date.setTimeZone(options.timeZone);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if ('locale' in options) {
|
|
194
|
+
date = date.setLocale(options.locale);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return date;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Create a new DateTime from a timestamp.
|
|
202
|
+
* @param {number} timestamp The timestamp.
|
|
203
|
+
* @param {object} [options] Options for the new DateTime.
|
|
204
|
+
* @param {string} [options.timeZone] The timeZone to use.
|
|
205
|
+
* @param {string} [options.locale] The locale to use.
|
|
206
|
+
* @return {DateTime} A new DateTime object.
|
|
207
|
+
*/
|
|
208
|
+
export function fromTimestamp(timestamp, options = {}) {
|
|
209
|
+
return new DateTime(null, options)
|
|
210
|
+
.setTimestamp(timestamp);
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Create a new DateTime for the current time.
|
|
215
|
+
* @param {object} [options] Options for the new DateTime.
|
|
216
|
+
* @param {string} [options.timeZone] The timeZone to use.
|
|
217
|
+
* @param {string} [options.locale] The locale to use.
|
|
218
|
+
* @return {DateTime} A new DateTime object.
|
|
219
|
+
*/
|
|
220
|
+
export function now(options = {}) {
|
|
221
|
+
return new DateTime(null, options);
|
|
222
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { config, monthDays } from './../vars.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* DateTime (Static) Utility
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get the day of the year for a year, month and date.
|
|
9
|
+
* @param {number} year The year.
|
|
10
|
+
* @param {number} month The month. (1, 12)
|
|
11
|
+
* @param {number} date The date.
|
|
12
|
+
* @return {number} The day of the year. (1, 366)
|
|
13
|
+
*/
|
|
14
|
+
export function dayOfYear(year, month, date) {
|
|
15
|
+
return new Array(month - 1)
|
|
16
|
+
.fill()
|
|
17
|
+
.reduce(
|
|
18
|
+
(d, _, i) =>
|
|
19
|
+
d + daysInMonth(year, i + 1),
|
|
20
|
+
date,
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get the number of days in a month, from a year and month.
|
|
26
|
+
* @param {number} year The year.
|
|
27
|
+
* @param {number} month The month. (1, 12)
|
|
28
|
+
* @return {number} The number of days in the month.
|
|
29
|
+
*/
|
|
30
|
+
export function daysInMonth(year, month) {
|
|
31
|
+
const date = new Date(Date.UTC(year, month - 1));
|
|
32
|
+
month = date.getUTCMonth();
|
|
33
|
+
|
|
34
|
+
return monthDays[month] +
|
|
35
|
+
(
|
|
36
|
+
month == 1 && isLeapYear(
|
|
37
|
+
date.getUTCFullYear(),
|
|
38
|
+
) ?
|
|
39
|
+
1 :
|
|
40
|
+
0
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the number of days in a year.
|
|
46
|
+
* @param {number} year The year.
|
|
47
|
+
* @return {number} The number of days in the year.
|
|
48
|
+
*/
|
|
49
|
+
export function daysInYear(year) {
|
|
50
|
+
return !isLeapYear(year) ?
|
|
51
|
+
365 :
|
|
52
|
+
366;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get the default locale.
|
|
57
|
+
* @return {string} The locale.
|
|
58
|
+
*/
|
|
59
|
+
export function getDefaultLocale() {
|
|
60
|
+
return config.defaultLocale;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get the default timeZone.
|
|
65
|
+
* @return {string} The name of the timeZone.
|
|
66
|
+
*/
|
|
67
|
+
export function getDefaultTimeZone() {
|
|
68
|
+
return config.defaultTimeZone;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Return true if a year is a leap year.
|
|
73
|
+
* @param {number} year The year.
|
|
74
|
+
* @return {Boolean} TRUE if the year is a leap year, otherwise FALSE.
|
|
75
|
+
*/
|
|
76
|
+
export function isLeapYear(year) {
|
|
77
|
+
return new Date(year, 1, 29)
|
|
78
|
+
.getDate() === 29;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Set whether dates will be clamped when changing months.
|
|
83
|
+
* @param {Boolean} clampDates Whether to clamp dates.
|
|
84
|
+
*/
|
|
85
|
+
export function setDateClamping(clampDates) {
|
|
86
|
+
config.clampDates = clampDates;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Set the default locale.
|
|
91
|
+
* @param {string} locale The locale.
|
|
92
|
+
*/
|
|
93
|
+
export function setDefaultLocale(locale) {
|
|
94
|
+
config.defaultLocale = locale;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Set the default timeZone.
|
|
99
|
+
* @param {string} timeZone The name of the timeZone.
|
|
100
|
+
*/
|
|
101
|
+
export function setDefaultTimeZone(timeZone) {
|
|
102
|
+
config.defaultTimeZone = timeZone;
|
|
103
|
+
};
|
package/src/vars.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DateTime Variables
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const resolvedOptions = (new Intl.DateTimeFormat).resolvedOptions();
|
|
6
|
+
|
|
7
|
+
export const config = {
|
|
8
|
+
clampDates: true,
|
|
9
|
+
defaultLocale: resolvedOptions.locale,
|
|
10
|
+
defaultTimeZone: resolvedOptions.timeZone,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const dateStringTimeZoneRegExp = /\s(?:UTC|GMT|Z|[\+\-]\d)|\d{4}\-\d{2}\-\d{2}T\d{2}\:\d{2}\:\d{2}\.\d{3}[\+\-]\d{2}\:\d{2}/i;
|
|
14
|
+
|
|
15
|
+
export const formats = {
|
|
16
|
+
date: 'eee MMM dd yyyy',
|
|
17
|
+
rfc3339_extended: `yyyy-MM-dd'T'HH:mm:ss.SSSxxx`,
|
|
18
|
+
string: 'eee MMM dd yyyy HH:mm:ss xx (VV)',
|
|
19
|
+
time: 'HH:mm:ss xx (VV)',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const formatTokenRegExp = /([a-z])\1*|'[^']*'/i;
|
|
23
|
+
|
|
24
|
+
export const monthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
25
|
+
|
|
26
|
+
export const offsetRegExp = /(?:GMT)?([\+\-])(\d{2})(\:?)(\d{2})?/;
|
|
27
|
+
|
|
28
|
+
export const parseOrderKeys = [
|
|
29
|
+
['year', 'weekYear'],
|
|
30
|
+
['era'],
|
|
31
|
+
['quarter', 'month', 'week', 'dayOfYear'],
|
|
32
|
+
['weekOfMonth'],
|
|
33
|
+
['date', 'weekDay'],
|
|
34
|
+
['weekDayInMonth'],
|
|
35
|
+
['hours24', 'hours12', 'dayPeriod'],
|
|
36
|
+
['minutes', 'seconds', 'milliseconds'],
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
export const thresholds = {
|
|
40
|
+
month: 12,
|
|
41
|
+
week: null,
|
|
42
|
+
day: 7,
|
|
43
|
+
hour: 24,
|
|
44
|
+
minute: 60,
|
|
45
|
+
second: 60,
|
|
46
|
+
};
|