@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.
@@ -0,0 +1,96 @@
1
+ import { minDaysInFirstWeek, weekStart } from './locales.js';
2
+ import { getData } from './../factory.js';
3
+
4
+ /**
5
+ * Get the formatting type from the component token length.
6
+ * @param {number} length The component token length.
7
+ * @return {string} The formatting type.
8
+ */
9
+ export function getType(length) {
10
+ switch (length) {
11
+ case 5:
12
+ return 'narrow';
13
+ case 4:
14
+ return 'long';
15
+ default:
16
+ return 'short';
17
+ }
18
+ };
19
+
20
+ /**
21
+ * Get the minimum days.
22
+ * @param {string} locale The locale.
23
+ * @return {number} The minimum days.
24
+ */
25
+ export function minimumDays(locale) {
26
+ return getData(
27
+ `minimumDays.${locale}`,
28
+ (_) => {
29
+ let minDays = 1;
30
+ const localeTest = locale.toLowerCase().split('-');
31
+ while (minDays === 1 && localeTest.length) {
32
+ for (const days in minDaysInFirstWeek) {
33
+ if (!{}.hasOwnProperty.call(minDaysInFirstWeek, days)) {
34
+ continue;
35
+ }
36
+
37
+ const locales = minDaysInFirstWeek[days];
38
+
39
+ if (locales.includes(localeTest.join('-'))) {
40
+ minDays = parseInt(days);
41
+ break;
42
+ }
43
+ }
44
+
45
+ localeTest.pop();
46
+ }
47
+
48
+ return minDays;
49
+ },
50
+ );
51
+ };
52
+
53
+ /**
54
+ * Get the week start offset for a locale.
55
+ * @param {string} [locale] The locale to load.
56
+ * @return {number} The week start offset.
57
+ */
58
+ function weekStartOffset(locale) {
59
+ return getData(
60
+ `weekStartOffset.${locale}`,
61
+ (_) => {
62
+ let weekStarted;
63
+ const localeTest = locale.toLowerCase().split('-');
64
+ while (!weekStarted && localeTest.length) {
65
+ for (const start in weekStart) {
66
+ if (!{}.hasOwnProperty.call(weekStart, start)) {
67
+ continue;
68
+ }
69
+
70
+ const locales = weekStart[start];
71
+
72
+ if (locales.includes(localeTest.join('-'))) {
73
+ weekStarted = parseInt(start);
74
+ break;
75
+ }
76
+ }
77
+
78
+ localeTest.pop();
79
+ }
80
+
81
+ return weekStarted ?
82
+ weekStarted - 2 :
83
+ 0;
84
+ },
85
+ );
86
+ };
87
+
88
+ /**
89
+ * Convert a day of the week to a local format.
90
+ * @param {string} locale The locale.
91
+ * @param {number} day The day of the week.
92
+ * @return {number} The local day of the week.
93
+ */
94
+ export function weekDay(locale, day) {
95
+ return (7 + parseInt(day) - weekStartOffset(locale)) % 7 || 7;
96
+ };
@@ -0,0 +1,142 @@
1
+ import { getData, makeFormatter } from './../factory.js';
2
+
3
+ /**
4
+ * DateFormatter Values
5
+ */
6
+
7
+ /**
8
+ * Get cached day period values.
9
+ * @param {string} locale The locale.
10
+ * @param {string} [type=long] The formatting type.
11
+ * @return {array} The cached values.
12
+ */
13
+ export function getDayPeriods(locale, type = 'long') {
14
+ return getData(
15
+ `periods.${locale}.${type}`,
16
+ (_) => {
17
+ const dayPeriodFormatter = makeFormatter(locale, { hour: 'numeric', hourCycle: 'h11' });
18
+ return new Array(2)
19
+ .fill()
20
+ .map((_, index) =>
21
+ dayPeriodFormatter.formatToParts(Date.UTC(2018, 0, 1, index * 12))
22
+ .find((part) => part.type === 'dayPeriod')
23
+ .value,
24
+ );
25
+ },
26
+ );
27
+ };
28
+
29
+ /**
30
+ * Get cached day values.
31
+ * @param {string} locale The locale.
32
+ * @param {string} [type=long] The formatting type.
33
+ * @param {Boolean} [standalone=true] Whether the values are standalone.
34
+ * @return {array} The cached values.
35
+ */
36
+ export function getDays(locale, type = 'long', standalone = true) {
37
+ return getData(
38
+ `days.${locale}.${type}.${standalone}`,
39
+ (_) => {
40
+ if (standalone) {
41
+ const dayFormatter = makeFormatter(locale, { weekday: type });
42
+ return new Array(7)
43
+ .fill()
44
+ .map((_, index) =>
45
+ dayFormatter.format(Date.UTC(2018, 0, index)),
46
+ );
47
+ }
48
+
49
+ const dayFormatter = makeFormatter(locale, { year: 'numeric', month: 'numeric', day: 'numeric', weekday: type });
50
+ return new Array(7)
51
+ .fill()
52
+ .map((_, index) =>
53
+ dayFormatter.formatToParts(Date.UTC(2018, 0, index))
54
+ .find((part) => part.type === 'weekday')
55
+ .value,
56
+ );
57
+ },
58
+ );
59
+ };
60
+
61
+ /**
62
+ * Get cached era values.
63
+ * @param {string} locale The locale.
64
+ * @param {string} [type=long] The formatting type.
65
+ * @return {array} The cached values.
66
+ */
67
+ export function getEras(locale, type = 'long') {
68
+ return getData(
69
+ `eras.${locale}.${type}`,
70
+ (_) => {
71
+ const eraFormatter = makeFormatter(locale, { era: type });
72
+ return new Array(2)
73
+ .fill()
74
+ .map((_, index) =>
75
+ eraFormatter.formatToParts(Date.UTC(index - 1, 0, 1))
76
+ .find((part) => part.type === 'era')
77
+ .value,
78
+ );
79
+ },
80
+ );
81
+ };
82
+
83
+ /**
84
+ * Get cached month values.
85
+ * @param {string} locale The locale.
86
+ * @param {string} [type=long] The formatting type.
87
+ * @param {Boolean} [standalone=true] Whether the values are standalone.
88
+ * @return {array} The cached values.
89
+ */
90
+ export function getMonths(locale, type = 'long', standalone = true) {
91
+ return getData(
92
+ `months.${locale}.${type}.${standalone}`,
93
+ (_) => {
94
+ if (standalone) {
95
+ const monthFormatter = makeFormatter(locale, { month: type });
96
+ return new Array(12)
97
+ .fill()
98
+ .map((_, index) =>
99
+ monthFormatter.format(Date.UTC(2018, index, 1)),
100
+ );
101
+ }
102
+
103
+ const monthFormatter = makeFormatter(locale, { year: 'numeric', month: type, day: 'numeric' });
104
+ return new Array(12)
105
+ .fill()
106
+ .map((_, index) =>
107
+ monthFormatter.formatToParts(Date.UTC(2018, index, 1))
108
+ .find((part) => part.type === 'month')
109
+ .value,
110
+ );
111
+ },
112
+ );
113
+ };
114
+
115
+ /**
116
+ * Get cached number values.
117
+ * @param {string} locale The locale.
118
+ * @return {array} The cached values.
119
+ */
120
+ export function getNumbers(locale) {
121
+ return getData(
122
+ `numbers.${locale}`,
123
+ (_) => {
124
+ const numberFormatter = makeFormatter(locale, { minute: 'numeric' });
125
+ return new Array(10)
126
+ .fill()
127
+ .map((_, index) =>
128
+ numberFormatter.format(Date.UTC(2018, 0, 1, 0, index)),
129
+ );
130
+ },
131
+ );
132
+ };
133
+
134
+ /**
135
+ * Get the RegExp for the number values.
136
+ * @param {string} locale The locale.
137
+ * @return {string} The number values RegExp.
138
+ */
139
+ export function numberRegExp(locale) {
140
+ const numbers = getNumbers(locale).join('|');
141
+ return `(?:${numbers})+`;
142
+ };
package/src/helpers.js ADDED
@@ -0,0 +1,272 @@
1
+ import { getDateFormatter } from './factory.js';
2
+ import { thresholds } from './vars.js';
3
+
4
+ /**
5
+ * DateTime Helpers
6
+ */
7
+
8
+ /**
9
+ * Compensate the difference between two dates.
10
+ * @param {DateTime} date The DateTime.
11
+ * @param {DateTime} other The DateTime to compare to.
12
+ * @param {number} amount The amount to compensate.
13
+ * @param {Boolean} [compensate=true] Whether to compensate the amount.
14
+ * @param {number} [compensation=1] The compensation offset.
15
+ * @return {number} The compensated amount.
16
+ */
17
+ export function compensateDiff(date, other, amount, compensate = true, compensation = 1) {
18
+ if (amount > 0) {
19
+ amount = Math.floor(amount);
20
+
21
+ if (compensate && date < other) {
22
+ amount += compensation;
23
+ }
24
+ } else if (amount < 0) {
25
+ amount = Math.ceil(amount);
26
+
27
+ if (compensate && date > other) {
28
+ amount -= compensation;
29
+ }
30
+ }
31
+
32
+ return amount;
33
+ };
34
+
35
+ /**
36
+ * Get the biggest difference between two dates.
37
+ * @param {DateTime} date The DateTime.
38
+ * @param {DateTime} [other] The DateTime to compare to.
39
+ * @return {array} The biggest difference (amount and time unit).
40
+ */
41
+ export function getBiggestDiff(date, other) {
42
+ let lastResult;
43
+ for (const timeUnit of ['year', 'month', 'week', 'day', 'hour', 'minute', 'second']) {
44
+ const relativeDiff = date.diff(other, timeUnit);
45
+ if (lastResult && thresholds[timeUnit] && Math.abs(relativeDiff) >= thresholds[timeUnit]) {
46
+ return lastResult;
47
+ }
48
+
49
+ const actualDiff = date.diff(other, timeUnit, false);
50
+ if (actualDiff) {
51
+ return [relativeDiff, timeUnit];
52
+ }
53
+
54
+ if (relativeDiff) {
55
+ lastResult = [relativeDiff, timeUnit];
56
+ } else {
57
+ lastResult = null;
58
+ }
59
+ }
60
+
61
+ return lastResult ?
62
+ lastResult :
63
+ [0, 'second'];
64
+ };
65
+
66
+ /**
67
+ * Get the offset for a DateTime.
68
+ * @param {DateTime} date The DateTime.
69
+ * @return {number} The offset.
70
+ */
71
+ export function getOffset(date) {
72
+ const timeZone = date.getTimeZone();
73
+
74
+ if (timeZone === 'UTC') {
75
+ return 0;
76
+ }
77
+
78
+ const utcString = getDateFormatter('UTC').format(date);
79
+ const localString = getDateFormatter(timeZone).format(date);
80
+
81
+ return (new Date(utcString) - new Date(localString)) / 60000;
82
+ };
83
+
84
+ /**
85
+ * Get the number of milliseconds since the UNIX epoch (offset to timeZone).
86
+ * @param {DateTime} date The DateTime.
87
+ * @return {number} The number of milliseconds since the UNIX epoch (offset to timeZone).
88
+ */
89
+ export function getOffsetTime(date) {
90
+ return date.getTime() - (date.getTimeZoneOffset() * 60000);
91
+ };
92
+
93
+ /**
94
+ * Modify a DateTime by a duration.
95
+ * @param {DateTime} date The DateTime.
96
+ * @param {number} amount The amount to modify the date by.
97
+ * @param {string} [timeUnit] The unit of time.
98
+ * @return {DateTime} The DateTime object.
99
+ */
100
+ export function modify(date, amount, timeUnit) {
101
+ timeUnit = timeUnit.toLowerCase();
102
+
103
+ switch (timeUnit) {
104
+ case 'second':
105
+ case 'seconds':
106
+ return date.setSeconds(
107
+ date.getSeconds() + amount,
108
+ );
109
+ case 'minute':
110
+ case 'minutes':
111
+ return date.setMinutes(
112
+ date.getMinutes() + amount,
113
+ );
114
+ case 'hour':
115
+ case 'hours':
116
+ return date.setHours(
117
+ date.getHours() + amount,
118
+ );
119
+ case 'week':
120
+ case 'weeks':
121
+ return date.setDate(
122
+ date.getDate() + (amount * 7),
123
+ );
124
+ case 'day':
125
+ case 'days':
126
+ return date.setDate(
127
+ date.getDate() + amount,
128
+ );
129
+ case 'month':
130
+ case 'months':
131
+ return date.setMonth(
132
+ date.getMonth() + amount,
133
+ );
134
+ case 'year':
135
+ case 'years':
136
+ return date.setYear(
137
+ date.getYear() + amount,
138
+ );
139
+ default:
140
+ throw new Error('Invalid time unit supplied');
141
+ }
142
+ };
143
+
144
+ /**
145
+ * Compare a literal format string with a date string.
146
+ * @param {string} formatString The literal format string.
147
+ * @param {string} dateString The date string.
148
+ */
149
+ export function parseCompare(formatString, dateString) {
150
+ let i = 0;
151
+ for (const char of formatString) {
152
+ if (char !== dateString[i]) {
153
+ throw new Error(`Unmatched character in DateTime string: ${char}`);
154
+ }
155
+
156
+ i++;
157
+ }
158
+ };
159
+
160
+ /**
161
+ * Generate methods for parsing a date.
162
+ * @return {object} An object containing date parsing methods.
163
+ */
164
+ export function parseFactory() {
165
+ let isPM = false;
166
+ let lastAM = true;
167
+
168
+ return {
169
+ date: {
170
+ get: (datetime) => datetime.getDate(),
171
+ set: (datetime, value) => datetime.setDate(value),
172
+ },
173
+ dayPeriod: {
174
+ get: (datetime) => datetime.getHours() < 12 ? 0 : 1,
175
+ set: (datetime, value) => {
176
+ isPM = value;
177
+ let hours = value ? 12 : 0;
178
+ if (lastAM) {
179
+ hours += datetime.getHours();
180
+ }
181
+ return datetime.setHours(hours);
182
+ },
183
+ },
184
+ dayOfYear: {
185
+ get: (datetime) => datetime.getDayOfYear(),
186
+ set: (datetime, value) => datetime.setDayOfYear(value),
187
+ },
188
+ era: {
189
+ get: (datetime) => datetime.getYear() < 1 ? 0 : 1,
190
+ set: (datetime, value) => {
191
+ const offset = value ? 1 : -1;
192
+ return datetime.setYear(
193
+ datetime.getYear() * offset,
194
+ );
195
+ },
196
+ },
197
+ hours12: {
198
+ get: (datetime) => datetime.getHours() % 12,
199
+ set: (datetime, value) => {
200
+ if (isPM) {
201
+ value += 12;
202
+ }
203
+ lastAM = true;
204
+ return datetime.setHours(value);
205
+ },
206
+ },
207
+ hours24: {
208
+ get: (datetime) => datetime.getHours(),
209
+ set: (datetime, value) => {
210
+ lastAM = false;
211
+ return datetime.setHours(value);
212
+ },
213
+ },
214
+ milliseconds: {
215
+ get: (datetime) => datetime.getMilliseconds(),
216
+ set: (datetime, value) => datetime.setMilliseconds(value),
217
+ },
218
+ minutes: {
219
+ get: (datetime) => datetime.getMinutes(),
220
+ set: (datetime, value) => datetime.setMinutes(value),
221
+ },
222
+ month: {
223
+ get: (datetime) => datetime.getMonth(),
224
+ set: (datetime, value) => datetime.setMonth(value),
225
+ },
226
+ quarter: {
227
+ get: (datetime) => datetime.getQuarter(),
228
+ set: (datetime, value) => datetime.setQuarter(value),
229
+ },
230
+ seconds: {
231
+ get: (datetime) => datetime.getSeconds(),
232
+ set: (datetime, value) => datetime.setSeconds(value),
233
+ },
234
+ week: {
235
+ get: (datetime) => datetime.getWeek(),
236
+ set: (datetime, value) => datetime.setWeek(value),
237
+ },
238
+ weekDay: {
239
+ get: (datetime) => datetime.getWeekDay(),
240
+ set: (datetime, value) => datetime.setWeekDay(value),
241
+ },
242
+ weekDayInMonth: {
243
+ get: (datetime) => datetime.getWeekDayInMonth(),
244
+ set: (datetime, value) => datetime.setWeekDayInMonth(value),
245
+ },
246
+ weekOfMonth: {
247
+ get: (datetime) => datetime.getWeekOfMonth(),
248
+ set: (datetime, value) => datetime.setWeekOfMonth(value),
249
+ },
250
+ weekYear: {
251
+ get: (datetime) => datetime.getWeekYear(),
252
+ set: (datetime, value) => datetime.setWeekYear(value),
253
+ },
254
+ year: {
255
+ get: (datetime) => {
256
+ const year = datetime.getYear();
257
+ return Math.abs(year);
258
+ },
259
+ set: (datetime, value) => datetime.setYear(value),
260
+ },
261
+ };
262
+ };
263
+
264
+ /**
265
+ * Set the number of milliseconds since the UNIX epoch (offset to timeZone).
266
+ * @param {DateTime} date The DateTime.
267
+ * @param {number} time The number of milliseconds since the UNIX epoch (offset to timeZone).
268
+ * @return {DateTime} The DateTime object.
269
+ */
270
+ export function setOffsetTime(date, time) {
271
+ return date.setTime(time + (date.getTimeZoneOffset() * 60000));
272
+ };
package/src/index.js ADDED
@@ -0,0 +1,89 @@
1
+ import DateTime from './date-time.js';
2
+ import { fromArray, fromDate, fromFormat, fromISOString, fromTimestamp, now } from './static/create.js';
3
+ import { dayOfYear, daysInMonth as _daysInMonth, daysInYear as _daysInYear, getDefaultLocale, getDefaultTimeZone, isLeapYear as _isLeapYear, setDateClamping, setDefaultLocale, setDefaultTimeZone } from './static/utility.js';
4
+ import { getDate, getDay, getDayOfYear, getHours, getMilliseconds, getMinutes, getMonth, getQuarter, getSeconds, getTimestamp, getWeek, getWeekDay, getWeekDayInMonth, getWeekOfMonth, getWeekYear, getYear } from './prototype/attributes-get.js';
5
+ import { setDate, setDay, setDayOfYear, setHours, setMilliseconds, setMinutes, setMonth, setQuarter, setSeconds, setTimestamp, setWeek, setWeekDay, setWeekDayInMonth, setWeekOfMonth, setWeekYear, setYear } from './prototype/attributes-set.js';
6
+ import { add, endOf, startOf, sub } from './prototype/manipulate.js';
7
+ import { format, toDateString, toISOString, toString, toTimeString, toUTCString } from './prototype/output.js';
8
+ import { dayName, dayPeriod, daysInMonth, daysInYear, diff, era, humanDiff, isAfter, isBefore, isBetween, isDST, isLeapYear, isSame, isSameOrAfter, isSameOrBefore, monthName, timeZoneName, weeksInYear } from './prototype/utility.js';
9
+
10
+ DateTime.dayOfYear = dayOfYear;
11
+ DateTime.daysInMonth = _daysInMonth;
12
+ DateTime.daysInYear = _daysInYear;
13
+ DateTime.fromArray = fromArray;
14
+ DateTime.fromDate = fromDate;
15
+ DateTime.fromFormat = fromFormat;
16
+ DateTime.fromISOString = fromISOString;
17
+ DateTime.fromTimestamp = fromTimestamp;
18
+ DateTime.getDefaultLocale = getDefaultLocale;
19
+ DateTime.getDefaultTimeZone = getDefaultTimeZone;
20
+ DateTime.isLeapYear = _isLeapYear;
21
+ DateTime.now = now;
22
+ DateTime.setDateClamping = setDateClamping;
23
+ DateTime.setDefaultLocale = setDefaultLocale;
24
+ DateTime.setDefaultTimeZone = setDefaultTimeZone;
25
+
26
+ const proto = DateTime.prototype;
27
+
28
+ proto.add = add;
29
+ proto.dayName = dayName;
30
+ proto.dayPeriod = dayPeriod;
31
+ proto.daysInMonth = daysInMonth;
32
+ proto.daysInYear = daysInYear;
33
+ proto.diff = diff;
34
+ proto.endOf = endOf;
35
+ proto.era = era;
36
+ proto.format = format;
37
+ proto.getDate = getDate;
38
+ proto.getDay = getDay;
39
+ proto.getDayOfYear = getDayOfYear;
40
+ proto.getHours = getHours;
41
+ proto.getMilliseconds = getMilliseconds;
42
+ proto.getMinutes = getMinutes;
43
+ proto.getMonth = getMonth;
44
+ proto.getQuarter = getQuarter;
45
+ proto.getSeconds = getSeconds;
46
+ proto.getTimestamp = getTimestamp;
47
+ proto.getWeek = getWeek;
48
+ proto.getWeekDay = getWeekDay;
49
+ proto.getWeekDayInMonth = getWeekDayInMonth;
50
+ proto.getWeekOfMonth = getWeekOfMonth;
51
+ proto.getWeekYear = getWeekYear;
52
+ proto.getYear = getYear;
53
+ proto.humanDiff = humanDiff;
54
+ proto.isAfter = isAfter;
55
+ proto.isBefore = isBefore;
56
+ proto.isBetween = isBetween;
57
+ proto.isDST = isDST;
58
+ proto.isLeapYear = isLeapYear;
59
+ proto.isSame = isSame;
60
+ proto.isSameOrAfter = isSameOrAfter;
61
+ proto.isSameOrBefore = isSameOrBefore;
62
+ proto.monthName = monthName;
63
+ proto.setDate = setDate;
64
+ proto.setDay = setDay;
65
+ proto.setDayOfYear = setDayOfYear;
66
+ proto.setHours = setHours;
67
+ proto.setMilliseconds = setMilliseconds;
68
+ proto.setMinutes = setMinutes;
69
+ proto.setMonth = setMonth;
70
+ proto.setQuarter = setQuarter;
71
+ proto.setSeconds = setSeconds;
72
+ proto.setTimestamp = setTimestamp;
73
+ proto.setWeek = setWeek;
74
+ proto.setWeekDay = setWeekDay;
75
+ proto.setWeekDayInMonth = setWeekDayInMonth;
76
+ proto.setWeekOfMonth = setWeekOfMonth;
77
+ proto.setWeekYear = setWeekYear;
78
+ proto.setYear = setYear;
79
+ proto.startOf = startOf;
80
+ proto.sub = sub;
81
+ proto.timeZoneName = timeZoneName;
82
+ proto.toDateString = toDateString;
83
+ proto.toISOString = toISOString;
84
+ proto.toString = toString;
85
+ proto.toTimeString = toTimeString;
86
+ proto.toUTCString = toUTCString;
87
+ proto.weeksInYear = weeksInYear;
88
+
89
+ export default DateTime;