@beinformed/ui 1.58.3 → 1.59.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/CHANGELOG.md +24 -0
- package/esm/constants/Constants.js +10 -0
- package/esm/constants/Constants.js.map +1 -1
- package/esm/constants/Settings.js +5 -1
- package/esm/constants/Settings.js.map +1 -1
- package/esm/models/attributes/DatetimeAttributeModel.js +39 -4
- package/esm/models/attributes/DatetimeAttributeModel.js.map +1 -1
- package/esm/models/attributes/input-constraints/DatetimeFormatConstraint.js +31 -2
- package/esm/models/attributes/input-constraints/DatetimeFormatConstraint.js.map +1 -1
- package/esm/models/content/SectionModel.js +1 -1
- package/esm/models/content/SectionModel.js.map +1 -1
- package/esm/models/content/SubSectionModel.js +12 -4
- package/esm/models/content/SubSectionModel.js.map +1 -1
- package/esm/react-client/client.js +2 -1
- package/esm/react-client/client.js.map +1 -1
- package/esm/react-server/serverUtil.js +2 -1
- package/esm/react-server/serverUtil.js.map +1 -1
- package/esm/redux/actions/Preferences.js +15 -1
- package/esm/redux/actions/Preferences.js.map +1 -1
- package/esm/utils/datetime/DateTimeUtil.js +292 -94
- package/esm/utils/datetime/DateTimeUtil.js.map +1 -1
- package/lib/constants/Constants.js +11 -1
- package/lib/constants/Constants.js.flow +11 -0
- package/lib/constants/Constants.js.map +1 -1
- package/lib/constants/Settings.js +7 -2
- package/lib/constants/Settings.js.flow +6 -0
- package/lib/constants/Settings.js.map +1 -1
- package/lib/models/attributes/DatetimeAttributeModel.js +38 -3
- package/lib/models/attributes/DatetimeAttributeModel.js.flow +54 -4
- package/lib/models/attributes/DatetimeAttributeModel.js.map +1 -1
- package/lib/models/attributes/__tests__/DatetimeAttributeModel.spec.js.flow +9 -0
- package/lib/models/attributes/__tests__/DatetimeAttributeModel_offset.spec.js.flow +306 -0
- package/lib/models/attributes/input-constraints/DatetimeFormatConstraint.js +31 -2
- package/lib/models/attributes/input-constraints/DatetimeFormatConstraint.js.flow +42 -3
- package/lib/models/attributes/input-constraints/DatetimeFormatConstraint.js.map +1 -1
- package/lib/models/content/SectionModel.js +1 -1
- package/lib/models/content/SectionModel.js.flow +2 -1
- package/lib/models/content/SectionModel.js.map +1 -1
- package/lib/models/content/SubSectionModel.js +12 -3
- package/lib/models/content/SubSectionModel.js.flow +20 -3
- package/lib/models/content/SubSectionModel.js.map +1 -1
- package/lib/models/content/__tests__/ContentModel.spec.js.flow +3 -3
- package/lib/react-client/client.js +1 -0
- package/lib/react-client/client.js.flow +2 -0
- package/lib/react-client/client.js.map +1 -1
- package/lib/react-server/__tests__/serverUtil.spec.js.flow +12 -0
- package/lib/react-server/serverUtil.js +1 -0
- package/lib/react-server/serverUtil.js.flow +2 -0
- package/lib/react-server/serverUtil.js.map +1 -1
- package/lib/redux/actions/Preferences.js +17 -2
- package/lib/redux/actions/Preferences.js.flow +22 -0
- package/lib/redux/actions/Preferences.js.map +1 -1
- package/lib/redux/reducers/__tests__/ModelCatalogReducer.spec.js.flow +23 -0
- package/lib/utils/datetime/DateTimeUtil.js +292 -93
- package/lib/utils/datetime/DateTimeUtil.js.flow +482 -172
- package/lib/utils/datetime/DateTimeUtil.js.map +1 -1
- package/lib/utils/datetime/__tests__/DateTime.spec.js.flow +771 -483
- package/package.json +11 -9
- package/src/constants/Constants.js +11 -0
- package/src/constants/Settings.js +6 -0
- package/src/models/attributes/DatetimeAttributeModel.js +54 -4
- package/src/models/attributes/__tests__/DatetimeAttributeModel.spec.js +9 -0
- package/src/models/attributes/__tests__/DatetimeAttributeModel_offset.spec.js +306 -0
- package/src/models/attributes/input-constraints/DatetimeFormatConstraint.js +42 -3
- package/src/models/content/SectionModel.js +2 -1
- package/src/models/content/SubSectionModel.js +20 -3
- package/src/models/content/__tests__/ContentModel.spec.js +3 -3
- package/src/react-client/client.js +2 -0
- package/src/react-server/__tests__/serverUtil.spec.js +12 -0
- package/src/react-server/serverUtil.js +2 -0
- package/src/redux/actions/Preferences.js +22 -0
- package/src/redux/reducers/__tests__/ModelCatalogReducer.spec.js +23 -0
- package/src/utils/datetime/DateTimeUtil.js +482 -172
- package/src/utils/datetime/__tests__/DateTime.spec.js +771 -483
|
@@ -1,25 +1,14 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import {
|
|
3
|
-
parse,
|
|
4
3
|
format,
|
|
5
|
-
isValid,
|
|
6
4
|
isAfter,
|
|
7
5
|
isBefore,
|
|
8
6
|
isSameDay,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
addMonths,
|
|
15
|
-
addYears,
|
|
16
|
-
subSeconds,
|
|
17
|
-
subMinutes,
|
|
18
|
-
subHours,
|
|
19
|
-
subDays,
|
|
20
|
-
subWeeks,
|
|
21
|
-
subMonths,
|
|
22
|
-
subYears,
|
|
7
|
+
isValid,
|
|
8
|
+
parse,
|
|
9
|
+
add,
|
|
10
|
+
sub,
|
|
11
|
+
set,
|
|
23
12
|
startOfMonth,
|
|
24
13
|
endOfMonth,
|
|
25
14
|
startOfWeek,
|
|
@@ -27,52 +16,56 @@ import {
|
|
|
27
16
|
getMinutes,
|
|
28
17
|
getDay,
|
|
29
18
|
getWeek,
|
|
30
|
-
setMilliseconds,
|
|
31
|
-
setSeconds,
|
|
32
|
-
setMinutes,
|
|
33
|
-
setHours,
|
|
34
|
-
setMonth,
|
|
35
|
-
setYear,
|
|
36
|
-
set,
|
|
37
19
|
} from "date-fns";
|
|
38
|
-
import {
|
|
20
|
+
import { enGB, nl } from "date-fns/locale";
|
|
21
|
+
import { tz } from "@date-fns/tz";
|
|
39
22
|
|
|
40
|
-
import
|
|
41
|
-
|
|
42
|
-
import { getSetting } from "../../constants/Settings";
|
|
23
|
+
import soft from "timezone-soft";
|
|
43
24
|
|
|
44
25
|
import {
|
|
26
|
+
DATETIME_OFFSET_FORMAT,
|
|
27
|
+
DEFAULT_FIRST_WEEK_CONTAINS_DATE,
|
|
28
|
+
DEFAULT_WEEK_STARTS_ON,
|
|
29
|
+
getSetting,
|
|
30
|
+
IS_GRAALJS,
|
|
31
|
+
isIncludeTimeOffsetInDateTimes,
|
|
45
32
|
ISO_DATE_FORMAT,
|
|
46
33
|
ISO_DATETIME_FORMAT,
|
|
47
34
|
ISO_TIME_FORMAT,
|
|
48
35
|
ISO_TIMESTAMP_FORMAT,
|
|
49
|
-
DEFAULT_WEEK_STARTS_ON,
|
|
50
|
-
DEFAULT_FIRST_WEEK_CONTAINS_DATE,
|
|
51
36
|
} from "../../constants";
|
|
52
37
|
|
|
38
|
+
import { getCookie } from "../browser/Cookies";
|
|
39
|
+
|
|
40
|
+
type OffsetInfoInput = {
|
|
41
|
+
abbr: string,
|
|
42
|
+
offset: number,
|
|
43
|
+
name: string,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type OffsetInfo = {
|
|
47
|
+
abbr: string,
|
|
48
|
+
label: string,
|
|
49
|
+
value: string,
|
|
50
|
+
};
|
|
51
|
+
|
|
53
52
|
/**
|
|
54
53
|
* @hideconstructor
|
|
55
54
|
*/
|
|
56
55
|
class BaseDateTimeUtil {
|
|
57
56
|
_isoFormat: string;
|
|
57
|
+
_timeZone: string =
|
|
58
|
+
typeof Intl === "undefined"
|
|
59
|
+
? "Etc/UTC"
|
|
60
|
+
: Intl.DateTimeFormat().resolvedOptions().timeZone || "Etc/UTC";
|
|
58
61
|
|
|
59
62
|
constructor(isoFormat: string) {
|
|
60
63
|
this._isoFormat = isoFormat;
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
/**
|
|
67
|
+
* Returns the options defined in settings
|
|
64
68
|
*/
|
|
65
|
-
getLocale(): typeof nl | typeof enGB {
|
|
66
|
-
const locale = getCookie("locale") ?? "en";
|
|
67
|
-
|
|
68
|
-
if (locale === "nl") {
|
|
69
|
-
return nl;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return enGB;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// returns the options defined in settings
|
|
76
69
|
getOptions(): {
|
|
77
70
|
weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6,
|
|
78
71
|
firstWeekContainsDate: 1 | 2 | 3 | 4 | 5 | 6 | 7,
|
|
@@ -94,10 +87,45 @@ class BaseDateTimeUtil {
|
|
|
94
87
|
|
|
95
88
|
/**
|
|
96
89
|
*/
|
|
97
|
-
|
|
90
|
+
getIsoFormat(): string {
|
|
91
|
+
if (
|
|
92
|
+
isIncludeTimeOffsetInDateTimes() &&
|
|
93
|
+
this._isoFormat.startsWith(ISO_DATETIME_FORMAT)
|
|
94
|
+
) {
|
|
95
|
+
return this._isoFormat + DATETIME_OFFSET_FORMAT;
|
|
96
|
+
}
|
|
97
|
+
return this._isoFormat;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
*/
|
|
102
|
+
convertFormat(sourceFormat: string): string {
|
|
103
|
+
return sourceFormat ? sourceFormat : this.getIsoFormat();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
*/
|
|
108
|
+
getLocale(): typeof nl | typeof enGB {
|
|
109
|
+
const locale = getCookie("locale") ?? "en";
|
|
110
|
+
|
|
111
|
+
if (locale === "nl") {
|
|
112
|
+
return nl;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return enGB;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
*/
|
|
120
|
+
toDate(date: string | Date, inputFormat: string = this.getIsoFormat()): Date {
|
|
121
|
+
if (date instanceof Date) {
|
|
122
|
+
return date;
|
|
123
|
+
}
|
|
124
|
+
|
|
98
125
|
const { weekStartsOn, firstWeekContainsDate } = this.getOptions();
|
|
99
126
|
|
|
100
127
|
return parse(date, inputFormat, new Date(), {
|
|
128
|
+
in: this.getDateFnsContext(),
|
|
101
129
|
weekStartsOn,
|
|
102
130
|
firstWeekContainsDate,
|
|
103
131
|
});
|
|
@@ -105,13 +133,18 @@ class BaseDateTimeUtil {
|
|
|
105
133
|
|
|
106
134
|
/**
|
|
107
135
|
*/
|
|
108
|
-
toFormat(
|
|
136
|
+
toFormat(
|
|
137
|
+
isoDate: string | Date,
|
|
138
|
+
targetFormat: string,
|
|
139
|
+
inputFormat: string = this.getIsoFormat(),
|
|
140
|
+
): string {
|
|
109
141
|
const { weekStartsOn } = this.getOptions();
|
|
110
142
|
|
|
111
|
-
const parsedDate =
|
|
143
|
+
const parsedDate = this.toDate(isoDate, inputFormat);
|
|
112
144
|
|
|
113
145
|
if (isValid(parsedDate)) {
|
|
114
146
|
return format(parsedDate, targetFormat, {
|
|
147
|
+
in: this.getDateFnsContext(),
|
|
115
148
|
weekStartsOn,
|
|
116
149
|
locale: this.getLocale(),
|
|
117
150
|
});
|
|
@@ -122,19 +155,11 @@ class BaseDateTimeUtil {
|
|
|
122
155
|
|
|
123
156
|
/**
|
|
124
157
|
*/
|
|
125
|
-
toISO(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (isValid(parsedDate)) {
|
|
132
|
-
return format(parsedDate, this._isoFormat, {
|
|
133
|
-
weekStartsOn,
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return "Invalid Date";
|
|
158
|
+
toISO(
|
|
159
|
+
date: string | Date,
|
|
160
|
+
sourceFormat: string = this.getIsoFormat(),
|
|
161
|
+
): string {
|
|
162
|
+
return this.toFormat(date, this.getIsoFormat(), sourceFormat);
|
|
138
163
|
}
|
|
139
164
|
|
|
140
165
|
/**
|
|
@@ -143,52 +168,49 @@ class BaseDateTimeUtil {
|
|
|
143
168
|
return this.toISO(new Date());
|
|
144
169
|
}
|
|
145
170
|
|
|
146
|
-
|
|
147
|
-
*/
|
|
148
|
-
convertFormat(sourceFormat: string): string {
|
|
149
|
-
return sourceFormat ? sourceFormat : this._isoFormat;
|
|
150
|
-
}
|
|
171
|
+
//////////// VALIDATION
|
|
151
172
|
|
|
152
173
|
/**
|
|
153
|
-
* VALIDATION
|
|
154
174
|
*/
|
|
155
175
|
hasFormat(date: string, sourceFormat: string): boolean {
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const formattedValue = format(realDate, sourceFormat, {
|
|
161
|
-
weekStartsOn,
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
const isOutsideRange =
|
|
165
|
-
isBefore(realDate, new Date(1000, 1, 1)) ||
|
|
166
|
-
isAfter(realDate, new Date(9999, 11, 31));
|
|
167
|
-
if (isOutsideRange) {
|
|
168
|
-
return false;
|
|
169
|
-
}
|
|
176
|
+
const formattedValue = this.toFormat(date, sourceFormat, sourceFormat);
|
|
177
|
+
if (formattedValue === "Invalid Date") {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
170
180
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
181
|
+
const isOutsideRange =
|
|
182
|
+
isBefore(formattedValue, new Date(1000, 1, 1)) ||
|
|
183
|
+
isAfter(formattedValue, new Date(9999, 11, 31));
|
|
184
|
+
if (isOutsideRange) {
|
|
185
|
+
return false;
|
|
175
186
|
}
|
|
176
187
|
|
|
177
|
-
return
|
|
188
|
+
return (
|
|
189
|
+
formattedValue.replace(/0/gu, "").toUpperCase() ===
|
|
190
|
+
date.replace(/0/gu, "").toUpperCase()
|
|
191
|
+
);
|
|
178
192
|
}
|
|
179
193
|
|
|
180
194
|
/**
|
|
181
195
|
*/
|
|
182
|
-
isValid(
|
|
183
|
-
|
|
196
|
+
isValid(
|
|
197
|
+
date: string | Date | null | void,
|
|
198
|
+
inputFormat: string = this.getIsoFormat(),
|
|
199
|
+
): boolean {
|
|
200
|
+
if (!date) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const parsedDate = this.toDate(date, inputFormat);
|
|
205
|
+
return isValid(parsedDate);
|
|
184
206
|
}
|
|
185
207
|
|
|
186
208
|
/**
|
|
187
209
|
*/
|
|
188
210
|
isAfter(
|
|
189
|
-
inputDate: string,
|
|
190
|
-
afterISODate: ?string,
|
|
191
|
-
inputFormat: string = this.
|
|
211
|
+
inputDate: string | Date,
|
|
212
|
+
afterISODate: ?string | Date,
|
|
213
|
+
inputFormat: string = this.getIsoFormat(),
|
|
192
214
|
): boolean {
|
|
193
215
|
return (
|
|
194
216
|
afterISODate != null &&
|
|
@@ -199,9 +221,9 @@ class BaseDateTimeUtil {
|
|
|
199
221
|
/**
|
|
200
222
|
*/
|
|
201
223
|
isSameOrAfter(
|
|
202
|
-
inputDate: string,
|
|
203
|
-
afterISODate: ?string,
|
|
204
|
-
inputFormat: string = this.
|
|
224
|
+
inputDate: string | Date,
|
|
225
|
+
afterISODate: ?string | Date,
|
|
226
|
+
inputFormat: string = this.getIsoFormat(),
|
|
205
227
|
): boolean {
|
|
206
228
|
return (
|
|
207
229
|
afterISODate != null &&
|
|
@@ -213,9 +235,9 @@ class BaseDateTimeUtil {
|
|
|
213
235
|
/**
|
|
214
236
|
*/
|
|
215
237
|
isBefore(
|
|
216
|
-
inputDate: string,
|
|
217
|
-
beforeISODate: ?string,
|
|
218
|
-
inputFormat: string = this.
|
|
238
|
+
inputDate: string | Date,
|
|
239
|
+
beforeISODate: ?string | Date,
|
|
240
|
+
inputFormat: string = this.getIsoFormat(),
|
|
219
241
|
): boolean {
|
|
220
242
|
return (
|
|
221
243
|
beforeISODate != null &&
|
|
@@ -226,9 +248,9 @@ class BaseDateTimeUtil {
|
|
|
226
248
|
/**
|
|
227
249
|
*/
|
|
228
250
|
isSameOrBefore(
|
|
229
|
-
inputDate: string,
|
|
230
|
-
beforeISODate: ?string,
|
|
231
|
-
inputFormat: string = this.
|
|
251
|
+
inputDate: string | Date,
|
|
252
|
+
beforeISODate: ?string | Date,
|
|
253
|
+
inputFormat: string = this.getIsoFormat(),
|
|
232
254
|
): boolean {
|
|
233
255
|
return (
|
|
234
256
|
beforeISODate != null &&
|
|
@@ -240,9 +262,9 @@ class BaseDateTimeUtil {
|
|
|
240
262
|
/**
|
|
241
263
|
*/
|
|
242
264
|
isSame(
|
|
243
|
-
inputDate: string,
|
|
244
|
-
compareDate: ?string,
|
|
245
|
-
inputFormat: string = this.
|
|
265
|
+
inputDate: string | Date,
|
|
266
|
+
compareDate: ?string | Date,
|
|
267
|
+
inputFormat: string = this.getIsoFormat(),
|
|
246
268
|
): boolean {
|
|
247
269
|
return (
|
|
248
270
|
compareDate != null &&
|
|
@@ -254,9 +276,9 @@ class BaseDateTimeUtil {
|
|
|
254
276
|
/**
|
|
255
277
|
*/
|
|
256
278
|
isSameDay(
|
|
257
|
-
inputDate: string,
|
|
258
|
-
compareDate: string,
|
|
259
|
-
inputFormat: string = this.
|
|
279
|
+
inputDate: string | Date,
|
|
280
|
+
compareDate: string | Date,
|
|
281
|
+
inputFormat: string = this.getIsoFormat(),
|
|
260
282
|
): boolean {
|
|
261
283
|
return (
|
|
262
284
|
compareDate != null &&
|
|
@@ -270,16 +292,16 @@ class BaseDateTimeUtil {
|
|
|
270
292
|
/**
|
|
271
293
|
*/
|
|
272
294
|
isOther(
|
|
273
|
-
inputDate: string,
|
|
274
|
-
compareDate: ?string,
|
|
275
|
-
inputFormat: string = this.
|
|
295
|
+
inputDate: string | Date,
|
|
296
|
+
compareDate: ?string | Date,
|
|
297
|
+
inputFormat: string = this.getIsoFormat(),
|
|
276
298
|
): boolean {
|
|
277
299
|
return !this.isSame(inputDate, compareDate, inputFormat);
|
|
278
300
|
}
|
|
279
301
|
|
|
280
302
|
/**
|
|
281
303
|
*/
|
|
282
|
-
isWeekend(inputDate: string): boolean {
|
|
304
|
+
isWeekend(inputDate: string | Date): boolean {
|
|
283
305
|
const SATURDAY_NUMBER = 6;
|
|
284
306
|
const SUNDAY_NUMBER = 0;
|
|
285
307
|
const weekDay = getDay(this.toDate(inputDate));
|
|
@@ -288,175 +310,371 @@ class BaseDateTimeUtil {
|
|
|
288
310
|
}
|
|
289
311
|
|
|
290
312
|
/**
|
|
291
|
-
*
|
|
313
|
+
* Checks if a given local date and time is ambiguous in the specified timezone.
|
|
314
|
+
* Ambiguity happens during the end of daylight saving time (DST) transitions.
|
|
292
315
|
*/
|
|
293
|
-
|
|
294
|
-
|
|
316
|
+
isAmbiguous(
|
|
317
|
+
inputDate: string | Date,
|
|
318
|
+
inputFormat: string = this.getIsoFormat(),
|
|
319
|
+
): boolean {
|
|
320
|
+
if (inputDate == null || typeof Intl === "undefined") {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const dateTime = this.toDate(inputDate, inputFormat);
|
|
325
|
+
if (!isValid(dateTime)) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const t = [60, -60, 30, -30];
|
|
330
|
+
const a = t.map((x) => {
|
|
331
|
+
const newDate = add(dateTime, { minutes: x });
|
|
332
|
+
return format(newDate, "HH:mm");
|
|
333
|
+
});
|
|
334
|
+
const time = format(dateTime, "HH:mm");
|
|
335
|
+
return a.indexOf(time) > -1;
|
|
295
336
|
}
|
|
296
337
|
|
|
338
|
+
//////////// CALCULATIONS
|
|
339
|
+
|
|
297
340
|
/**
|
|
341
|
+
* @private
|
|
298
342
|
*/
|
|
299
|
-
|
|
300
|
-
|
|
343
|
+
_calculate(
|
|
344
|
+
date: string | Date,
|
|
345
|
+
calculationFn: Function,
|
|
346
|
+
property: string,
|
|
347
|
+
value: number,
|
|
348
|
+
inputFormat: string = this.getIsoFormat(),
|
|
349
|
+
): string {
|
|
350
|
+
const parsedDate = this.toDate(date, inputFormat);
|
|
351
|
+
return this.toISO(
|
|
352
|
+
calculationFn(
|
|
353
|
+
parsedDate,
|
|
354
|
+
{ [property]: value },
|
|
355
|
+
{
|
|
356
|
+
in: this.getDateFnsContext(),
|
|
357
|
+
},
|
|
358
|
+
),
|
|
359
|
+
);
|
|
301
360
|
}
|
|
302
361
|
|
|
303
362
|
/**
|
|
304
363
|
*/
|
|
305
|
-
|
|
306
|
-
|
|
364
|
+
addSeconds(
|
|
365
|
+
date: string,
|
|
366
|
+
amount: number,
|
|
367
|
+
inputFormat: string = this.getIsoFormat(),
|
|
368
|
+
): string {
|
|
369
|
+
return this._calculate(date, add, "seconds", amount, inputFormat);
|
|
307
370
|
}
|
|
308
371
|
|
|
309
372
|
/**
|
|
310
373
|
*/
|
|
311
|
-
|
|
312
|
-
|
|
374
|
+
addMinutes(
|
|
375
|
+
date: string,
|
|
376
|
+
amount: number,
|
|
377
|
+
inputFormat: string = this.getIsoFormat(),
|
|
378
|
+
): string {
|
|
379
|
+
return this._calculate(date, add, "minutes", amount, inputFormat);
|
|
313
380
|
}
|
|
314
381
|
|
|
315
382
|
/**
|
|
316
383
|
*/
|
|
317
|
-
|
|
318
|
-
|
|
384
|
+
addHours(
|
|
385
|
+
date: string,
|
|
386
|
+
amount: number,
|
|
387
|
+
inputFormat: string = this.getIsoFormat(),
|
|
388
|
+
): string {
|
|
389
|
+
return this._calculate(date, add, "hours", amount, inputFormat);
|
|
319
390
|
}
|
|
320
391
|
|
|
321
392
|
/**
|
|
322
393
|
*/
|
|
323
|
-
|
|
324
|
-
|
|
394
|
+
addDays(
|
|
395
|
+
date: string,
|
|
396
|
+
amount: number,
|
|
397
|
+
inputFormat: string = this.getIsoFormat(),
|
|
398
|
+
): string {
|
|
399
|
+
return this._calculate(date, add, "days", amount, inputFormat);
|
|
325
400
|
}
|
|
326
401
|
|
|
327
402
|
/**
|
|
328
403
|
*/
|
|
329
|
-
|
|
330
|
-
|
|
404
|
+
addWeeks(
|
|
405
|
+
date: string,
|
|
406
|
+
amount: number,
|
|
407
|
+
inputFormat: string = this.getIsoFormat(),
|
|
408
|
+
): string {
|
|
409
|
+
return this._calculate(date, add, "weeks", amount, inputFormat);
|
|
331
410
|
}
|
|
332
411
|
|
|
333
412
|
/**
|
|
334
413
|
*/
|
|
335
|
-
|
|
336
|
-
|
|
414
|
+
addMonths(
|
|
415
|
+
date: string,
|
|
416
|
+
amount: number,
|
|
417
|
+
inputFormat: string = this.getIsoFormat(),
|
|
418
|
+
): string {
|
|
419
|
+
return this._calculate(date, add, "months", amount, inputFormat);
|
|
337
420
|
}
|
|
338
421
|
|
|
339
422
|
/**
|
|
340
423
|
*/
|
|
341
|
-
|
|
342
|
-
|
|
424
|
+
addYears(
|
|
425
|
+
date: string,
|
|
426
|
+
amount: number,
|
|
427
|
+
inputFormat: string = this.getIsoFormat(),
|
|
428
|
+
): string {
|
|
429
|
+
return this._calculate(date, add, "years", amount, inputFormat);
|
|
343
430
|
}
|
|
344
431
|
|
|
345
432
|
/**
|
|
346
433
|
*/
|
|
347
|
-
|
|
348
|
-
|
|
434
|
+
subtractSeconds(
|
|
435
|
+
date: string,
|
|
436
|
+
amount: number,
|
|
437
|
+
inputFormat: string = this.getIsoFormat(),
|
|
438
|
+
): string {
|
|
439
|
+
return this._calculate(date, sub, "seconds", amount, inputFormat);
|
|
349
440
|
}
|
|
350
441
|
|
|
351
442
|
/**
|
|
352
443
|
*/
|
|
353
|
-
|
|
354
|
-
|
|
444
|
+
subtractMinutes(
|
|
445
|
+
date: string,
|
|
446
|
+
amount: number,
|
|
447
|
+
inputFormat: string = this.getIsoFormat(),
|
|
448
|
+
): string {
|
|
449
|
+
return this._calculate(date, sub, "minutes", amount, inputFormat);
|
|
355
450
|
}
|
|
356
451
|
|
|
357
452
|
/**
|
|
358
453
|
*/
|
|
359
|
-
|
|
360
|
-
|
|
454
|
+
subtractHours(
|
|
455
|
+
date: string,
|
|
456
|
+
amount: number,
|
|
457
|
+
inputFormat: string = this.getIsoFormat(),
|
|
458
|
+
): string {
|
|
459
|
+
return this._calculate(date, sub, "hours", amount, inputFormat);
|
|
361
460
|
}
|
|
362
461
|
|
|
363
462
|
/**
|
|
364
463
|
*/
|
|
365
|
-
|
|
366
|
-
|
|
464
|
+
subtractDays(
|
|
465
|
+
date: string,
|
|
466
|
+
amount: number,
|
|
467
|
+
inputFormat: string = this.getIsoFormat(),
|
|
468
|
+
): string {
|
|
469
|
+
return this._calculate(date, sub, "days", amount, inputFormat);
|
|
367
470
|
}
|
|
368
471
|
|
|
369
472
|
/**
|
|
370
473
|
*/
|
|
371
|
-
|
|
372
|
-
|
|
474
|
+
subtractWeeks(
|
|
475
|
+
date: string,
|
|
476
|
+
amount: number,
|
|
477
|
+
inputFormat: string = this.getIsoFormat(),
|
|
478
|
+
): string {
|
|
479
|
+
return this._calculate(date, sub, "weeks", amount, inputFormat);
|
|
373
480
|
}
|
|
374
481
|
|
|
375
482
|
/**
|
|
376
|
-
* GETTERS
|
|
377
483
|
*/
|
|
378
|
-
|
|
379
|
-
|
|
484
|
+
subtractMonths(
|
|
485
|
+
date: string,
|
|
486
|
+
amount: number,
|
|
487
|
+
inputFormat: string = this.getIsoFormat(),
|
|
488
|
+
): string {
|
|
489
|
+
return this._calculate(date, sub, "months", amount, inputFormat);
|
|
380
490
|
}
|
|
381
491
|
|
|
382
492
|
/**
|
|
383
493
|
*/
|
|
384
|
-
|
|
385
|
-
|
|
494
|
+
subtractYears(
|
|
495
|
+
date: string,
|
|
496
|
+
amount: number,
|
|
497
|
+
inputFormat: string = this.getIsoFormat(),
|
|
498
|
+
): string {
|
|
499
|
+
return this._calculate(date, sub, "years", amount, inputFormat);
|
|
386
500
|
}
|
|
387
501
|
|
|
502
|
+
//////////// GETTERS
|
|
503
|
+
|
|
388
504
|
/**
|
|
505
|
+
* @private
|
|
389
506
|
*/
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
507
|
+
_get(
|
|
508
|
+
date: string | Date,
|
|
509
|
+
method: Function,
|
|
510
|
+
inputFormat: string = this.getIsoFormat(),
|
|
511
|
+
options: Object = {},
|
|
512
|
+
): string {
|
|
513
|
+
const parsedDate = this.toDate(date, inputFormat);
|
|
393
514
|
return this.toISO(
|
|
394
|
-
|
|
395
|
-
|
|
515
|
+
method(parsedDate, {
|
|
516
|
+
in: this.getDateFnsContext(),
|
|
517
|
+
...options,
|
|
396
518
|
}),
|
|
397
519
|
);
|
|
398
520
|
}
|
|
399
521
|
|
|
400
522
|
/**
|
|
401
523
|
*/
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
524
|
+
startOfMonth(
|
|
525
|
+
date: string | Date,
|
|
526
|
+
inputFormat: string = this.getIsoFormat(),
|
|
527
|
+
): string {
|
|
528
|
+
return this._get(date, startOfMonth, inputFormat);
|
|
405
529
|
}
|
|
406
530
|
|
|
407
531
|
/**
|
|
408
532
|
*/
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
533
|
+
endOfMonth(
|
|
534
|
+
date: string | Date,
|
|
535
|
+
inputFormat: string = this.getIsoFormat(),
|
|
536
|
+
): string {
|
|
537
|
+
return this._get(date, endOfMonth, inputFormat);
|
|
412
538
|
}
|
|
413
539
|
|
|
414
540
|
/**
|
|
415
541
|
*/
|
|
416
|
-
|
|
417
|
-
|
|
542
|
+
startOfWeek(
|
|
543
|
+
date: string | Date,
|
|
544
|
+
inputFormat: string = this.getIsoFormat(),
|
|
545
|
+
): string {
|
|
546
|
+
const { weekStartsOn } = this.getOptions();
|
|
547
|
+
return this._get(date, startOfWeek, inputFormat, {
|
|
548
|
+
weekStartsOn,
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
*/
|
|
554
|
+
getHours(
|
|
555
|
+
date: string | Date,
|
|
556
|
+
inputFormat: string = this.getIsoFormat(),
|
|
557
|
+
): number {
|
|
558
|
+
const parsedDate = this.toDate(date, inputFormat);
|
|
559
|
+
return getHours(parsedDate, { in: this.getDateFnsContext() });
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
*/
|
|
564
|
+
getMinutes(
|
|
565
|
+
date: string | Date,
|
|
566
|
+
inputFormat: string = this.getIsoFormat(),
|
|
567
|
+
): number {
|
|
568
|
+
const parsedDate = this.toDate(date, inputFormat);
|
|
569
|
+
return getMinutes(parsedDate, { in: this.getDateFnsContext() });
|
|
570
|
+
}
|
|
418
571
|
|
|
419
|
-
|
|
572
|
+
/**
|
|
573
|
+
*/
|
|
574
|
+
getWeek(
|
|
575
|
+
date: string | Date,
|
|
576
|
+
inputFormat: string = this.getIsoFormat(),
|
|
577
|
+
): number {
|
|
578
|
+
const { weekStartsOn, firstWeekContainsDate } = this.getOptions();
|
|
579
|
+
const parsedDate = this.toDate(date, inputFormat);
|
|
580
|
+
return getWeek(parsedDate, {
|
|
581
|
+
in: this.getDateFnsContext(),
|
|
420
582
|
weekStartsOn,
|
|
421
583
|
firstWeekContainsDate,
|
|
422
584
|
});
|
|
423
585
|
}
|
|
424
586
|
|
|
587
|
+
//////////// SETTERS
|
|
588
|
+
|
|
425
589
|
/**
|
|
426
|
-
*
|
|
590
|
+
* @private
|
|
427
591
|
*/
|
|
428
|
-
|
|
429
|
-
|
|
592
|
+
_set(
|
|
593
|
+
date: string | Date,
|
|
594
|
+
property: string,
|
|
595
|
+
value: number,
|
|
596
|
+
inputFormat: string = this.getIsoFormat(),
|
|
597
|
+
): string {
|
|
598
|
+
const parsedDate = this.toDate(date, inputFormat);
|
|
599
|
+
return this.toISO(
|
|
600
|
+
set(
|
|
601
|
+
parsedDate,
|
|
602
|
+
{ [property]: value },
|
|
603
|
+
// {
|
|
604
|
+
// in: this.getDateFnsContext(),
|
|
605
|
+
// },
|
|
606
|
+
),
|
|
607
|
+
);
|
|
430
608
|
}
|
|
431
609
|
|
|
432
610
|
/**
|
|
433
611
|
*/
|
|
434
|
-
|
|
435
|
-
|
|
612
|
+
setYear(
|
|
613
|
+
date: string | Date,
|
|
614
|
+
year: number,
|
|
615
|
+
inputFormat: string = this.getIsoFormat(),
|
|
616
|
+
): string {
|
|
617
|
+
return this._set(date, "year", year, inputFormat);
|
|
436
618
|
}
|
|
437
619
|
|
|
438
620
|
/**
|
|
439
621
|
*/
|
|
440
|
-
|
|
441
|
-
|
|
622
|
+
setMonth(
|
|
623
|
+
date: string | Date,
|
|
624
|
+
month: number,
|
|
625
|
+
inputFormat: string = this.getIsoFormat(),
|
|
626
|
+
): string {
|
|
627
|
+
return this._set(date, "month", month, inputFormat);
|
|
442
628
|
}
|
|
443
629
|
|
|
444
630
|
/**
|
|
445
631
|
*/
|
|
446
|
-
|
|
447
|
-
|
|
632
|
+
setDay(
|
|
633
|
+
date: string | Date,
|
|
634
|
+
day: number,
|
|
635
|
+
inputFormat: string = this.getIsoFormat(),
|
|
636
|
+
): string {
|
|
637
|
+
return this._set(date, "date", day, inputFormat);
|
|
448
638
|
}
|
|
449
639
|
|
|
450
640
|
/**
|
|
451
641
|
*/
|
|
452
|
-
|
|
453
|
-
|
|
642
|
+
setHour(
|
|
643
|
+
date: string | Date,
|
|
644
|
+
hour: number,
|
|
645
|
+
inputFormat: string = this.getIsoFormat(),
|
|
646
|
+
): string {
|
|
647
|
+
return this._set(date, "hours", hour, inputFormat);
|
|
454
648
|
}
|
|
455
649
|
|
|
456
650
|
/**
|
|
457
651
|
*/
|
|
458
|
-
|
|
459
|
-
|
|
652
|
+
setMinute(
|
|
653
|
+
date: string | Date,
|
|
654
|
+
minute: number,
|
|
655
|
+
inputFormat: string = this.getIsoFormat(),
|
|
656
|
+
): string {
|
|
657
|
+
return this._set(date, "minutes", minute, inputFormat);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
*/
|
|
662
|
+
setSecond(
|
|
663
|
+
date: string | Date,
|
|
664
|
+
second: number,
|
|
665
|
+
inputFormat: string = this.getIsoFormat(),
|
|
666
|
+
): string {
|
|
667
|
+
return this._set(date, "seconds", second, inputFormat);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
*/
|
|
672
|
+
setMilliseconds(
|
|
673
|
+
date: string | Date,
|
|
674
|
+
millisecond: number,
|
|
675
|
+
inputFormat: string = this.getIsoFormat(),
|
|
676
|
+
): string {
|
|
677
|
+
return this._set(date, "milliseconds", millisecond, inputFormat);
|
|
460
678
|
}
|
|
461
679
|
|
|
462
680
|
/**
|
|
@@ -467,16 +685,108 @@ class BaseDateTimeUtil {
|
|
|
467
685
|
minutes: number,
|
|
468
686
|
seconds: number,
|
|
469
687
|
milliseconds: number,
|
|
688
|
+
inputFormat: string = this.getIsoFormat(),
|
|
470
689
|
): string {
|
|
690
|
+
const parsedDate = this.toDate(date, inputFormat);
|
|
471
691
|
return this.toISO(
|
|
472
|
-
set(
|
|
473
|
-
|
|
474
|
-
minutes,
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
692
|
+
set(
|
|
693
|
+
parsedDate,
|
|
694
|
+
{ hours, minutes, seconds, milliseconds },
|
|
695
|
+
{
|
|
696
|
+
in: this.getDateFnsContext(),
|
|
697
|
+
},
|
|
698
|
+
),
|
|
478
699
|
);
|
|
479
700
|
}
|
|
701
|
+
|
|
702
|
+
//////////// Timezone related
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
*/
|
|
706
|
+
getTimeZone(): string {
|
|
707
|
+
return this._timeZone;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
*/
|
|
712
|
+
setTimeZone(timeZone: string) {
|
|
713
|
+
this._timeZone = timeZone;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
*/
|
|
718
|
+
getDateFnsContext(): null | Function {
|
|
719
|
+
if (IS_GRAALJS) {
|
|
720
|
+
return null; // tz method does not work in graal (yet)
|
|
721
|
+
}
|
|
722
|
+
return tz(this.getTimeZone());
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
//////////// Offsets
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
*/
|
|
729
|
+
getOffset(
|
|
730
|
+
date: string | Date,
|
|
731
|
+
inputFormat: string = this.getIsoFormat(),
|
|
732
|
+
): OffsetInfo | null {
|
|
733
|
+
const parsedDate = this.toDate(date, inputFormat);
|
|
734
|
+
if (isValid(parsedDate)) {
|
|
735
|
+
const dateOffset = this.toFormat(parsedDate, DATETIME_OFFSET_FORMAT);
|
|
736
|
+
const offsets = this.getTimezoneOffsets();
|
|
737
|
+
if (
|
|
738
|
+
typeof offsets.daylight !== "undefined" &&
|
|
739
|
+
offsets.daylight.value === dateOffset
|
|
740
|
+
) {
|
|
741
|
+
return offsets.daylight;
|
|
742
|
+
} else if (
|
|
743
|
+
typeof offsets.standard !== "undefined" &&
|
|
744
|
+
offsets.standard.value === dateOffset
|
|
745
|
+
) {
|
|
746
|
+
return offsets.standard;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
return null;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
*/
|
|
754
|
+
getTimezoneOffsets(): {
|
|
755
|
+
standard?: OffsetInfo,
|
|
756
|
+
daylight?: OffsetInfo,
|
|
757
|
+
} {
|
|
758
|
+
const createOffsetObject = (info: OffsetInfoInput): OffsetInfo => {
|
|
759
|
+
const sign = info.offset < 0 ? "-" : "+";
|
|
760
|
+
const absOffset = Math.abs(info.offset);
|
|
761
|
+
const hours = Math.trunc(absOffset);
|
|
762
|
+
const minutes = Math.round((absOffset % 1) * 60);
|
|
763
|
+
|
|
764
|
+
const offsetString = `${sign}${String(hours + (minutes === 60 ? 1 : 0)).padStart(2, "0")}:${String(minutes % 60).padStart(2, "0")}`;
|
|
765
|
+
|
|
766
|
+
return {
|
|
767
|
+
label: info.name,
|
|
768
|
+
abbr: info.abbr,
|
|
769
|
+
value: offsetString,
|
|
770
|
+
};
|
|
771
|
+
};
|
|
772
|
+
|
|
773
|
+
const timezone = soft(this.getTimeZone());
|
|
774
|
+
|
|
775
|
+
if (timezone.length === 0) {
|
|
776
|
+
return {};
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
const { daylight, standard } = timezone[0];
|
|
780
|
+
|
|
781
|
+
if (daylight) {
|
|
782
|
+
return {
|
|
783
|
+
daylight: createOffsetObject(daylight),
|
|
784
|
+
standard: createOffsetObject(standard),
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
return { standard: createOffsetObject(standard) };
|
|
789
|
+
}
|
|
480
790
|
}
|
|
481
791
|
|
|
482
792
|
/**
|