@koine/browser 2.0.0-beta.121 → 2.0.0-beta.123

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.
@@ -2,9 +2,659 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var dateFnsTz = require('date-fns-tz');
6
5
  var utils = require('@koine/utils');
7
6
 
7
+ /**
8
+ * Returns the [year, month, day, hour, minute, seconds] tokens of the provided
9
+ * `date` as it will be rendered in the `timeZone`.
10
+ */ function _instanceof$1(left, right) {
11
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
12
+ return !!right[Symbol.hasInstance](left);
13
+ } else {
14
+ return left instanceof right;
15
+ }
16
+ }
17
+ function tzTokenizeDate(date, timeZone) {
18
+ var dtf = getDateTimeFormat(timeZone);
19
+ return 'formatToParts' in dtf ? partsOffset(dtf, date) : hackyOffset(dtf, date);
20
+ }
21
+ var typeToPos = {
22
+ year: 0,
23
+ month: 1,
24
+ day: 2,
25
+ hour: 3,
26
+ minute: 4,
27
+ second: 5
28
+ };
29
+ function partsOffset(dtf, date) {
30
+ try {
31
+ var formatted = dtf.formatToParts(date);
32
+ var filled = [];
33
+ for(var i = 0; i < formatted.length; i++){
34
+ var pos = typeToPos[formatted[i].type];
35
+ if (pos !== undefined) {
36
+ filled[pos] = parseInt(formatted[i].value, 10);
37
+ }
38
+ }
39
+ return filled;
40
+ } catch (error) {
41
+ if (_instanceof$1(error, RangeError)) {
42
+ return [
43
+ NaN
44
+ ];
45
+ }
46
+ throw error;
47
+ }
48
+ }
49
+ function hackyOffset(dtf, date) {
50
+ var formatted = dtf.format(date);
51
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
52
+ var parsed = /(\d+)\/(\d+)\/(\d+),? (\d+):(\d+):(\d+)/.exec(formatted);
53
+ // const [, fMonth, fDay, fYear, fHour, fMinute, fSecond] = parsed
54
+ // return [fYear, fMonth, fDay, fHour, fMinute, fSecond]
55
+ return [
56
+ parseInt(parsed[3], 10),
57
+ parseInt(parsed[1], 10),
58
+ parseInt(parsed[2], 10),
59
+ parseInt(parsed[4], 10),
60
+ parseInt(parsed[5], 10),
61
+ parseInt(parsed[6], 10)
62
+ ];
63
+ }
64
+ // Get a cached Intl.DateTimeFormat instance for the IANA `timeZone`. This can be used
65
+ // to get deterministic local date/time output according to the `en-US` locale which
66
+ // can be used to extract local time parts as necessary.
67
+ var dtfCache = {};
68
+ function getDateTimeFormat(timeZone) {
69
+ if (!dtfCache[timeZone]) {
70
+ // New browsers use `hourCycle`, IE and Chrome <73 does not support it and uses `hour12`
71
+ var testDateFormatted = new Intl.DateTimeFormat('en-US', {
72
+ hourCycle: 'h23',
73
+ timeZone: 'America/New_York',
74
+ year: 'numeric',
75
+ month: '2-digit',
76
+ day: '2-digit',
77
+ hour: '2-digit',
78
+ minute: '2-digit',
79
+ second: '2-digit'
80
+ }).format(new Date('2014-06-25T04:00:00.123Z'));
81
+ var hourCycleSupported = testDateFormatted === '06/25/2014, 00:00:00' || testDateFormatted === '‎06‎/‎25‎/‎2014‎ ‎00‎:‎00‎:‎00';
82
+ dtfCache[timeZone] = hourCycleSupported ? new Intl.DateTimeFormat('en-US', {
83
+ hourCycle: 'h23',
84
+ timeZone: timeZone,
85
+ year: 'numeric',
86
+ month: 'numeric',
87
+ day: '2-digit',
88
+ hour: '2-digit',
89
+ minute: '2-digit',
90
+ second: '2-digit'
91
+ }) : new Intl.DateTimeFormat('en-US', {
92
+ hour12: false,
93
+ timeZone: timeZone,
94
+ year: 'numeric',
95
+ month: 'numeric',
96
+ day: '2-digit',
97
+ hour: '2-digit',
98
+ minute: '2-digit',
99
+ second: '2-digit'
100
+ });
101
+ }
102
+ return dtfCache[timeZone];
103
+ }
104
+
105
+ /**
106
+ * Use instead of `new Date(Date.UTC(...))` to support years below 100 which doesn't work
107
+ * otherwise due to the nature of the
108
+ * [`Date` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#interpretation_of_two-digit_years.
109
+ *
110
+ * For `Date.UTC(...)`, use `newDateUTC(...).getTime()`.
111
+ */ function newDateUTC(fullYear, month, day, hour, minute, second, millisecond) {
112
+ var utcDate = new Date(0);
113
+ utcDate.setUTCFullYear(fullYear, month, day);
114
+ utcDate.setUTCHours(hour, minute, second, millisecond);
115
+ return utcDate;
116
+ }
117
+
118
+ var MILLISECONDS_IN_HOUR$1 = 3600000;
119
+ var MILLISECONDS_IN_MINUTE$1 = 60000;
120
+ var patterns$1 = {
121
+ timezone: /([Z+-].*)$/,
122
+ timezoneZ: /^(Z)$/,
123
+ timezoneHH: /^([+-]\d{2})$/,
124
+ timezoneHHMM: /^([+-])(\d{2}):?(\d{2})$/
125
+ };
126
+ // Parse constious time zone offset formats to an offset in milliseconds
127
+ function tzParseTimezone(timezoneString, date, isUtcDate) {
128
+ // Empty string
129
+ if (!timezoneString) {
130
+ return 0;
131
+ }
132
+ // Z
133
+ var token = patterns$1.timezoneZ.exec(timezoneString);
134
+ if (token) {
135
+ return 0;
136
+ }
137
+ var hours;
138
+ var absoluteOffset;
139
+ // ±hh
140
+ token = patterns$1.timezoneHH.exec(timezoneString);
141
+ if (token) {
142
+ hours = parseInt(token[1], 10);
143
+ if (!validateTimezone(hours)) {
144
+ return NaN;
145
+ }
146
+ return -(hours * MILLISECONDS_IN_HOUR$1);
147
+ }
148
+ // ±hh:mm or ±hhmm
149
+ token = patterns$1.timezoneHHMM.exec(timezoneString);
150
+ if (token) {
151
+ hours = parseInt(token[2], 10);
152
+ var minutes = parseInt(token[3], 10);
153
+ if (!validateTimezone(hours, minutes)) {
154
+ return NaN;
155
+ }
156
+ absoluteOffset = Math.abs(hours) * MILLISECONDS_IN_HOUR$1 + minutes * MILLISECONDS_IN_MINUTE$1;
157
+ return token[1] === '+' ? -absoluteOffset : absoluteOffset;
158
+ }
159
+ // IANA time zone
160
+ if (isValidTimezoneIANAString(timezoneString)) {
161
+ date = new Date(date || Date.now());
162
+ var utcDate = isUtcDate ? date : toUtcDate(date);
163
+ var offset = calcOffset(utcDate, timezoneString);
164
+ var fixedOffset = isUtcDate ? offset : fixOffset(date, offset, timezoneString);
165
+ return -fixedOffset;
166
+ }
167
+ return NaN;
168
+ }
169
+ function toUtcDate(date) {
170
+ return newDateUTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
171
+ }
172
+ function calcOffset(date, timezoneString) {
173
+ var tokens = tzTokenizeDate(date, timezoneString);
174
+ // ms dropped because it's not provided by tzTokenizeDate
175
+ var asUTC = newDateUTC(tokens[0], tokens[1] - 1, tokens[2], tokens[3] % 24, tokens[4], tokens[5], 0).getTime();
176
+ var asTS = date.getTime();
177
+ var over = asTS % 1000;
178
+ asTS -= over >= 0 ? over : 1000 + over;
179
+ return asUTC - asTS;
180
+ }
181
+ function fixOffset(date, offset, timezoneString) {
182
+ var localTS = date.getTime();
183
+ // Our UTC time is just a guess because our offset is just a guess
184
+ var utcGuess = localTS - offset;
185
+ // Test whether the zone matches the offset for this ts
186
+ var o2 = calcOffset(new Date(utcGuess), timezoneString);
187
+ // If so, offset didn't change, and we're done
188
+ if (offset === o2) {
189
+ return offset;
190
+ }
191
+ // If not, change the ts by the difference in the offset
192
+ utcGuess -= o2 - offset;
193
+ // If that gives us the local time we want, we're done
194
+ var o3 = calcOffset(new Date(utcGuess), timezoneString);
195
+ if (o2 === o3) {
196
+ return o2;
197
+ }
198
+ // If it's different, we're in a hole time. The offset has changed, but we don't adjust the time
199
+ return Math.max(o2, o3);
200
+ }
201
+ function validateTimezone(hours, minutes) {
202
+ return -23 <= hours && hours <= 23 && (minutes == null || 0 <= minutes && minutes <= 59);
203
+ }
204
+ var validIANATimezoneCache = {};
205
+ function isValidTimezoneIANAString(timeZoneString) {
206
+ if (validIANATimezoneCache[timeZoneString]) return true;
207
+ try {
208
+ new Intl.DateTimeFormat(undefined, {
209
+ timeZone: timeZoneString
210
+ });
211
+ validIANATimezoneCache[timeZoneString] = true;
212
+ return true;
213
+ } catch (error) {
214
+ return false;
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Google Chrome as of 67.0.3396.87 introduced timezones with offset that includes seconds.
220
+ * They usually appear for dates that denote time before the timezones were introduced
221
+ * (e.g. for 'Europe/Prague' timezone the offset is GMT+00:57:44 before 1 October 1891
222
+ * and GMT+01:00:00 after that date)
223
+ *
224
+ * Date#getTimezoneOffset returns the offset in minutes and would return 57 for the example above,
225
+ * which would lead to incorrect calculations.
226
+ *
227
+ * This function returns the timezone offset in milliseconds that takes seconds in account.
228
+ */ function getTimezoneOffsetInMilliseconds(date) {
229
+ var utcDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()));
230
+ utcDate.setUTCFullYear(date.getFullYear());
231
+ return +date - +utcDate;
232
+ }
233
+
234
+ /** Regex to identify the presence of a time zone specifier in a date string */ var tzPattern = /(Z|[+-]\d{2}(?::?\d{2})?| UTC| [a-zA-Z]+\/[a-zA-Z_]+(?:\/[a-zA-Z_]+)?)$/;
235
+
236
+ function _instanceof(left, right) {
237
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
238
+ return !!right[Symbol.hasInstance](left);
239
+ } else {
240
+ return left instanceof right;
241
+ }
242
+ }
243
+ var MILLISECONDS_IN_HOUR = 3600000;
244
+ var MILLISECONDS_IN_MINUTE = 60000;
245
+ var DEFAULT_ADDITIONAL_DIGITS = 2;
246
+ var patterns = {
247
+ dateTimePattern: /^([0-9W+-]+)(T| )(.*)/,
248
+ datePattern: /^([0-9W+-]+)(.*)/,
249
+ plainTime: /:/,
250
+ // year tokens
251
+ YY: /^(\d{2})$/,
252
+ YYY: [
253
+ /^([+-]\d{2})$/,
254
+ /^([+-]\d{3})$/,
255
+ /^([+-]\d{4})$/
256
+ ],
257
+ YYYY: /^(\d{4})/,
258
+ YYYYY: [
259
+ /^([+-]\d{4})/,
260
+ /^([+-]\d{5})/,
261
+ /^([+-]\d{6})/
262
+ ],
263
+ // date tokens
264
+ MM: /^-(\d{2})$/,
265
+ DDD: /^-?(\d{3})$/,
266
+ MMDD: /^-?(\d{2})-?(\d{2})$/,
267
+ Www: /^-?W(\d{2})$/,
268
+ WwwD: /^-?W(\d{2})-?(\d{1})$/,
269
+ HH: /^(\d{2}([.,]\d*)?)$/,
270
+ HHMM: /^(\d{2}):?(\d{2}([.,]\d*)?)$/,
271
+ HHMMSS: /^(\d{2}):?(\d{2}):?(\d{2}([.,]\d*)?)$/,
272
+ // time zone tokens (to identify the presence of a tz)
273
+ timeZone: tzPattern
274
+ };
275
+ /**
276
+ * @name toDate
277
+ * @category Common Helpers
278
+ * @summary Convert the given argument to an instance of Date.
279
+ *
280
+ * @description
281
+ * Convert the given argument to an instance of Date.
282
+ *
283
+ * If the argument is an instance of Date, the function returns its clone.
284
+ *
285
+ * If the argument is a number, it is treated as a timestamp.
286
+ *
287
+ * If an argument is a string, the function tries to parse it.
288
+ * Function accepts complete ISO 8601 formats as well as partial implementations.
289
+ * ISO 8601: http://en.wikipedia.org/wiki/ISO_8601
290
+ * If the function cannot parse the string or the values are invalid, it returns Invalid Date.
291
+ *
292
+ * If the argument is none of the above, the function returns Invalid Date.
293
+ *
294
+ * **Note**: *all* Date arguments passed to any *date-fns* function is processed by `toDate`.
295
+ * All *date-fns* functions will throw `RangeError` if `options.additionalDigits` is not 0, 1, 2 or undefined.
296
+ *
297
+ * @param argument the value to convert
298
+ * @param options the object with options. See [Options]{@link https://date-fns.org/docs/Options}
299
+ * @param {0|1|2} [options.additionalDigits=2] - the additional number of digits in the extended year format
300
+ * @param {string} [options.timeZone=''] - used to specify the IANA time zone offset of a date String.
301
+ *
302
+ * @returns the parsed date in the local time zone
303
+ * @throws {TypeError} 1 argument required
304
+ * @throws {RangeError} `options.additionalDigits` must be 0, 1 or 2
305
+ *
306
+ * @example
307
+ * // Convert string '2014-02-11T11:30:30' to date:
308
+ * const result = toDate('2014-02-11T11:30:30')
309
+ * //=> Tue Feb 11 2014 11:30:30
310
+ *
311
+ * @example
312
+ * // Convert string '+02014101' to date,
313
+ * // if the additional number of digits in the extended year format is 1:
314
+ * const result = toDate('+02014101', {additionalDigits: 1})
315
+ * //=> Fri Apr 11 2014 00:00:00
316
+ */ function toDate(argument) {
317
+ var options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
318
+ if (arguments.length < 1) {
319
+ throw new TypeError('1 argument required, but only ' + arguments.length + ' present');
320
+ }
321
+ if (argument === null) {
322
+ return new Date(NaN);
323
+ }
324
+ var additionalDigits = options.additionalDigits == null ? DEFAULT_ADDITIONAL_DIGITS : Number(options.additionalDigits);
325
+ if (additionalDigits !== 2 && additionalDigits !== 1 && additionalDigits !== 0) {
326
+ throw new RangeError('additionalDigits must be 0, 1 or 2');
327
+ }
328
+ // Clone the date
329
+ if (_instanceof(argument, Date) || typeof argument === 'object' && Object.prototype.toString.call(argument) === '[object Date]') {
330
+ // Prevent the date to lose the milliseconds when passed to new Date() in IE10
331
+ return new Date(argument.getTime());
332
+ } else if (typeof argument === 'number' || Object.prototype.toString.call(argument) === '[object Number]') {
333
+ return new Date(argument);
334
+ } else if (!(Object.prototype.toString.call(argument) === '[object String]')) {
335
+ return new Date(NaN);
336
+ }
337
+ var dateStrings = splitDateString(argument);
338
+ var _parseYear = parseYear(dateStrings.date, additionalDigits), year = _parseYear.year, restDateString = _parseYear.restDateString;
339
+ var date = parseDate(restDateString, year);
340
+ if (date === null || isNaN(date.getTime())) {
341
+ return new Date(NaN);
342
+ }
343
+ if (date) {
344
+ var timestamp = date.getTime();
345
+ var time = 0;
346
+ var offset;
347
+ if (dateStrings.time) {
348
+ time = parseTime(dateStrings.time);
349
+ if (time === null || isNaN(time)) {
350
+ return new Date(NaN);
351
+ }
352
+ }
353
+ if (dateStrings.timeZone || options.timeZone) {
354
+ offset = tzParseTimezone(dateStrings.timeZone || options.timeZone, new Date(timestamp + time));
355
+ if (isNaN(offset)) {
356
+ return new Date(NaN);
357
+ }
358
+ } else {
359
+ // get offset accurate to hour in time zones that change offset
360
+ offset = getTimezoneOffsetInMilliseconds(new Date(timestamp + time));
361
+ offset = getTimezoneOffsetInMilliseconds(new Date(timestamp + time + offset));
362
+ }
363
+ return new Date(timestamp + time + offset);
364
+ } else {
365
+ return new Date(NaN);
366
+ }
367
+ }
368
+ function splitDateString(dateString) {
369
+ var dateStrings = {};
370
+ var parts = patterns.dateTimePattern.exec(dateString);
371
+ var timeString;
372
+ if (!parts) {
373
+ parts = patterns.datePattern.exec(dateString);
374
+ if (parts) {
375
+ dateStrings.date = parts[1];
376
+ timeString = parts[2];
377
+ } else {
378
+ dateStrings.date = null;
379
+ timeString = dateString;
380
+ }
381
+ } else {
382
+ dateStrings.date = parts[1];
383
+ timeString = parts[3];
384
+ }
385
+ if (timeString) {
386
+ var token = patterns.timeZone.exec(timeString);
387
+ if (token) {
388
+ dateStrings.time = timeString.replace(token[1], '');
389
+ dateStrings.timeZone = token[1].trim();
390
+ } else {
391
+ dateStrings.time = timeString;
392
+ }
393
+ }
394
+ return dateStrings;
395
+ }
396
+ function parseYear(dateString, additionalDigits) {
397
+ if (dateString) {
398
+ var patternYYY = patterns.YYY[additionalDigits];
399
+ var patternYYYYY = patterns.YYYYY[additionalDigits];
400
+ // YYYY or ±YYYYY
401
+ var token = patterns.YYYY.exec(dateString) || patternYYYYY.exec(dateString);
402
+ if (token) {
403
+ var yearString = token[1];
404
+ return {
405
+ year: parseInt(yearString, 10),
406
+ restDateString: dateString.slice(yearString.length)
407
+ };
408
+ }
409
+ // YY or ±YYY
410
+ token = patterns.YY.exec(dateString) || patternYYY.exec(dateString);
411
+ if (token) {
412
+ var centuryString = token[1];
413
+ return {
414
+ year: parseInt(centuryString, 10) * 100,
415
+ restDateString: dateString.slice(centuryString.length)
416
+ };
417
+ }
418
+ }
419
+ // Invalid ISO-formatted year
420
+ return {
421
+ year: null
422
+ };
423
+ }
424
+ function parseDate(dateString, year) {
425
+ // Invalid ISO-formatted year
426
+ if (year === null) {
427
+ return null;
428
+ }
429
+ var date;
430
+ var month;
431
+ var week;
432
+ // YYYY
433
+ if (!dateString || !dateString.length) {
434
+ date = new Date(0);
435
+ date.setUTCFullYear(year);
436
+ return date;
437
+ }
438
+ // YYYY-MM
439
+ var token = patterns.MM.exec(dateString);
440
+ if (token) {
441
+ date = new Date(0);
442
+ month = parseInt(token[1], 10) - 1;
443
+ if (!validateDate(year, month)) {
444
+ return new Date(NaN);
445
+ }
446
+ date.setUTCFullYear(year, month);
447
+ return date;
448
+ }
449
+ // YYYY-DDD or YYYYDDD
450
+ token = patterns.DDD.exec(dateString);
451
+ if (token) {
452
+ date = new Date(0);
453
+ var dayOfYear = parseInt(token[1], 10);
454
+ if (!validateDayOfYearDate(year, dayOfYear)) {
455
+ return new Date(NaN);
456
+ }
457
+ date.setUTCFullYear(year, 0, dayOfYear);
458
+ return date;
459
+ }
460
+ // yyyy-MM-dd or YYYYMMDD
461
+ token = patterns.MMDD.exec(dateString);
462
+ if (token) {
463
+ date = new Date(0);
464
+ month = parseInt(token[1], 10) - 1;
465
+ var day = parseInt(token[2], 10);
466
+ if (!validateDate(year, month, day)) {
467
+ return new Date(NaN);
468
+ }
469
+ date.setUTCFullYear(year, month, day);
470
+ return date;
471
+ }
472
+ // YYYY-Www or YYYYWww
473
+ token = patterns.Www.exec(dateString);
474
+ if (token) {
475
+ week = parseInt(token[1], 10) - 1;
476
+ if (!validateWeekDate(week)) {
477
+ return new Date(NaN);
478
+ }
479
+ return dayOfISOWeekYear(year, week);
480
+ }
481
+ // YYYY-Www-D or YYYYWwwD
482
+ token = patterns.WwwD.exec(dateString);
483
+ if (token) {
484
+ week = parseInt(token[1], 10) - 1;
485
+ var dayOfWeek = parseInt(token[2], 10) - 1;
486
+ if (!validateWeekDate(week, dayOfWeek)) {
487
+ return new Date(NaN);
488
+ }
489
+ return dayOfISOWeekYear(year, week, dayOfWeek);
490
+ }
491
+ // Invalid ISO-formatted date
492
+ return null;
493
+ }
494
+ function parseTime(timeString) {
495
+ var hours;
496
+ var minutes;
497
+ // hh
498
+ var token = patterns.HH.exec(timeString);
499
+ if (token) {
500
+ hours = parseFloat(token[1].replace(',', '.'));
501
+ if (!validateTime(hours)) {
502
+ return NaN;
503
+ }
504
+ return hours % 24 * MILLISECONDS_IN_HOUR;
505
+ }
506
+ // hh:mm or hhmm
507
+ token = patterns.HHMM.exec(timeString);
508
+ if (token) {
509
+ hours = parseInt(token[1], 10);
510
+ minutes = parseFloat(token[2].replace(',', '.'));
511
+ if (!validateTime(hours, minutes)) {
512
+ return NaN;
513
+ }
514
+ return hours % 24 * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE;
515
+ }
516
+ // hh:mm:ss or hhmmss
517
+ token = patterns.HHMMSS.exec(timeString);
518
+ if (token) {
519
+ hours = parseInt(token[1], 10);
520
+ minutes = parseInt(token[2], 10);
521
+ var seconds = parseFloat(token[3].replace(',', '.'));
522
+ if (!validateTime(hours, minutes, seconds)) {
523
+ return NaN;
524
+ }
525
+ return hours % 24 * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE + seconds * 1000;
526
+ }
527
+ // Invalid ISO-formatted time
528
+ return null;
529
+ }
530
+ function dayOfISOWeekYear(isoWeekYear, week, day) {
531
+ week = week || 0;
532
+ day = day || 0;
533
+ var date = new Date(0);
534
+ date.setUTCFullYear(isoWeekYear, 0, 4);
535
+ var fourthOfJanuaryDay = date.getUTCDay() || 7;
536
+ var diff = week * 7 + day + 1 - fourthOfJanuaryDay;
537
+ date.setUTCDate(date.getUTCDate() + diff);
538
+ return date;
539
+ }
540
+ // Validation functions
541
+ var DAYS_IN_MONTH = [
542
+ 31,
543
+ 28,
544
+ 31,
545
+ 30,
546
+ 31,
547
+ 30,
548
+ 31,
549
+ 31,
550
+ 30,
551
+ 31,
552
+ 30,
553
+ 31
554
+ ];
555
+ var DAYS_IN_MONTH_LEAP_YEAR = [
556
+ 31,
557
+ 29,
558
+ 31,
559
+ 30,
560
+ 31,
561
+ 30,
562
+ 31,
563
+ 31,
564
+ 30,
565
+ 31,
566
+ 30,
567
+ 31
568
+ ];
569
+ function isLeapYearIndex(year) {
570
+ return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;
571
+ }
572
+ function validateDate(year, month, date) {
573
+ if (month < 0 || month > 11) {
574
+ return false;
575
+ }
576
+ if (date != null) {
577
+ if (date < 1) {
578
+ return false;
579
+ }
580
+ var isLeapYear = isLeapYearIndex(year);
581
+ if (isLeapYear && date > DAYS_IN_MONTH_LEAP_YEAR[month]) {
582
+ return false;
583
+ }
584
+ if (!isLeapYear && date > DAYS_IN_MONTH[month]) {
585
+ return false;
586
+ }
587
+ }
588
+ return true;
589
+ }
590
+ function validateDayOfYearDate(year, dayOfYear) {
591
+ if (dayOfYear < 1) {
592
+ return false;
593
+ }
594
+ var isLeapYear = isLeapYearIndex(year);
595
+ if (isLeapYear && dayOfYear > 366) {
596
+ return false;
597
+ }
598
+ if (!isLeapYear && dayOfYear > 365) {
599
+ return false;
600
+ }
601
+ return true;
602
+ }
603
+ function validateWeekDate(week, day) {
604
+ if (week < 0 || week > 52) {
605
+ return false;
606
+ }
607
+ if (day != null && (day < 0 || day > 6)) {
608
+ return false;
609
+ }
610
+ return true;
611
+ }
612
+ function validateTime(hours, minutes, seconds) {
613
+ if (hours < 0 || hours >= 25) {
614
+ return false;
615
+ }
616
+ if (minutes != null && (minutes < 0 || minutes >= 60)) {
617
+ return false;
618
+ }
619
+ if (seconds != null && (seconds < 0 || seconds >= 60)) {
620
+ return false;
621
+ }
622
+ return true;
623
+ }
624
+
625
+ /**
626
+ * @name toZonedTime
627
+ * @category Time Zone Helpers
628
+ * @summary Get a date/time representing local time in a given time zone from the UTC date
629
+ *
630
+ * @description
631
+ * Returns a date instance with values representing the local time in the time zone
632
+ * specified of the UTC time from the date provided. In other words, when the new date
633
+ * is formatted it will show the equivalent hours in the target time zone regardless
634
+ * of the current system time zone.
635
+ *
636
+ * @param date the date with the relevant UTC time
637
+ * @param timeZone the time zone to get local time for, can be an offset or IANA time zone
638
+ * @param options the object with options. See [Options]{@link https://date-fns.org/docs/Options}
639
+ * @param {0|1|2} [options.additionalDigits=2] - passed to `toDate`. See [toDate]{@link https://date-fns.org/docs/toDate}
640
+ *
641
+ * @throws {TypeError} 2 arguments required
642
+ * @throws {RangeError} `options.additionalDigits` must be 0, 1 or 2
643
+ *
644
+ * @example
645
+ * // In June 10am UTC is 6am in New York (-04:00)
646
+ * const result = toZonedTime('2014-06-25T10:00:00.000Z', 'America/New_York')
647
+ * //=> Jun 25 2014 06:00:00
648
+ */ function toZonedTime(date, timeZone, options) {
649
+ date = toDate(date, options);
650
+ var offsetMilliseconds = tzParseTimezone(timeZone, date, true);
651
+ var d = new Date(date.getTime() - offsetMilliseconds);
652
+ var resultDate = new Date(0);
653
+ resultDate.setFullYear(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate());
654
+ resultDate.setHours(d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());
655
+ return resultDate;
656
+ }
657
+
8
658
  /**
9
659
  * It returns a `Date` object from a date `string` adjusted on the user timeZone,
10
660
  * if a timeZone is not provided we try getting it from the `Intl` browwser native
@@ -20,7 +670,7 @@ var utils = require('@koine/utils');
20
670
  * @param timeZone Optionally pass a timeZone (e.g. from user preference or from the server), it falls back trying to read it from the `Intl` browwser native API.
21
671
  */let getZonedDate=(o="",n)=>{if(o.endsWith("Z")||(o+="Z"),!n&&utils.isBrowser)try{n=Intl.DateTimeFormat().resolvedOptions().timeZone;}catch(e){"development"===process.env.NODE_ENV&&console.warn("[@koine/browser:getZonedDate] failed reading timeZone, error",e);}// no need to do anything here, it just means `Intl` failed, probably
22
672
  // because the browser does not support it
23
- return n?dateFnsTz.toZonedTime(new Date(o),n):new Date(o)};
673
+ return n?toZonedTime(new Date(o),n):new Date(o)};
24
674
 
25
675
  exports.default = getZonedDate;
26
676
  exports.getZonedDate = getZonedDate;
@@ -1,6 +1,656 @@
1
- import { toZonedTime } from 'date-fns-tz';
2
1
  import { isBrowser } from '@koine/utils';
3
2
 
3
+ /**
4
+ * Returns the [year, month, day, hour, minute, seconds] tokens of the provided
5
+ * `date` as it will be rendered in the `timeZone`.
6
+ */ function _instanceof$1(left, right) {
7
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
8
+ return !!right[Symbol.hasInstance](left);
9
+ } else {
10
+ return left instanceof right;
11
+ }
12
+ }
13
+ function tzTokenizeDate(date, timeZone) {
14
+ var dtf = getDateTimeFormat(timeZone);
15
+ return 'formatToParts' in dtf ? partsOffset(dtf, date) : hackyOffset(dtf, date);
16
+ }
17
+ var typeToPos = {
18
+ year: 0,
19
+ month: 1,
20
+ day: 2,
21
+ hour: 3,
22
+ minute: 4,
23
+ second: 5
24
+ };
25
+ function partsOffset(dtf, date) {
26
+ try {
27
+ var formatted = dtf.formatToParts(date);
28
+ var filled = [];
29
+ for(var i = 0; i < formatted.length; i++){
30
+ var pos = typeToPos[formatted[i].type];
31
+ if (pos !== undefined) {
32
+ filled[pos] = parseInt(formatted[i].value, 10);
33
+ }
34
+ }
35
+ return filled;
36
+ } catch (error) {
37
+ if (_instanceof$1(error, RangeError)) {
38
+ return [
39
+ NaN
40
+ ];
41
+ }
42
+ throw error;
43
+ }
44
+ }
45
+ function hackyOffset(dtf, date) {
46
+ var formatted = dtf.format(date);
47
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
48
+ var parsed = /(\d+)\/(\d+)\/(\d+),? (\d+):(\d+):(\d+)/.exec(formatted);
49
+ // const [, fMonth, fDay, fYear, fHour, fMinute, fSecond] = parsed
50
+ // return [fYear, fMonth, fDay, fHour, fMinute, fSecond]
51
+ return [
52
+ parseInt(parsed[3], 10),
53
+ parseInt(parsed[1], 10),
54
+ parseInt(parsed[2], 10),
55
+ parseInt(parsed[4], 10),
56
+ parseInt(parsed[5], 10),
57
+ parseInt(parsed[6], 10)
58
+ ];
59
+ }
60
+ // Get a cached Intl.DateTimeFormat instance for the IANA `timeZone`. This can be used
61
+ // to get deterministic local date/time output according to the `en-US` locale which
62
+ // can be used to extract local time parts as necessary.
63
+ var dtfCache = {};
64
+ function getDateTimeFormat(timeZone) {
65
+ if (!dtfCache[timeZone]) {
66
+ // New browsers use `hourCycle`, IE and Chrome <73 does not support it and uses `hour12`
67
+ var testDateFormatted = new Intl.DateTimeFormat('en-US', {
68
+ hourCycle: 'h23',
69
+ timeZone: 'America/New_York',
70
+ year: 'numeric',
71
+ month: '2-digit',
72
+ day: '2-digit',
73
+ hour: '2-digit',
74
+ minute: '2-digit',
75
+ second: '2-digit'
76
+ }).format(new Date('2014-06-25T04:00:00.123Z'));
77
+ var hourCycleSupported = testDateFormatted === '06/25/2014, 00:00:00' || testDateFormatted === '‎06‎/‎25‎/‎2014‎ ‎00‎:‎00‎:‎00';
78
+ dtfCache[timeZone] = hourCycleSupported ? new Intl.DateTimeFormat('en-US', {
79
+ hourCycle: 'h23',
80
+ timeZone: timeZone,
81
+ year: 'numeric',
82
+ month: 'numeric',
83
+ day: '2-digit',
84
+ hour: '2-digit',
85
+ minute: '2-digit',
86
+ second: '2-digit'
87
+ }) : new Intl.DateTimeFormat('en-US', {
88
+ hour12: false,
89
+ timeZone: timeZone,
90
+ year: 'numeric',
91
+ month: 'numeric',
92
+ day: '2-digit',
93
+ hour: '2-digit',
94
+ minute: '2-digit',
95
+ second: '2-digit'
96
+ });
97
+ }
98
+ return dtfCache[timeZone];
99
+ }
100
+
101
+ /**
102
+ * Use instead of `new Date(Date.UTC(...))` to support years below 100 which doesn't work
103
+ * otherwise due to the nature of the
104
+ * [`Date` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#interpretation_of_two-digit_years.
105
+ *
106
+ * For `Date.UTC(...)`, use `newDateUTC(...).getTime()`.
107
+ */ function newDateUTC(fullYear, month, day, hour, minute, second, millisecond) {
108
+ var utcDate = new Date(0);
109
+ utcDate.setUTCFullYear(fullYear, month, day);
110
+ utcDate.setUTCHours(hour, minute, second, millisecond);
111
+ return utcDate;
112
+ }
113
+
114
+ var MILLISECONDS_IN_HOUR$1 = 3600000;
115
+ var MILLISECONDS_IN_MINUTE$1 = 60000;
116
+ var patterns$1 = {
117
+ timezone: /([Z+-].*)$/,
118
+ timezoneZ: /^(Z)$/,
119
+ timezoneHH: /^([+-]\d{2})$/,
120
+ timezoneHHMM: /^([+-])(\d{2}):?(\d{2})$/
121
+ };
122
+ // Parse constious time zone offset formats to an offset in milliseconds
123
+ function tzParseTimezone(timezoneString, date, isUtcDate) {
124
+ // Empty string
125
+ if (!timezoneString) {
126
+ return 0;
127
+ }
128
+ // Z
129
+ var token = patterns$1.timezoneZ.exec(timezoneString);
130
+ if (token) {
131
+ return 0;
132
+ }
133
+ var hours;
134
+ var absoluteOffset;
135
+ // ±hh
136
+ token = patterns$1.timezoneHH.exec(timezoneString);
137
+ if (token) {
138
+ hours = parseInt(token[1], 10);
139
+ if (!validateTimezone(hours)) {
140
+ return NaN;
141
+ }
142
+ return -(hours * MILLISECONDS_IN_HOUR$1);
143
+ }
144
+ // ±hh:mm or ±hhmm
145
+ token = patterns$1.timezoneHHMM.exec(timezoneString);
146
+ if (token) {
147
+ hours = parseInt(token[2], 10);
148
+ var minutes = parseInt(token[3], 10);
149
+ if (!validateTimezone(hours, minutes)) {
150
+ return NaN;
151
+ }
152
+ absoluteOffset = Math.abs(hours) * MILLISECONDS_IN_HOUR$1 + minutes * MILLISECONDS_IN_MINUTE$1;
153
+ return token[1] === '+' ? -absoluteOffset : absoluteOffset;
154
+ }
155
+ // IANA time zone
156
+ if (isValidTimezoneIANAString(timezoneString)) {
157
+ date = new Date(date || Date.now());
158
+ var utcDate = isUtcDate ? date : toUtcDate(date);
159
+ var offset = calcOffset(utcDate, timezoneString);
160
+ var fixedOffset = isUtcDate ? offset : fixOffset(date, offset, timezoneString);
161
+ return -fixedOffset;
162
+ }
163
+ return NaN;
164
+ }
165
+ function toUtcDate(date) {
166
+ return newDateUTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
167
+ }
168
+ function calcOffset(date, timezoneString) {
169
+ var tokens = tzTokenizeDate(date, timezoneString);
170
+ // ms dropped because it's not provided by tzTokenizeDate
171
+ var asUTC = newDateUTC(tokens[0], tokens[1] - 1, tokens[2], tokens[3] % 24, tokens[4], tokens[5], 0).getTime();
172
+ var asTS = date.getTime();
173
+ var over = asTS % 1000;
174
+ asTS -= over >= 0 ? over : 1000 + over;
175
+ return asUTC - asTS;
176
+ }
177
+ function fixOffset(date, offset, timezoneString) {
178
+ var localTS = date.getTime();
179
+ // Our UTC time is just a guess because our offset is just a guess
180
+ var utcGuess = localTS - offset;
181
+ // Test whether the zone matches the offset for this ts
182
+ var o2 = calcOffset(new Date(utcGuess), timezoneString);
183
+ // If so, offset didn't change, and we're done
184
+ if (offset === o2) {
185
+ return offset;
186
+ }
187
+ // If not, change the ts by the difference in the offset
188
+ utcGuess -= o2 - offset;
189
+ // If that gives us the local time we want, we're done
190
+ var o3 = calcOffset(new Date(utcGuess), timezoneString);
191
+ if (o2 === o3) {
192
+ return o2;
193
+ }
194
+ // If it's different, we're in a hole time. The offset has changed, but we don't adjust the time
195
+ return Math.max(o2, o3);
196
+ }
197
+ function validateTimezone(hours, minutes) {
198
+ return -23 <= hours && hours <= 23 && (minutes == null || 0 <= minutes && minutes <= 59);
199
+ }
200
+ var validIANATimezoneCache = {};
201
+ function isValidTimezoneIANAString(timeZoneString) {
202
+ if (validIANATimezoneCache[timeZoneString]) return true;
203
+ try {
204
+ new Intl.DateTimeFormat(undefined, {
205
+ timeZone: timeZoneString
206
+ });
207
+ validIANATimezoneCache[timeZoneString] = true;
208
+ return true;
209
+ } catch (error) {
210
+ return false;
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Google Chrome as of 67.0.3396.87 introduced timezones with offset that includes seconds.
216
+ * They usually appear for dates that denote time before the timezones were introduced
217
+ * (e.g. for 'Europe/Prague' timezone the offset is GMT+00:57:44 before 1 October 1891
218
+ * and GMT+01:00:00 after that date)
219
+ *
220
+ * Date#getTimezoneOffset returns the offset in minutes and would return 57 for the example above,
221
+ * which would lead to incorrect calculations.
222
+ *
223
+ * This function returns the timezone offset in milliseconds that takes seconds in account.
224
+ */ function getTimezoneOffsetInMilliseconds(date) {
225
+ var utcDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()));
226
+ utcDate.setUTCFullYear(date.getFullYear());
227
+ return +date - +utcDate;
228
+ }
229
+
230
+ /** Regex to identify the presence of a time zone specifier in a date string */ var tzPattern = /(Z|[+-]\d{2}(?::?\d{2})?| UTC| [a-zA-Z]+\/[a-zA-Z_]+(?:\/[a-zA-Z_]+)?)$/;
231
+
232
+ function _instanceof(left, right) {
233
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
234
+ return !!right[Symbol.hasInstance](left);
235
+ } else {
236
+ return left instanceof right;
237
+ }
238
+ }
239
+ var MILLISECONDS_IN_HOUR = 3600000;
240
+ var MILLISECONDS_IN_MINUTE = 60000;
241
+ var DEFAULT_ADDITIONAL_DIGITS = 2;
242
+ var patterns = {
243
+ dateTimePattern: /^([0-9W+-]+)(T| )(.*)/,
244
+ datePattern: /^([0-9W+-]+)(.*)/,
245
+ plainTime: /:/,
246
+ // year tokens
247
+ YY: /^(\d{2})$/,
248
+ YYY: [
249
+ /^([+-]\d{2})$/,
250
+ /^([+-]\d{3})$/,
251
+ /^([+-]\d{4})$/
252
+ ],
253
+ YYYY: /^(\d{4})/,
254
+ YYYYY: [
255
+ /^([+-]\d{4})/,
256
+ /^([+-]\d{5})/,
257
+ /^([+-]\d{6})/
258
+ ],
259
+ // date tokens
260
+ MM: /^-(\d{2})$/,
261
+ DDD: /^-?(\d{3})$/,
262
+ MMDD: /^-?(\d{2})-?(\d{2})$/,
263
+ Www: /^-?W(\d{2})$/,
264
+ WwwD: /^-?W(\d{2})-?(\d{1})$/,
265
+ HH: /^(\d{2}([.,]\d*)?)$/,
266
+ HHMM: /^(\d{2}):?(\d{2}([.,]\d*)?)$/,
267
+ HHMMSS: /^(\d{2}):?(\d{2}):?(\d{2}([.,]\d*)?)$/,
268
+ // time zone tokens (to identify the presence of a tz)
269
+ timeZone: tzPattern
270
+ };
271
+ /**
272
+ * @name toDate
273
+ * @category Common Helpers
274
+ * @summary Convert the given argument to an instance of Date.
275
+ *
276
+ * @description
277
+ * Convert the given argument to an instance of Date.
278
+ *
279
+ * If the argument is an instance of Date, the function returns its clone.
280
+ *
281
+ * If the argument is a number, it is treated as a timestamp.
282
+ *
283
+ * If an argument is a string, the function tries to parse it.
284
+ * Function accepts complete ISO 8601 formats as well as partial implementations.
285
+ * ISO 8601: http://en.wikipedia.org/wiki/ISO_8601
286
+ * If the function cannot parse the string or the values are invalid, it returns Invalid Date.
287
+ *
288
+ * If the argument is none of the above, the function returns Invalid Date.
289
+ *
290
+ * **Note**: *all* Date arguments passed to any *date-fns* function is processed by `toDate`.
291
+ * All *date-fns* functions will throw `RangeError` if `options.additionalDigits` is not 0, 1, 2 or undefined.
292
+ *
293
+ * @param argument the value to convert
294
+ * @param options the object with options. See [Options]{@link https://date-fns.org/docs/Options}
295
+ * @param {0|1|2} [options.additionalDigits=2] - the additional number of digits in the extended year format
296
+ * @param {string} [options.timeZone=''] - used to specify the IANA time zone offset of a date String.
297
+ *
298
+ * @returns the parsed date in the local time zone
299
+ * @throws {TypeError} 1 argument required
300
+ * @throws {RangeError} `options.additionalDigits` must be 0, 1 or 2
301
+ *
302
+ * @example
303
+ * // Convert string '2014-02-11T11:30:30' to date:
304
+ * const result = toDate('2014-02-11T11:30:30')
305
+ * //=> Tue Feb 11 2014 11:30:30
306
+ *
307
+ * @example
308
+ * // Convert string '+02014101' to date,
309
+ * // if the additional number of digits in the extended year format is 1:
310
+ * const result = toDate('+02014101', {additionalDigits: 1})
311
+ * //=> Fri Apr 11 2014 00:00:00
312
+ */ function toDate(argument) {
313
+ var options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
314
+ if (arguments.length < 1) {
315
+ throw new TypeError('1 argument required, but only ' + arguments.length + ' present');
316
+ }
317
+ if (argument === null) {
318
+ return new Date(NaN);
319
+ }
320
+ var additionalDigits = options.additionalDigits == null ? DEFAULT_ADDITIONAL_DIGITS : Number(options.additionalDigits);
321
+ if (additionalDigits !== 2 && additionalDigits !== 1 && additionalDigits !== 0) {
322
+ throw new RangeError('additionalDigits must be 0, 1 or 2');
323
+ }
324
+ // Clone the date
325
+ if (_instanceof(argument, Date) || typeof argument === 'object' && Object.prototype.toString.call(argument) === '[object Date]') {
326
+ // Prevent the date to lose the milliseconds when passed to new Date() in IE10
327
+ return new Date(argument.getTime());
328
+ } else if (typeof argument === 'number' || Object.prototype.toString.call(argument) === '[object Number]') {
329
+ return new Date(argument);
330
+ } else if (!(Object.prototype.toString.call(argument) === '[object String]')) {
331
+ return new Date(NaN);
332
+ }
333
+ var dateStrings = splitDateString(argument);
334
+ var _parseYear = parseYear(dateStrings.date, additionalDigits), year = _parseYear.year, restDateString = _parseYear.restDateString;
335
+ var date = parseDate(restDateString, year);
336
+ if (date === null || isNaN(date.getTime())) {
337
+ return new Date(NaN);
338
+ }
339
+ if (date) {
340
+ var timestamp = date.getTime();
341
+ var time = 0;
342
+ var offset;
343
+ if (dateStrings.time) {
344
+ time = parseTime(dateStrings.time);
345
+ if (time === null || isNaN(time)) {
346
+ return new Date(NaN);
347
+ }
348
+ }
349
+ if (dateStrings.timeZone || options.timeZone) {
350
+ offset = tzParseTimezone(dateStrings.timeZone || options.timeZone, new Date(timestamp + time));
351
+ if (isNaN(offset)) {
352
+ return new Date(NaN);
353
+ }
354
+ } else {
355
+ // get offset accurate to hour in time zones that change offset
356
+ offset = getTimezoneOffsetInMilliseconds(new Date(timestamp + time));
357
+ offset = getTimezoneOffsetInMilliseconds(new Date(timestamp + time + offset));
358
+ }
359
+ return new Date(timestamp + time + offset);
360
+ } else {
361
+ return new Date(NaN);
362
+ }
363
+ }
364
+ function splitDateString(dateString) {
365
+ var dateStrings = {};
366
+ var parts = patterns.dateTimePattern.exec(dateString);
367
+ var timeString;
368
+ if (!parts) {
369
+ parts = patterns.datePattern.exec(dateString);
370
+ if (parts) {
371
+ dateStrings.date = parts[1];
372
+ timeString = parts[2];
373
+ } else {
374
+ dateStrings.date = null;
375
+ timeString = dateString;
376
+ }
377
+ } else {
378
+ dateStrings.date = parts[1];
379
+ timeString = parts[3];
380
+ }
381
+ if (timeString) {
382
+ var token = patterns.timeZone.exec(timeString);
383
+ if (token) {
384
+ dateStrings.time = timeString.replace(token[1], '');
385
+ dateStrings.timeZone = token[1].trim();
386
+ } else {
387
+ dateStrings.time = timeString;
388
+ }
389
+ }
390
+ return dateStrings;
391
+ }
392
+ function parseYear(dateString, additionalDigits) {
393
+ if (dateString) {
394
+ var patternYYY = patterns.YYY[additionalDigits];
395
+ var patternYYYYY = patterns.YYYYY[additionalDigits];
396
+ // YYYY or ±YYYYY
397
+ var token = patterns.YYYY.exec(dateString) || patternYYYYY.exec(dateString);
398
+ if (token) {
399
+ var yearString = token[1];
400
+ return {
401
+ year: parseInt(yearString, 10),
402
+ restDateString: dateString.slice(yearString.length)
403
+ };
404
+ }
405
+ // YY or ±YYY
406
+ token = patterns.YY.exec(dateString) || patternYYY.exec(dateString);
407
+ if (token) {
408
+ var centuryString = token[1];
409
+ return {
410
+ year: parseInt(centuryString, 10) * 100,
411
+ restDateString: dateString.slice(centuryString.length)
412
+ };
413
+ }
414
+ }
415
+ // Invalid ISO-formatted year
416
+ return {
417
+ year: null
418
+ };
419
+ }
420
+ function parseDate(dateString, year) {
421
+ // Invalid ISO-formatted year
422
+ if (year === null) {
423
+ return null;
424
+ }
425
+ var date;
426
+ var month;
427
+ var week;
428
+ // YYYY
429
+ if (!dateString || !dateString.length) {
430
+ date = new Date(0);
431
+ date.setUTCFullYear(year);
432
+ return date;
433
+ }
434
+ // YYYY-MM
435
+ var token = patterns.MM.exec(dateString);
436
+ if (token) {
437
+ date = new Date(0);
438
+ month = parseInt(token[1], 10) - 1;
439
+ if (!validateDate(year, month)) {
440
+ return new Date(NaN);
441
+ }
442
+ date.setUTCFullYear(year, month);
443
+ return date;
444
+ }
445
+ // YYYY-DDD or YYYYDDD
446
+ token = patterns.DDD.exec(dateString);
447
+ if (token) {
448
+ date = new Date(0);
449
+ var dayOfYear = parseInt(token[1], 10);
450
+ if (!validateDayOfYearDate(year, dayOfYear)) {
451
+ return new Date(NaN);
452
+ }
453
+ date.setUTCFullYear(year, 0, dayOfYear);
454
+ return date;
455
+ }
456
+ // yyyy-MM-dd or YYYYMMDD
457
+ token = patterns.MMDD.exec(dateString);
458
+ if (token) {
459
+ date = new Date(0);
460
+ month = parseInt(token[1], 10) - 1;
461
+ var day = parseInt(token[2], 10);
462
+ if (!validateDate(year, month, day)) {
463
+ return new Date(NaN);
464
+ }
465
+ date.setUTCFullYear(year, month, day);
466
+ return date;
467
+ }
468
+ // YYYY-Www or YYYYWww
469
+ token = patterns.Www.exec(dateString);
470
+ if (token) {
471
+ week = parseInt(token[1], 10) - 1;
472
+ if (!validateWeekDate(week)) {
473
+ return new Date(NaN);
474
+ }
475
+ return dayOfISOWeekYear(year, week);
476
+ }
477
+ // YYYY-Www-D or YYYYWwwD
478
+ token = patterns.WwwD.exec(dateString);
479
+ if (token) {
480
+ week = parseInt(token[1], 10) - 1;
481
+ var dayOfWeek = parseInt(token[2], 10) - 1;
482
+ if (!validateWeekDate(week, dayOfWeek)) {
483
+ return new Date(NaN);
484
+ }
485
+ return dayOfISOWeekYear(year, week, dayOfWeek);
486
+ }
487
+ // Invalid ISO-formatted date
488
+ return null;
489
+ }
490
+ function parseTime(timeString) {
491
+ var hours;
492
+ var minutes;
493
+ // hh
494
+ var token = patterns.HH.exec(timeString);
495
+ if (token) {
496
+ hours = parseFloat(token[1].replace(',', '.'));
497
+ if (!validateTime(hours)) {
498
+ return NaN;
499
+ }
500
+ return hours % 24 * MILLISECONDS_IN_HOUR;
501
+ }
502
+ // hh:mm or hhmm
503
+ token = patterns.HHMM.exec(timeString);
504
+ if (token) {
505
+ hours = parseInt(token[1], 10);
506
+ minutes = parseFloat(token[2].replace(',', '.'));
507
+ if (!validateTime(hours, minutes)) {
508
+ return NaN;
509
+ }
510
+ return hours % 24 * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE;
511
+ }
512
+ // hh:mm:ss or hhmmss
513
+ token = patterns.HHMMSS.exec(timeString);
514
+ if (token) {
515
+ hours = parseInt(token[1], 10);
516
+ minutes = parseInt(token[2], 10);
517
+ var seconds = parseFloat(token[3].replace(',', '.'));
518
+ if (!validateTime(hours, minutes, seconds)) {
519
+ return NaN;
520
+ }
521
+ return hours % 24 * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE + seconds * 1000;
522
+ }
523
+ // Invalid ISO-formatted time
524
+ return null;
525
+ }
526
+ function dayOfISOWeekYear(isoWeekYear, week, day) {
527
+ week = week || 0;
528
+ day = day || 0;
529
+ var date = new Date(0);
530
+ date.setUTCFullYear(isoWeekYear, 0, 4);
531
+ var fourthOfJanuaryDay = date.getUTCDay() || 7;
532
+ var diff = week * 7 + day + 1 - fourthOfJanuaryDay;
533
+ date.setUTCDate(date.getUTCDate() + diff);
534
+ return date;
535
+ }
536
+ // Validation functions
537
+ var DAYS_IN_MONTH = [
538
+ 31,
539
+ 28,
540
+ 31,
541
+ 30,
542
+ 31,
543
+ 30,
544
+ 31,
545
+ 31,
546
+ 30,
547
+ 31,
548
+ 30,
549
+ 31
550
+ ];
551
+ var DAYS_IN_MONTH_LEAP_YEAR = [
552
+ 31,
553
+ 29,
554
+ 31,
555
+ 30,
556
+ 31,
557
+ 30,
558
+ 31,
559
+ 31,
560
+ 30,
561
+ 31,
562
+ 30,
563
+ 31
564
+ ];
565
+ function isLeapYearIndex(year) {
566
+ return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;
567
+ }
568
+ function validateDate(year, month, date) {
569
+ if (month < 0 || month > 11) {
570
+ return false;
571
+ }
572
+ if (date != null) {
573
+ if (date < 1) {
574
+ return false;
575
+ }
576
+ var isLeapYear = isLeapYearIndex(year);
577
+ if (isLeapYear && date > DAYS_IN_MONTH_LEAP_YEAR[month]) {
578
+ return false;
579
+ }
580
+ if (!isLeapYear && date > DAYS_IN_MONTH[month]) {
581
+ return false;
582
+ }
583
+ }
584
+ return true;
585
+ }
586
+ function validateDayOfYearDate(year, dayOfYear) {
587
+ if (dayOfYear < 1) {
588
+ return false;
589
+ }
590
+ var isLeapYear = isLeapYearIndex(year);
591
+ if (isLeapYear && dayOfYear > 366) {
592
+ return false;
593
+ }
594
+ if (!isLeapYear && dayOfYear > 365) {
595
+ return false;
596
+ }
597
+ return true;
598
+ }
599
+ function validateWeekDate(week, day) {
600
+ if (week < 0 || week > 52) {
601
+ return false;
602
+ }
603
+ if (day != null && (day < 0 || day > 6)) {
604
+ return false;
605
+ }
606
+ return true;
607
+ }
608
+ function validateTime(hours, minutes, seconds) {
609
+ if (hours < 0 || hours >= 25) {
610
+ return false;
611
+ }
612
+ if (minutes != null && (minutes < 0 || minutes >= 60)) {
613
+ return false;
614
+ }
615
+ if (seconds != null && (seconds < 0 || seconds >= 60)) {
616
+ return false;
617
+ }
618
+ return true;
619
+ }
620
+
621
+ /**
622
+ * @name toZonedTime
623
+ * @category Time Zone Helpers
624
+ * @summary Get a date/time representing local time in a given time zone from the UTC date
625
+ *
626
+ * @description
627
+ * Returns a date instance with values representing the local time in the time zone
628
+ * specified of the UTC time from the date provided. In other words, when the new date
629
+ * is formatted it will show the equivalent hours in the target time zone regardless
630
+ * of the current system time zone.
631
+ *
632
+ * @param date the date with the relevant UTC time
633
+ * @param timeZone the time zone to get local time for, can be an offset or IANA time zone
634
+ * @param options the object with options. See [Options]{@link https://date-fns.org/docs/Options}
635
+ * @param {0|1|2} [options.additionalDigits=2] - passed to `toDate`. See [toDate]{@link https://date-fns.org/docs/toDate}
636
+ *
637
+ * @throws {TypeError} 2 arguments required
638
+ * @throws {RangeError} `options.additionalDigits` must be 0, 1 or 2
639
+ *
640
+ * @example
641
+ * // In June 10am UTC is 6am in New York (-04:00)
642
+ * const result = toZonedTime('2014-06-25T10:00:00.000Z', 'America/New_York')
643
+ * //=> Jun 25 2014 06:00:00
644
+ */ function toZonedTime(date, timeZone, options) {
645
+ date = toDate(date, options);
646
+ var offsetMilliseconds = tzParseTimezone(timeZone, date, true);
647
+ var d = new Date(date.getTime() - offsetMilliseconds);
648
+ var resultDate = new Date(0);
649
+ resultDate.setFullYear(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate());
650
+ resultDate.setHours(d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());
651
+ return resultDate;
652
+ }
653
+
4
654
  /**
5
655
  * It returns a `Date` object from a date `string` adjusted on the user timeZone,
6
656
  * if a timeZone is not provided we try getting it from the `Intl` browwser native
package/index.cjs.js CHANGED
@@ -20,7 +20,6 @@ var redirectTo = require('./redirectTo.cjs.js');
20
20
  var storageClient = require('./storageClient.cjs.js');
21
21
  require('@koine/utils');
22
22
  require('@koine/dom');
23
- require('date-fns-tz');
24
23
 
25
24
 
26
25
 
package/index.esm.js CHANGED
@@ -18,4 +18,3 @@ export { redirectTo } from './redirectTo.esm.js';
18
18
  export { storageClient } from './storageClient.esm.js';
19
19
  import '@koine/utils';
20
20
  import '@koine/dom';
21
- import 'date-fns-tz';
package/package.json CHANGED
@@ -2,8 +2,8 @@
2
2
  "name": "@koine/browser",
3
3
  "sideEffects": false,
4
4
  "dependencies": {
5
- "@koine/dom": "2.0.0-beta.121",
6
- "@koine/utils": "2.0.0-beta.121"
5
+ "@koine/dom": "2.0.0-beta.123",
6
+ "@koine/utils": "2.0.0-beta.123"
7
7
  },
8
8
  "peerDependenciesMeta": {
9
9
  "date-fns-tz": {
@@ -110,5 +110,5 @@
110
110
  },
111
111
  "module": "./index.esm.js",
112
112
  "main": "./index.cjs.js",
113
- "version": "2.0.0-beta.121"
113
+ "version": "2.0.0-beta.123"
114
114
  }