PageSourceSearch

https://studio.xapp.ai/vendors-node_modules_luxon_build_node_luxon_js.95927b80.js

js xapp.ai collected 2026-10-02 02:34:22 UTC 263,166 bytes, 7,821 lines download raw bytes

1;!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5f354246-f192-44db-93f8-16258885782d",e._sentryDebugIdIdentifier="sentry-dbid-5f354246-f192-44db-93f8-16258885782d")}catch(e){}}();
2
3    var _global =
4      typeof window !== 'undefined' ?
5        window :
6        typeof global !== 'undefined' ?
7          global :
8          typeof globalThis !== 'undefined' ?
9            globalThis :
10            typeof self !== 'undefined' ?
11              self :
12              {};
13
14    _global.SENTRY_RELEASE={id:"bf8ecb3987fc28ef4f4fa70826513d8bf936c9ad"};
15"use strict";
16(self["webpackChunk_xapp_oc_studio"] = self["webpackChunk_xapp_oc_studio"] || []).push([["vendors-node_modules_luxon_build_node_luxon_js"],{
17
18/***/ "../../node_modules/luxon/build/node/luxon.js"
19/*!****************************************************!*\
20  !*** ../../node_modules/luxon/build/node/luxon.js ***!
21  \****************************************************/
22(__unused_webpack_module, exports) {
23
24
25
26Object.defineProperty(exports, "__esModule", ({ value: true })
vendor: 36,527 bytes, lines 26-1469
26);
27
28// these aren't really private, but nor are they really useful to document
29
30/**
31 * @private
32 */
33class LuxonError extends Error {}
34
35/**
36 * @private
37 */
38class InvalidDateTimeError extends LuxonError {
39  constructor(reason) {
40    super(`Invalid DateTime: ${reason.toMessage()}`);
41  }
42}
43
44/**
45 * @private
46 */
47class InvalidIntervalError extends LuxonError {
48  constructor(reason) {
49    super(`Invalid Interval: ${reason.toMessage()}`);
50  }
51}
52
53/**
54 * @private
55 */
56class InvalidDurationError extends LuxonError {
57  constructor(reason) {
58    super(`Invalid Duration: ${reason.toMessage()}`);
59  }
60}
61
62/**
63 * @private
64 */
65class ConflictingSpecificationError extends LuxonError {}
66
67/**
68 * @private
69 */
70class InvalidUnitError extends LuxonError {
71  constructor(unit) {
72    super(`Invalid unit ${unit}`);
73  }
74}
75
76/**
77 * @private
78 */
79class InvalidArgumentError extends LuxonError {}
80
81/**
82 * @private
83 */
84class ZoneIsAbstractError extends LuxonError {
85  constructor() {
86    super("Zone is an abstract class");
87  }
88}
89
90/**
91 * @private
92 */
93
94const n = "numeric",
95  s = "short",
96  l = "long";
97const DATE_SHORT = {
98  year: n,
99  month: n,
100  day: n
101};
102const DATE_MED = {
103  year: n,
104  month: s,
105  day: n
106};
107const DATE_MED_WITH_WEEKDAY = {
108  year: n,
109  month: s,
110  day: n,
111  weekday: s
112};
113const DATE_FULL = {
114  year: n,
115  month: l,
116  day: n
117};
118const DATE_HUGE = {
119  year: n,
120  month: l,
121  day: n,
122  weekday: l
123};
124const TIME_SIMPLE = {
125  hour: n,
126  minute: n
127};
128const TIME_WITH_SECONDS = {
129  hour: n,
130  minute: n,
131  second: n
132};
133const TIME_WITH_SHORT_OFFSET = {
134  hour: n,
135  minute: n,
136  second: n,
137  timeZoneName: s
138};
139const TIME_WITH_LONG_OFFSET = {
140  hour: n,
141  minute: n,
142  second: n,
143  timeZoneName: l
144};
145const TIME_24_SIMPLE = {
146  hour: n,
147  minute: n,
148  hourCycle: "h23"
149};
150const TIME_24_WITH_SECONDS = {
151  hour: n,
152  minute: n,
153  second: n,
154  hourCycle: "h23"
155};
156const TIME_24_WITH_SHORT_OFFSET = {
157  hour: n,
158  minute: n,
159  second: n,
160  hourCycle: "h23",
161  timeZoneName: s
162};
163const TIME_24_WITH_LONG_OFFSET = {
164  hour: n,
165  minute: n,
166  second: n,
167  hourCycle: "h23",
168  timeZoneName: l
169};
170const DATETIME_SHORT = {
171  year: n,
172  month: n,
173  day: n,
174  hour: n,
175  minute: n
176};
177const DATETIME_SHORT_WITH_SECONDS = {
178  year: n,
179  month: n,
180  day: n,
181  hour: n,
182  minute: n,
183  second: n
184};
185const DATETIME_MED = {
186  year: n,
187  month: s,
188  day: n,
189  hour: n,
190  minute: n
191};
192const DATETIME_MED_WITH_SECONDS = {
193  year: n,
194  month: s,
195  day: n,
196  hour: n,
197  minute: n,
198  second: n
199};
200const DATETIME_MED_WITH_WEEKDAY = {
201  year: n,
202  month: s,
203  day: n,
204  weekday: s,
205  hour: n,
206  minute: n
207};
208const DATETIME_FULL = {
209  year: n,
210  month: l,
211  day: n,
212  hour: n,
213  minute: n,
214  timeZoneName: s
215};
216const DATETIME_FULL_WITH_SECONDS = {
217  year: n,
218  month: l,
219  day: n,
220  hour: n,
221  minute: n,
222  second: n,
223  timeZoneName: s
224};
225const DATETIME_HUGE = {
226  year: n,
227  month: l,
228  day: n,
229  weekday: l,
230  hour: n,
231  minute: n,
232  timeZoneName: l
233};
234const DATETIME_HUGE_WITH_SECONDS = {
235  year: n,
236  month: l,
237  day: n,
238  weekday: l,
239  hour: n,
240  minute: n,
241  second: n,
242  timeZoneName: l
243};
244
245/**
246 * @interface
247 */
248class Zone {
249  /**
250   * The type of zone
251   * @abstract
252   * @type {string}
253   */
254  get type() {
255    throw new ZoneIsAbstractError();
256  }
257
258  /**
259   * The name of this zone.
260   * @abstract
261   * @type {string}
262   */
263  get name() {
264    throw new ZoneIsAbstractError();
265  }
266
267  /**
268   * The IANA name of this zone.
269   * Defaults to `name` if not overwritten by a subclass.
270   * @abstract
271   * @type {string}
272   */
273  get ianaName() {
274    return this.name;
275  }
276
277  /**
278   * Returns whether the offset is known to be fixed for the whole year.
279   * @abstract
280   * @type {boolean}
281   */
282  get isUniversal() {
283    throw new ZoneIsAbstractError();
284  }
285
286  /**
287   * Returns the offset's common name (such as EST) at the specified timestamp
288   * @abstract
289   * @param {number} ts - Epoch milliseconds for which to get the name
290   * @param {Object} opts - Options to affect the format
291   * @param {string} opts.format - What style of offset to return. Accepts 'long' or 'short'.
292   * @param {string} opts.locale - What locale to return the offset name in.
293   * @return {string}
294   */
295  offsetName(ts, opts) {
296    throw new ZoneIsAbstractError();
297  }
298
299  /**
300   * Returns the offset's value as a string
301   * @abstract
302   * @param {number} ts - Epoch milliseconds for which to get the offset
303   * @param {string} format - What style of offset to return.
304   *                          Accepts 'narrow', 'short', or 'techie'. Returning '+6', '+06:00', or '+0600' respectively
305   * @return {string}
306   */
307  formatOffset(ts, format) {
308    throw new ZoneIsAbstractError();
309  }
310
311  /**
312   * Return the offset in minutes for this zone at the specified timestamp.
313   * @abstract
314   * @param {number} ts - Epoch milliseconds for which to compute the offset
315   * @return {number}
316   */
317  offset(ts) {
318    throw new ZoneIsAbstractError();
319  }
320
321  /**
322   * Return whether this Zone is equal to another zone
323   * @abstract
324   * @param {Zone} otherZone - the zone to compare
325   * @return {boolean}
326   */
327  equals(otherZone) {
328    throw new ZoneIsAbstractError();
329  }
330
331  /**
332   * Return whether this Zone is valid.
333   * @abstract
334   * @type {boolean}
335   */
336  get isValid() {
337    throw new ZoneIsAbstractError();
338  }
339}
340
341let singleton$1 = null;
342
343/**
344 * Represents the local zone for this JavaScript environment.
345 * @implements {Zone}
346 */
347class SystemZone extends Zone {
348  /**
349   * Get a singleton instance of the local zone
350   * @return {SystemZone}
351   */
352  static get instance() {
353    if (singleton$1 === null) {
354      singleton$1 = new SystemZone();
355    }
356    return singleton$1;
357  }
358
359  /** @override **/
360  get type() {
361    return "system";
362  }
363
364  /** @override **/
365  get name() {
366    return new Intl.DateTimeFormat().resolvedOptions().timeZone;
367  }
368
369  /** @override **/
370  get isUniversal() {
371    return false;
372  }
373
374  /** @override **/
375  offsetName(ts, {
376    format,
377    locale
378  }) {
379    return parseZoneInfo(ts, format, locale);
380  }
381
382  /** @override **/
383  formatOffset(ts, format) {
384    return formatOffset(this.offset(ts), format);
385  }
386
387  /** @override **/
388  offset(ts) {
389    return -new Date(ts).getTimezoneOffset();
390  }
391
392  /** @override **/
393  equals(otherZone) {
394    return otherZone.type === "system";
395  }
396
397  /** @override **/
398  get isValid() {
399    return true;
400  }
401}
402
403const dtfCache = new Map();
404function makeDTF(zoneName) {
405  let dtf = dtfCache.get(zoneName);
406  if (dtf === undefined) {
407    dtf = new Intl.DateTimeFormat("en-US", {
408      hour12: false,
409      timeZone: zoneName,
410      year: "numeric",
411      month: "2-digit",
412      day: "2-digit",
413      hour: "2-digit",
414      minute: "2-digit",
415      second: "2-digit",
416      era: "short"
417    });
418    dtfCache.set(zoneName, dtf);
419  }
420  return dtf;
421}
422const typeToPos = {
423  year: 0,
424  month: 1,
425  day: 2,
426  era: 3,
427  hour: 4,
428  minute: 5,
429  second: 6
430};
431function hackyOffset(dtf, date) {
432  const formatted = dtf.format(date).replace(/\u200E/g, ""),
433    parsed = /(\d+)\/(\d+)\/(\d+) (AD|BC),? (\d+):(\d+):(\d+)/.exec(formatted),
434    [, fMonth, fDay, fYear, fadOrBc, fHour, fMinute, fSecond] = parsed;
435  return [fYear, fMonth, fDay, fadOrBc, fHour, fMinute, fSecond];
436}
437function partsOffset(dtf, date) {
438  const formatted = dtf.formatToParts(date);
439  const filled = [];
440  for (let i = 0; i < formatted.length; i++) {
441    const {
442      type,
443      value
444    } = formatted[i];
445    const pos = typeToPos[type];
446    if (type === "era") {
447      filled[pos] = value;
448    } else if (!isUndefined(pos)) {
449      filled[pos] = parseInt(value, 10);
450    }
451  }
452  return filled;
453}
454const ianaZoneCache = new Map();
455/**
456 * A zone identified by an IANA identifier, like America/New_York
457 * @implements {Zone}
458 */
459class IANAZone extends Zone {
460  /**
461   * @param {string} name - Zone name
462   * @return {IANAZone}
463   */
464  static create(name) {
465    let zone = ianaZoneCache.get(name);
466    if (zone === undefined) {
467      ianaZoneCache.set(name, zone = new IANAZone(name));
468    }
469    return zone;
470  }
471
472  /**
473   * Reset local caches. Should only be necessary in testing scenarios.
474   * @return {void}
475   */
476  static resetCache() {
477    ianaZoneCache.clear();
478    dtfCache.clear();
479  }
480
481  /**
482   * Returns whether the provided string is a valid specifier. This only checks the string's format, not that the specifier identifies a known zone; see isValidZone for that.
483   * @param {string} s - The string to check validity on
484   * @example IANAZone.isValidSpecifier("America/New_York") //=> true
485   * @example IANAZone.isValidSpecifier("Sport~~blorp") //=> false
486   * @deprecated For backward compatibility, this forwards to isValidZone, better use `isValidZone()` directly instead.
487   * @return {boolean}
488   */
489  static isValidSpecifier(s) {
490    return this.isValidZone(s);
491  }
492
493  /**
494   * Returns whether the provided string identifies a real zone
495   * @param {string} zone - The string to check
496   * @example IANAZone.isValidZone("America/New_York") //=> true
497   * @example IANAZone.isValidZone("Fantasia/Castle") //=> false
498   * @example IANAZone.isValidZone("Sport~~blorp") //=> false
499   * @return {boolean}
500   */
501  static isValidZone(zone) {
502    if (!zone) {
503      return false;
504    }
505    try {
506      new Intl.DateTimeFormat("en-US", {
507        timeZone: zone
508      }).format();
509      return true;
510    } catch (e) {
511      return false;
512    }
513  }
514  constructor(name) {
515    super();
516    /** @private **/
517    this.zoneName = name;
518    /** @private **/
519    this.valid = IANAZone.isValidZone(name);
520  }
521
522  /**
523   * The type of zone. `iana` for all instances of `IANAZone`.
524   * @override
525   * @type {string}
526   */
527  get type() {
528    return "iana";
529  }
530
531  /**
532   * The name of this zone (i.e. the IANA zone name).
533   * @override
534   * @type {string}
535   */
536  get name() {
537    return this.zoneName;
538  }
539
540  /**
541   * Returns whether the offset is known to be fixed for the whole year:
542   * Always returns false for all IANA zones.
543   * @override
544   * @type {boolean}
545   */
546  get isUniversal() {
547    return false;
548  }
549
550  /**
551   * Returns the offset's common name (such as EST) at the specified timestamp
552   * @override
553   * @param {number} ts - Epoch milliseconds for which to get the name
554   * @param {Object} opts - Options to affect the format
555   * @param {string} opts.format - What style of offset to return. Accepts 'long' or 'short'.
556   * @param {string} opts.locale - What locale to return the offset name in.
557   * @return {string}
558   */
559  offsetName(ts, {
560    format,
561    locale
562  }) {
563    return parseZoneInfo(ts, format, locale, this.name);
564  }
565
566  /**
567   * Returns the offset's value as a string
568   * @override
569   * @param {number} ts - Epoch milliseconds for which to get the offset
570   * @param {string} format - What style of offset to return.
571   *                          Accepts 'narrow', 'short', or 'techie'. Returning '+6', '+06:00', or '+0600' respectively
572   * @return {string}
573   */
574  formatOffset(ts, format) {
575    return formatOffset(this.offset(ts), format);
576  }
577
578  /**
579   * Return the offset in minutes for this zone at the specified timestamp.
580   * @override
581   * @param {number} ts - Epoch milliseconds for which to compute the offset
582   * @return {number}
583   */
584  offset(ts) {
585    if (!this.valid) return NaN;
586    const date = new Date(ts);
587    if (isNaN(date)) return NaN;
588    const dtf = makeDTF(this.name);
589    let [year, month, day, adOrBc, hour, minute, second] = dtf.formatToParts ? partsOffset(dtf, date) : hackyOffset(dtf, date);
590    if (adOrBc === "BC") {
591      year = -Math.abs(year) + 1;
592    }
593
594    // because we're using hour12 and https://bugs.chromium.org/p/chromium/issues/detail?id=1025564&can=2&q=%2224%3A00%22%20datetimeformat
595    const adjustedHour = hour === 24 ? 0 : hour;
596    const asUTC = objToLocalTS({
597      year,
598      month,
599      day,
600      hour: adjustedHour,
601      minute,
602      second,
603      millisecond: 0
604    });
605    let asTS = +date;
606    const over = asTS % 1000;
607    asTS -= over >= 0 ? over : 1000 + over;
608    return (asUTC - asTS) / (60 * 1000);
609  }
610
611  /**
612   * Return whether this Zone is equal to another zone
613   * @override
614   * @param {Zone} otherZone - the zone to compare
615   * @return {boolean}
616   */
617  equals(otherZone) {
618    return otherZone.type === "iana" && otherZone.name === this.name;
619  }
620
621  /**
622   * Return whether this Zone is valid.
623   * @override
624   * @type {boolean}
625   */
626  get isValid() {
627    return this.valid;
628  }
629}
630
631// todo - remap caching
632
633let intlLFCache = {};
634function getCachedLF(locString, opts = {}) {
635  const key = JSON.stringify([locString, opts]);
636  let dtf = intlLFCache[key];
637  if (!dtf) {
638    dtf = new Intl.ListFormat(locString, opts);
639    intlLFCache[key] = dtf;
640  }
641  return dtf;
642}
643const intlDTCache = new Map();
644function getCachedDTF(locString, opts = {}) {
645  const key = JSON.stringify([locString, opts]);
646  let dtf = intlDTCache.get(key);
647  if (dtf === undefined) {
648    dtf = new Intl.DateTimeFormat(locString, opts);
649    intlDTCache.set(key, dtf);
650  }
651  return dtf;
652}
653const intlNumCache = new Map();
654function getCachedINF(locString, opts = {}) {
655  const key = JSON.stringify([locString, opts]);
656  let inf = intlNumCache.get(key);
657  if (inf === undefined) {
658    inf = new Intl.NumberFormat(locString, opts);
659    intlNumCache.set(key, inf);
660  }
661  return inf;
662}
663const intlRelCache = new Map();
664function getCachedRTF(locString, opts = {}) {
665  const {
666    base,
667    ...cacheKeyOpts
668  } = opts; // exclude `base` from the options
669  const key = JSON.stringify([locString, cacheKeyOpts]);
670  let inf = intlRelCache.get(key);
671  if (inf === undefined) {
672    inf = new Intl.RelativeTimeFormat(locString, opts);
673    intlRelCache.set(key, inf);
674  }
675  return inf;
676}
677let sysLocaleCache = null;
678function systemLocale() {
679  if (sysLocaleCache) {
680    return sysLocaleCache;
681  } else {
682    sysLocaleCache = new Intl.DateTimeFormat().resolvedOptions().locale;
683    return sysLocaleCache;
684  }
685}
686const intlResolvedOptionsCache = new Map();
687function getCachedIntResolvedOptions(locString) {
688  let opts = intlResolvedOptionsCache.get(locString);
689  if (opts === undefined) {
690    opts = new Intl.DateTimeFormat(locString).resolvedOptions();
691    intlResolvedOptionsCache.set(locString, opts);
692  }
693  return opts;
694}
695const weekInfoCache = new Map();
696function getCachedWeekInfo(locString) {
697  let data = weekInfoCache.get(locString);
698  if (!data) {
699    const locale = new Intl.Locale(locString);
700    // browsers currently implement this as a property, but spec says it should be a getter function
701    data = "getWeekInfo" in locale ? locale.getWeekInfo() : locale.weekInfo;
702    // minimalDays was removed from WeekInfo: https://github.com/tc39/proposal-intl-locale-info/issues/86
703    if (!("minimalDays" in data)) {
704      data = {
705        ...fallbackWeekSettings,
706        ...data
707      };
708    }
709    weekInfoCache.set(locString, data);
710  }
711  return data;
712}
713function parseLocaleString(localeStr) {
714  // I really want to avoid writing a BCP 47 parser
715  // see, e.g. https://github.com/wooorm/bcp-47
716  // Instead, we'll do this:
717
718  // a) if the string has no -u extensions, just leave it alone
719  // b) if it does, use Intl to resolve everything
720  // c) if Intl fails, try again without the -u
721
722  // private subtags and unicode subtags have ordering requirements,
723  // and we're not properly parsing this, so just strip out the
724  // private ones if they exist.
725  const xIndex = localeStr.indexOf("-x-");
726  if (xIndex !== -1) {
727    localeStr = localeStr.substring(0, xIndex);
728  }
729  const uIndex = localeStr.indexOf("-u-");
730  if (uIndex === -1) {
731    return [localeStr];
732  } else {
733    let options;
734    let selectedStr;
735    try {
736      options = getCachedDTF(localeStr).resolvedOptions();
737      selectedStr = localeStr;
738    } catch (e) {
739      const smaller = localeStr.substring(0, uIndex);
740      options = getCachedDTF(smaller).resolvedOptions();
741      selectedStr = smaller;
742    }
743    const {
744      numberingSystem,
745      calendar
746    } = options;
747    return [selectedStr, numberingSystem, calendar];
748  }
749}
750function intlConfigString(localeStr, numberingSystem, outputCalendar) {
751  if (outputCalendar || numberingSystem) {
752    if (!localeStr.includes("-u-")) {
753      localeStr += "-u";
754    }
755    if (outputCalendar) {
756      localeStr += `-ca-${outputCalendar}`;
757    }
758    if (numberingSystem) {
759      localeStr += `-nu-${numberingSystem}`;
760    }
761    return localeStr;
762  } else {
763    return localeStr;
764  }
765}
766function mapMonths(f) {
767  const ms = [];
768  for (let i = 1; i <= 12; i++) {
769    const dt = DateTime.utc(2009, i, 1);
770    ms.push(f(dt));
771  }
772  return ms;
773}
774function mapWeekdays(f) {
775  const ms = [];
776  for (let i = 1; i <= 7; i++) {
777    const dt = DateTime.utc(2016, 11, 13 + i);
778    ms.push(f(dt));
779  }
780  return ms;
781}
782function listStuff(loc, length, englishFn, intlFn) {
783  const mode = loc.listingMode();
784  if (mode === "error") {
785    return null;
786  } else if (mode === "en") {
787    return englishFn(length);
788  } else {
789    return intlFn(length);
790  }
791}
792function supportsFastNumbers(loc) {
793  if (loc.numberingSystem && loc.numberingSystem !== "latn") {
794    return false;
795  } else {
796    return loc.numberingSystem === "latn" || !loc.locale || loc.locale.startsWith("en") || getCachedIntResolvedOptions(loc.locale).numberingSystem === "latn";
797  }
798}
799
800/**
801 * @private
802 */
803
804class PolyNumberFormatter {
805  constructor(intl, forceSimple, opts) {
806    this.padTo = opts.padTo || 0;
807    this.floor = opts.floor || false;
808    const {
809      padTo,
810      floor,
811      ...otherOpts
812    } = opts;
813    if (!forceSimple || Object.keys(otherOpts).length > 0) {
814      const intlOpts = {
815        useGrouping: false,
816        ...opts
817      };
818      if (opts.padTo > 0) intlOpts.minimumIntegerDigits = opts.padTo;
819      this.inf = getCachedINF(intl, intlOpts);
820    }
821  }
822  format(i) {
823    if (this.inf) {
824      const fixed = this.floor ? Math.floor(i) : i;
825      return this.inf.format(fixed);
826    } else {
827      // to match the browser's numberformatter defaults
828      const fixed = this.floor ? Math.floor(i) : roundTo(i, 3);
829      return padStart(fixed, this.padTo);
830    }
831  }
832}
833
834/**
835 * @private
836 */
837
838class PolyDateFormatter {
839  constructor(dt, intl, opts) {
840    this.opts = opts;
841    this.originalZone = undefined;
842    let z = undefined;
843    if (this.opts.timeZone) {
844      // Don't apply any workarounds if a timeZone is explicitly provided in opts
845      this.dt = dt;
846    } else if (dt.zone.type === "fixed") {
847      // UTC-8 or Etc/UTC-8 are not part of tzdata, only Etc/GMT+8 and the like.
848      // That is why fixed-offset TZ is set to that unless it is:
849      // 1. Representing offset 0 when UTC is used to maintain previous behavior and does not become GMT.
850      // 2. Unsupported by the browser:
851      //    - some do not support Etc/
852      //    - < Etc/GMT-14, > Etc/GMT+12, and 30-minute or 45-minute offsets are not part of tzdata
853      const gmtOffset = -1 * (dt.offset / 60);
854      const offsetZ = gmtOffset >= 0 ? `Etc/GMT+${gmtOffset}` : `Etc/GMT${gmtOffset}`;
855      if (dt.offset !== 0 && IANAZone.create(offsetZ).valid) {
856        z = offsetZ;
857        this.dt = dt;
858      } else {
859        // Not all fixed-offset zones like Etc/+4:30 are present in tzdata so
860        // we manually apply the offset and substitute the zone as needed.
861        z = "UTC";
862        this.dt = dt.offset === 0 ? dt : dt.setZone("UTC").plus({
863          minutes: dt.offset
864        });
865        this.originalZone = dt.zone;
866      }
867    } else if (dt.zone.type === "system") {
868      this.dt = dt;
869    } else if (dt.zone.type === "iana") {
870      this.dt = dt;
871      z = dt.zone.name;
872    } else {
873      // Custom zones can have any offset / offsetName so we just manually
874      // apply the offset and substitute the zone as needed.
875      z = "UTC";
876      this.dt = dt.setZone("UTC").plus({
877        minutes: dt.offset
878      });
879      this.originalZone = dt.zone;
880    }
881    const intlOpts = {
882      ...this.opts
883    };
884    intlOpts.timeZone = intlOpts.timeZone || z;
885    this.dtf = getCachedDTF(intl, intlOpts);
886  }
887  format() {
888    if (this.originalZone) {
889      // If we have to substitute in the actual zone name, we have to use
890      // formatToParts so that the timezone can be replaced.
891      return this.formatToParts().map(({
892        value
893      }) => value).join("");
894    }
895    return this.dtf.format(this.dt.toJSDate());
896  }
897  formatToParts() {
898    const parts = this.dtf.formatToParts(this.dt.toJSDate());
899    if (this.originalZone) {
900      return parts.map(part => {
901        if (part.type === "timeZoneName") {
902          const offsetName = this.originalZone.offsetName(this.dt.ts, {
903            locale: this.dt.locale,
904            format: this.opts.timeZoneName
905          });
906          return {
907            ...part,
908            value: offsetName
909          };
910        } else {
911          return part;
912        }
913      });
914    }
915    return parts;
916  }
917  resolvedOptions() {
918    return this.dtf.resolvedOptions();
919  }
920}
921
922/**
923 * @private
924 */
925class PolyRelFormatter {
926  constructor(intl, isEnglish, opts) {
927    this.opts = {
928      style: "long",
929      ...opts
930    };
931    if (!isEnglish && hasRelative()) {
932      this.rtf = getCachedRTF(intl, opts);
933    }
934  }
935  format(count, unit) {
936    if (this.rtf) {
937      return this.rtf.format(count, unit);
938    } else {
939      return formatRelativeTime(unit, count, this.opts.numeric, this.opts.style !== "long");
940    }
941  }
942  formatToParts(count, unit) {
943    if (this.rtf) {
944      return this.rtf.formatToParts(count, unit);
945    } else {
946      return [];
947    }
948  }
949}
950const fallbackWeekSettings = {
951  firstDay: 1,
952  minimalDays: 4,
953  weekend: [6, 7]
954};
955
956/**
957 * @private
958 */
959class Locale {
960  static fromOpts(opts) {
961    return Locale.create(opts.locale, opts.numberingSystem, opts.outputCalendar, opts.weekSettings, opts.defaultToEN);
962  }
963  static create(locale, numberingSystem, outputCalendar, weekSettings, defaultToEN = false) {
964    const specifiedLocale = locale || Settings.defaultLocale;
965    // the system locale is useful for human-readable strings but annoying for parsing/formatting known formats
966    const localeR = specifiedLocale || (defaultToEN ? "en-US" : systemLocale());
967    const numberingSystemR = numberingSystem || Settings.defaultNumberingSystem;
968    const outputCalendarR = outputCalendar || Settings.defaultOutputCalendar;
969    const weekSettingsR = validateWeekSettings(weekSettings) || Settings.defaultWeekSettings;
970    return new Locale(localeR, numberingSystemR, outputCalendarR, weekSettingsR, specifiedLocale);
971  }
972  static resetCache() {
973    sysLocaleCache = null;
974    intlDTCache.clear();
975    intlNumCache.clear();
976    intlRelCache.clear();
977    intlResolvedOptionsCache.clear();
978    weekInfoCache.clear();
979  }
980  static fromObject({
981    locale,
982    numberingSystem,
983    outputCalendar,
984    weekSettings
985  } = {}) {
986    return Locale.create(locale, numberingSystem, outputCalendar, weekSettings);
987  }
988  constructor(locale, numbering, outputCalendar, weekSettings, specifiedLocale) {
989    const [parsedLocale, parsedNumberingSystem, parsedOutputCalendar] = parseLocaleString(locale);
990    this.locale = parsedLocale;
991    this.numberingSystem = numbering || parsedNumberingSystem || null;
992    this.outputCalendar = outputCalendar || parsedOutputCalendar || null;
993    this.weekSettings = weekSettings;
994    this.intl = intlConfigString(this.locale, this.numberingSystem, this.outputCalendar);
995    this.weekdaysCache = {
996      format: {},
997      standalone: {}
998    };
999    this.monthsCache = {
1000      format: {},
1001      standalone: {}
1002    };
1003    this.meridiemCache = null;
1004    this.eraCache = {};
1005    this.specifiedLocale = specifiedLocale;
1006    this.fastNumbersCached = null;
1007  }
1008  get fastNumbers() {
1009    if (this.fastNumbersCached == null) {
1010      this.fastNumbersCached = supportsFastNumbers(this);
1011    }
1012    return this.fastNumbersCached;
1013  }
1014  listingMode() {
1015    const isActuallyEn = this.isEnglish();
1016    const hasNoWeirdness = (this.numberingSystem === null || this.numberingSystem === "latn") && (this.outputCalendar === null || this.outputCalendar === "gregory");
1017    return isActuallyEn && hasNoWeirdness ? "en" : "intl";
1018  }
1019  clone(alts) {
1020    if (!alts || Object.getOwnPropertyNames(alts).length === 0) {
1021      return this;
1022    } else {
1023      return Locale.create(alts.locale || this.specifiedLocale, alts.numberingSystem || this.numberingSystem, alts.outputCalendar || this.outputCalendar, validateWeekSettings(alts.weekSettings) || this.weekSettings, alts.defaultToEN || false);
1024    }
1025  }
1026  redefaultToEN(alts = {}) {
1027    return this.clone({
1028      ...alts,
1029      defaultToEN: true
1030    });
1031  }
1032  redefaultToSystem(alts = {}) {
1033    return this.clone({
1034      ...alts,
1035      defaultToEN: false
1036    });
1037  }
1038  months(length, format = false) {
1039    return listStuff(this, length, months, () => {
1040      // Workaround for "ja" locale: formatToParts does not label all parts of the month
1041      // as "month" and for this locale there is no difference between "format" and "non-format".
1042      // As such, just use format() instead of formatToParts() and take the whole string
1043      const monthSpecialCase = this.intl === "ja" || this.intl.startsWith("ja-");
1044      format &= !monthSpecialCase;
1045      const intl = format ? {
1046          month: length,
1047          day: "numeric"
1048        } : {
1049          month: length
1050        },
1051        formatStr = format ? "format" : "standalone";
1052      if (!this.monthsCache[formatStr][length]) {
1053        const mapper = !monthSpecialCase ? dt => this.extract(dt, intl, "month") : dt => this.dtFormatter(dt, intl).format();
1054        this.monthsCache[formatStr][length] = mapMonths(mapper);
1055      }
1056      return this.monthsCache[formatStr][length];
1057    });
1058  }
1059  weekdays(length, format = false) {
1060    return listStuff(this, length, weekdays, () => {
1061      const intl = format ? {
1062          weekday: length,
1063          year: "numeric",
1064          month: "long",
1065          day: "numeric"
1066        } : {
1067          weekday: length
1068        },
1069        formatStr = format ? "format" : "standalone";
1070      if (!this.weekdaysCache[formatStr][length]) {
1071        this.weekdaysCache[formatStr][length] = mapWeekdays(dt => this.extract(dt, intl, "weekday"));
1072      }
1073      return this.weekdaysCache[formatStr][length];
1074    });
1075  }
1076  meridiems() {
1077    return listStuff(this, undefined, () => meridiems, () => {
1078      // In theory there could be aribitrary day periods. We're gonna assume there are exactly two
1079      // for AM and PM. This is probably wrong, but it's makes parsing way easier.
1080      if (!this.meridiemCache) {
1081        const intl = {
1082          hour: "numeric",
1083          hourCycle: "h12"
1084        };
1085        this.meridiemCache = [DateTime.utc(2016, 11, 13, 9), DateTime.utc(2016, 11, 13, 19)].map(dt => this.extract(dt, intl, "dayperiod"));
1086      }
1087      return this.meridiemCache;
1088    });
1089  }
1090  eras(length) {
1091    return listStuff(this, length, eras, () => {
1092      const intl = {
1093        era: length
1094      };
1095
1096      // This is problematic. Different calendars are going to define eras totally differently. What I need is the minimum set of dates
1097      // to definitely enumerate them.
1098      if (!this.eraCache[length]) {
1099        this.eraCache[length] = [DateTime.utc(-40, 1, 1), DateTime.utc(2017, 1, 1)].map(dt => this.extract(dt, intl, "era"));
1100      }
1101      return this.eraCache[length];
1102    });
1103  }
1104  extract(dt, intlOpts, field) {
1105    const df = this.dtFormatter(dt, intlOpts),
1106      results = df.formatToParts(),
1107      matching = results.find(m => m.type.toLowerCase() === field);
1108    return matching ? matching.value : null;
1109  }
1110  numberFormatter(opts = {}) {
1111    // this forcesimple option is never used (the only caller short-circuits on it, but it seems safer to leave)
1112    // (in contrast, the rest of the condition is used heavily)
1113    return new PolyNumberFormatter(this.intl, opts.forceSimple || this.fastNumbers, opts);
1114  }
1115  dtFormatter(dt, intlOpts = {}) {
1116    return new PolyDateFormatter(dt, this.intl, intlOpts);
1117  }
1118  relFormatter(opts = {}) {
1119    return new PolyRelFormatter(this.intl, this.isEnglish(), opts);
1120  }
1121  listFormatter(opts = {}) {
1122    return getCachedLF(this.intl, opts);
1123  }
1124  isEnglish() {
1125    return this.locale === "en" || this.locale.toLowerCase() === "en-us" || getCachedIntResolvedOptions(this.intl).locale.startsWith("en-us");
1126  }
1127  getWeekSettings() {
1128    if (this.weekSettings) {
1129      return this.weekSettings;
1130    } else if (!hasLocaleWeekInfo()) {
1131      return fallbackWeekSettings;
1132    } else {
1133      return getCachedWeekInfo(this.locale);
1134    }
1135  }
1136  getStartOfWeek() {
1137    return this.getWeekSettings().firstDay;
1138  }
1139  getMinDaysInFirstWeek() {
1140    return this.getWeekSettings().minimalDays;
1141  }
1142  getWeekendDays() {
1143    return this.getWeekSettings().weekend;
1144  }
1145  equals(other) {
1146    return this.locale === other.locale && this.numberingSystem === other.numberingSystem && this.outputCalendar === other.outputCalendar;
1147  }
1148  toString() {
1149    return `Locale(${this.locale}, ${this.numberingSystem}, ${this.outputCalendar})`;
1150  }
1151}
1152
1153let singleton = null;
1154
1155/**
1156 * A zone with a fixed offset (meaning no DST)
1157 * @implements {Zone}
1158 */
1159class FixedOffsetZone extends Zone {
1160  /**
1161   * Get a singleton instance of UTC
1162   * @return {FixedOffsetZone}
1163   */
1164  static get utcInstance() {
1165    if (singleton === null) {
1166      singleton = new FixedOffsetZone(0);
1167    }
1168    return singleton;
1169  }
1170
1171  /**
1172   * Get an instance with a specified offset
1173   * @param {number} offset - The offset in minutes
1174   * @return {FixedOffsetZone}
1175   */
1176  static instance(offset) {
1177    return offset === 0 ? FixedOffsetZone.utcInstance : new FixedOffsetZone(offset);
1178  }
1179
1180  /**
1181   * Get an instance of FixedOffsetZone from a UTC offset string, like "UTC+6"
1182   * @param {string} s - The offset string to parse
1183   * @example FixedOffsetZone.parseSpecifier("UTC+6")
1184   * @example FixedOffsetZone.parseSpecifier("UTC+06")
1185   * @example FixedOffsetZone.parseSpecifier("UTC-6:00")
1186   * @return {FixedOffsetZone}
1187   */
1188  static parseSpecifier(s) {
1189    if (s) {
1190      const r = s.match(/^utc(?:([+-]\d{1,2})(?::(\d{2}))?)?$/i);
1191      if (r) {
1192        return new FixedOffsetZone(signedOffset(r[1], r[2]));
1193      }
1194    }
1195    return null;
1196  }
1197  constructor(offset) {
1198    super();
1199    /** @private **/
1200    this.fixed = offset;
1201  }
1202
1203  /**
1204   * The type of zone. `fixed` for all instances of `FixedOffsetZone`.
1205   * @override
1206   * @type {string}
1207   */
1208  get type() {
1209    return "fixed";
1210  }
1211
1212  /**
1213   * The name of this zone.
1214   * All fixed zones' names always start with "UTC" (plus optional offset)
1215   * @override
1216   * @type {string}
1217   */
1218  get name() {
1219    return this.fixed === 0 ? "UTC" : `UTC${formatOffset(this.fixed, "narrow")}`;
1220  }
1221
1222  /**
1223   * The IANA name of this zone, i.e. `Etc/UTC` or `Etc/GMT+/-nn`
1224   *
1225   * @override
1226   * @type {string}
1227   */
1228  get ianaName() {
1229    if (this.fixed === 0) {
1230      return "Etc/UTC";
1231    } else {
1232      return `Etc/GMT${formatOffset(-this.fixed, "narrow")}`;
1233    }
1234  }
1235
1236  /**
1237   * Returns the offset's common name at the specified timestamp.
1238   *
1239   * For fixed offset zones this equals to the zone name.
1240   * @override
1241   */
1242  offsetName() {
1243    return this.name;
1244  }
1245
1246  /**
1247   * Returns the offset's value as a string
1248   * @override
1249   * @param {number} ts - Epoch milliseconds for which to get the offset
1250   * @param {string} format - What style of offset to return.
1251   *                          Accepts 'narrow', 'short', or 'techie'. Returning '+6', '+06:00', or '+0600' respectively
1252   * @return {string}
1253   */
1254  formatOffset(ts, format) {
1255    return formatOffset(this.fixed, format);
1256  }
1257
1258  /**
1259   * Returns whether the offset is known to be fixed for the whole year:
1260   * Always returns true for all fixed offset zones.
1261   * @override
1262   * @type {boolean}
1263   */
1264  get isUniversal() {
1265    return true;
1266  }
1267
1268  /**
1269   * Return the offset in minutes for this zone at the specified timestamp.
1270   *
1271   * For fixed offset zones, this is constant and does not depend on a timestamp.
1272   * @override
1273   * @return {number}
1274   */
1275  offset() {
1276    return this.fixed;
1277  }
1278
1279  /**
1280   * Return whether this Zone is equal to another zone (i.e. also fixed and same offset)
1281   * @override
1282   * @param {Zone} otherZone - the zone to compare
1283   * @return {boolean}
1284   */
1285  equals(otherZone) {
1286    return otherZone.type === "fixed" && otherZone.fixed === this.fixed;
1287  }
1288
1289  /**
1290   * Return whether this Zone is valid:
1291   * All fixed offset zones are valid.
1292   * @override
1293   * @type {boolean}
1294   */
1295  get isValid() {
1296    return true;
1297  }
1298}
1299
1300/**
1301 * A zone that failed to parse. You should never need to instantiate this.
1302 * @implements {Zone}
1303 */
1304class InvalidZone extends Zone {
1305  constructor(zoneName) {
1306    super();
1307    /**  @private */
1308    this.zoneName = zoneName;
1309  }
1310
1311  /** @override **/
1312  get type() {
1313    return "invalid";
1314  }
1315
1316  /** @override **/
1317  get name() {
1318    return this.zoneName;
1319  }
1320
1321  /** @override **/
1322  get isUniversal() {
1323    return false;
1324  }
1325
1326  /** @override **/
1327  offsetName() {
1328    return null;
1329  }
1330
1331  /** @override **/
1332  formatOffset() {
1333    return "";
1334  }
1335
1336  /** @override **/
1337  offset() {
1338    return NaN;
1339  }
1340
1341  /** @override **/
1342  equals() {
1343    return false;
1344  }
1345
1346  /** @override **/
1347  get isValid() {
1348    return false;
1349  }
1350}
1351
1352/**
1353 * @private
1354 */
1355function normalizeZone(input, defaultZone) {
1356  if (isUndefined(input) || input === null) {
1357    return defaultZone;
1358  } else if (input instanceof Zone) {
1359    return input;
1360  } else if (isString(input)) {
1361    const lowered = input.toLowerCase();
1362    if (lowered === "default") return defaultZone;else if (lowered === "local" || lowered === "system") return SystemZone.instance;else if (lowered === "utc" || lowered === "gmt") return FixedOffsetZone.utcInstance;else return FixedOffsetZone.parseSpecifier(lowered) || IANAZone.create(input);
1363  } else if (isNumber(input)) {
1364    return FixedOffsetZone.instance(input);
1365  } else if (typeof input === "object" && "offset" in input && typeof input.offset === "function") {
1366    // This is dumb, but the instanceof check above doesn't seem to really work
1367    // so we're duck checking it
1368    return input;
1369  } else {
1370    return new InvalidZone(input);
1371  }
1372}
1373
1374const numberingSystems = {
1375  arab: "[\u0660-\u0669]",
1376  arabext: "[\u06F0-\u06F9]",
1377  bali: "[\u1B50-\u1B59]",
1378  beng: "[\u09E6-\u09EF]",
1379  deva: "[\u0966-\u096F]",
1380  fullwide: "[\uFF10-\uFF19]",
1381  gujr: "[\u0AE6-\u0AEF]",
1382  hanidec: "[〇|一|二|三|四|五|六|七|八|九]",
1383  khmr: "[\u17E0-\u17E9]",
1384  knda: "[\u0CE6-\u0CEF]",
1385  laoo: "[\u0ED0-\u0ED9]",
1386  limb: "[\u1946-\u194F]",
1387  mlym: "[\u0D66-\u0D6F]",
1388  mong: "[\u1810-\u1819]",
1389  mymr: "[\u1040-\u1049]",
1390  orya: "[\u0B66-\u0B6F]",
1391  tamldec: "[\u0BE6-\u0BEF]",
1392  telu: "[\u0C66-\u0C6F]",
1393  thai: "[\u0E50-\u0E59]",
1394  tibt: "[\u0F20-\u0F29]",
1395  latn: "\\d"
1396};
1397const numberingSystemsUTF16 = {
1398  arab: [1632, 1641],
1399  arabext: [1776, 1785],
1400  bali: [6992, 7001],
1401  beng: [2534, 2543],
1402  deva: [2406, 2415],
1403  fullwide: [65296, 65303],
1404  gujr: [2790, 2799],
1405  khmr: [6112, 6121],
1406  knda: [3302, 3311],
1407  laoo: [3792, 3801],
1408  limb: [6470, 6479],
1409  mlym: [3430, 3439],
1410  mong: [6160, 6169],
1411  mymr: [4160, 4169],
1412  orya: [2918, 2927],
1413  tamldec: [3046, 3055],
1414  telu: [3174, 3183],
1415  thai: [3664, 3673],
1416  tibt: [3872, 3881]
1417};
1418const hanidecChars = numberingSystems.hanidec.replace(/[\[|\]]/g, "").split("");
1419function parseDigits(str) {
1420  let value = parseInt(str, 10);
1421  if (isNaN(value)) {
1422    value = "";
1423    for (let i = 0; i < str.length; i++) {
1424      const code = str.charCodeAt(i);
1425      if (str[i].search(numberingSystems.hanidec) !== -1) {
1426        value += hanidecChars.indexOf(str[i]);
1427      } else {
1428        for (const key in numberingSystemsUTF16) {
1429          const [min, max] = numberingSystemsUTF16[key];
1430          if (code >= min && code <= max) {
1431            value += code - min;
1432          }
1433        }
1434      }
1435    }
1436    return parseInt(value, 10);
1437  } else {
1438    return value;
1439  }
1440}
1441
1442// cache of {numberingSystem: {append: regex}}
1443const digitRegexCache = new Map();
1444function resetDigitRegexCache() {
1445  digitRegexCache.clear();
1446}
1447function digitRegex({
1448  numberingSystem
1449}, append = "") {
1450  const ns = numberingSystem || "latn";
1451  let appendCache = digitRegexCache.get(ns);
1452  if (appendCache === undefined) {
1453    appendCache = new Map();
1454    digitRegexCache.set(ns, appendCache);
1455  }
1456  let regex = appendCache.get(append);
1457  if (regex === undefined) {
1458    regex = new RegExp(`${numberingSystems[ns]}${append}`);
1459    appendCache.set(append, regex);
1460  }
1461  return regex;
1462}
1463
1464let now = () => Date.now(),
1465  defaultZone = "system",
1466  defaultLocale = null,
1467  defaultNumberingSystem = null,
1468  defaultOutputCalendar = null,
1469  twoDigitCutoffYear = 60,
vendor: 2,348 bytes, lines 1470-1549
1470  throwOnInvalid,
1471  defaultWeekSettings = null;
1472
1473/**
1474 * Settings contains static getters and setters that control Luxon's overall behavior. Luxon is a simple library with few options, but the ones it does have live here.
1475 */
1476class Settings {
1477  /**
1478   * Get the callback for returning the current timestamp.
1479   * @type {function}
1480   */
1481  static get now() {
1482    return now;
1483  }
1484
1485  /**
1486   * Set the callback for returning the current timestamp.
1487   * The function should return a number, which will be interpreted as an Epoch millisecond count
1488   * @type {function}
1489   * @example Settings.now = () => Date.now() + 3000 // pretend it is 3 seconds in the future
1490   * @example Settings.now = () => 0 // always pretend it's Jan 1, 1970 at midnight in UTC time
1491   */
1492  static set now(n) {
1493    now = n;
1494  }
1495
1496  /**
1497   * Set the default time zone to create DateTimes in. Does not affect existing instances.
1498   * Use the value "system" to reset this value to the system's time zone.
1499   * @type {string}
1500   */
1501  static set defaultZone(zone) {
1502    defaultZone = zone;
1503  }
1504
1505  /**
1506   * Get the default time zone object currently used to create DateTimes. Does not affect existing instances.
1507   * The default value is the system's time zone (the one set on the machine that runs this code).
1508   * @type {Zone}
1509   */
1510  static get defaultZone() {
1511    return normalizeZone(defaultZone, SystemZone.instance);
1512  }
1513
1514  /**
1515   * Get the default locale to create DateTimes with. Does not affect existing instances.
1516   * @type {string}
1517   */
1518  static get defaultLocale() {
1519    return defaultLocale;
1520  }
1521
1522  /**
1523   * Set the default locale to create DateTimes with. Does not affect existing instances.
1524   * @type {string}
1525   */
1526  static set defaultLocale(locale) {
1527    defaultLocale = locale;
1528  }
1529
1530  /**
1531   * Get the default numbering system to create DateTimes with. Does not affect existing instances.
1532   * @type {string}
1533   */
1534  static get defaultNumberingSystem() {
1535    return defaultNumberingSystem;
1536  }
1537
1538  /**
1539   * Set the default numbering system to create DateTimes with. Does not affect existing instances.
1540   * @type {string}
1541   */
1542  static set defaultNumberingSystem(numberingSystem) {
1543    defaultNumberingSystem = numberingSystem;
1544  }
1545
1546  /**
1547   * Get the default output calendar to create DateTimes with. Does not affect existing instances.
1548   * @type {string}
1549   */
vendor: 222,960 bytes, lines 1550-7815
1550  static get defaultOutputCalendar() {
1551    return defaultOutputCalendar;
1552  }
1553
1554  /**
1555   * Set the default output calendar to create DateTimes with. Does not affect existing instances.
1556   * @type {string}
1557   */
1558  static set defaultOutputCalendar(outputCalendar) {
1559    defaultOutputCalendar = outputCalendar;
1560  }
1561
1562  /**
1563   * @typedef {Object} WeekSettings
1564   * @property {number} firstDay
1565   * @property {number} minimalDays
1566   * @property {number[]} weekend
1567   */
1568
1569  /**
1570   * @return {WeekSettings|null}
1571   */
1572  static get defaultWeekSettings() {
1573    return defaultWeekSettings;
1574  }
1575
1576  /**
1577   * Allows overriding the default locale week settings, i.e. the start of the week, the weekend and
1578   * how many days are required in the first week of a year.
1579   * Does not affect existing instances.
1580   *
1581   * @param {WeekSettings|null} weekSettings
1582   */
1583  static set defaultWeekSettings(weekSettings) {
1584    defaultWeekSettings = validateWeekSettings(weekSettings);
1585  }
1586
1587  /**
1588   * Get the cutoff year for whether a 2-digit year string is interpreted in the current or previous century. Numbers higher than the cutoff will be considered to mean 19xx and numbers lower or equal to the cutoff will be considered 20xx.
1589   * @type {number}
1590   */
1591  static get twoDigitCutoffYear() {
1592    return twoDigitCutoffYear;
1593  }
1594
1595  /**
1596   * Set the cutoff year for whether a 2-digit year string is interpreted in the current or previous century. Numbers higher than the cutoff will be considered to mean 19xx and numbers lower or equal to the cutoff will be considered 20xx.
1597   * @type {number}
1598   * @example Settings.twoDigitCutoffYear = 0 // all 'yy' are interpreted as 20th century
1599   * @example Settings.twoDigitCutoffYear = 99 // all 'yy' are interpreted as 21st century
1600   * @example Settings.twoDigitCutoffYear = 50 // '49' -> 2049; '50' -> 1950
1601   * @example Settings.twoDigitCutoffYear = 1950 // interpreted as 50
1602   * @example Settings.twoDigitCutoffYear = 2050 // ALSO interpreted as 50
1603   */
1604  static set twoDigitCutoffYear(cutoffYear) {
1605    twoDigitCutoffYear = cutoffYear % 100;
1606  }
1607
1608  /**
1609   * Get whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals
1610   * @type {boolean}
1611   */
1612  static get throwOnInvalid() {
1613    return throwOnInvalid;
1614  }
1615
1616  /**
1617   * Set whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals
1618   * @type {boolean}
1619   */
1620  static set throwOnInvalid(t) {
1621    throwOnInvalid = t;
1622  }
1623
1624  /**
1625   * Reset Luxon's global caches. Should only be necessary in testing scenarios.
1626   * @return {void}
1627   */
1628  static resetCaches() {
1629    Locale.resetCache();
1630    IANAZone.resetCache();
1631    DateTime.resetCache();
1632    resetDigitRegexCache();
1633  }
1634}
1635
1636class Invalid {
1637  constructor(reason, explanation) {
1638    this.reason = reason;
1639    this.explanation = explanation;
1640  }
1641  toMessage() {
1642    if (this.explanation) {
1643      return `${this.reason}: ${this.explanation}`;
1644    } else {
1645      return this.reason;
1646    }
1647  }
1648}
1649
1650const nonLeapLadder = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
1651  leapLadder = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335];
1652function unitOutOfRange(unit, value) {
1653  return new Invalid("unit out of range", `you specified ${value} (of type ${typeof value}) as a ${unit}, which is invalid`);
1654}
1655function dayOfWeek(year, month, day) {
1656  const d = new Date(Date.UTC(year, month - 1, day));
1657  if (year < 100 && year >= 0) {
1658    d.setUTCFullYear(d.getUTCFullYear() - 1900);
1659  }
1660  const js = d.getUTCDay();
1661  return js === 0 ? 7 : js;
1662}
1663function computeOrdinal(year, month, day) {
1664  return day + (isLeapYear(year) ? leapLadder : nonLeapLadder)[month - 1];
1665}
1666function uncomputeOrdinal(year, ordinal) {
1667  const table = isLeapYear(year) ? leapLadder : nonLeapLadder,
1668    month0 = table.findIndex(i => i < ordinal),
1669    day = ordinal - table[month0];
1670  return {
1671    month: month0 + 1,
1672    day
1673  };
1674}
1675function isoWeekdayToLocal(isoWeekday, startOfWeek) {
1676  return (isoWeekday - startOfWeek + 7) % 7 + 1;
1677}
1678
1679/**
1680 * @private
1681 */
1682
1683function gregorianToWeek(gregObj, minDaysInFirstWeek = 4, startOfWeek = 1) {
1684  const {
1685      year,
1686      month,
1687      day
1688    } = gregObj,
1689    ordinal = computeOrdinal(year, month, day),
1690    weekday = isoWeekdayToLocal(dayOfWeek(year, month, day), startOfWeek);
1691  let weekNumber = Math.floor((ordinal - weekday + 14 - minDaysInFirstWeek) / 7),
1692    weekYear;
1693  if (weekNumber < 1) {
1694    weekYear = year - 1;
1695    weekNumber = weeksInWeekYear(weekYear, minDaysInFirstWeek, startOfWeek);
1696  } else if (weekNumber > weeksInWeekYear(year, minDaysInFirstWeek, startOfWeek)) {
1697    weekYear = year + 1;
1698    weekNumber = 1;
1699  } else {
1700    weekYear = year;
1701  }
1702  return {
1703    weekYear,
1704    weekNumber,
1705    weekday,
1706    ...timeObject(gregObj)
1707  };
1708}
1709function weekToGregorian(weekData, minDaysInFirstWeek = 4, startOfWeek = 1) {
1710  const {
1711      weekYear,
1712      weekNumber,
1713      weekday
1714    } = weekData,
1715    weekdayOfJan4 = isoWeekdayToLocal(dayOfWeek(weekYear, 1, minDaysInFirstWeek), startOfWeek),
1716    yearInDays = daysInYear(weekYear);
1717  let ordinal = weekNumber * 7 + weekday - weekdayOfJan4 - 7 + minDaysInFirstWeek,
1718    year;
1719  if (ordinal < 1) {
1720    year = weekYear - 1;
1721    ordinal += daysInYear(year);
1722  } else if (ordinal > yearInDays) {
1723    year = weekYear + 1;
1724    ordinal -= daysInYear(weekYear);
1725  } else {
1726    year = weekYear;
1727  }
1728  const {
1729    month,
1730    day
1731  } = uncomputeOrdinal(year, ordinal);
1732  return {
1733    year,
1734    month,
1735    day,
1736    ...timeObject(weekData)
1737  };
1738}
1739function gregorianToOrdinal(gregData) {
1740  const {
1741    year,
1742    month,
1743    day
1744  } = gregData;
1745  const ordinal = computeOrdinal(year, month, day);
1746  return {
1747    year,
1748    ordinal,
1749    ...timeObject(gregData)
1750  };
1751}
1752function ordinalToGregorian(ordinalData) {
1753  const {
1754    year,
1755    ordinal
1756  } = ordinalData;
1757  const {
1758    month,
1759    day
1760  } = uncomputeOrdinal(year, ordinal);
1761  return {
1762    year,
1763    month,
1764    day,
1765    ...timeObject(ordinalData)
1766  };
1767}
1768
1769/**
1770 * Check if local week units like localWeekday are used in obj.
1771 * If so, validates that they are not mixed with ISO week units and then copies them to the normal week unit properties.
1772 * Modifies obj in-place!
1773 * @param obj the object values
1774 */
1775function usesLocalWeekValues(obj, loc) {
1776  const hasLocaleWeekData = !isUndefined(obj.localWeekday) || !isUndefined(obj.localWeekNumber) || !isUndefined(obj.localWeekYear);
1777  if (hasLocaleWeekData) {
1778    const hasIsoWeekData = !isUndefined(obj.weekday) || !isUndefined(obj.weekNumber) || !isUndefined(obj.weekYear);
1779    if (hasIsoWeekData) {
1780      throw new ConflictingSpecificationError("Cannot mix locale-based week fields with ISO-based week fields");
1781    }
1782    if (!isUndefined(obj.localWeekday)) obj.weekday = obj.localWeekday;
1783    if (!isUndefined(obj.localWeekNumber)) obj.weekNumber = obj.localWeekNumber;
1784    if (!isUndefined(obj.localWeekYear)) obj.weekYear = obj.localWeekYear;
1785    delete obj.localWeekday;
1786    delete obj.localWeekNumber;
1787    delete obj.localWeekYear;
1788    return {
1789      minDaysInFirstWeek: loc.getMinDaysInFirstWeek(),
1790      startOfWeek: loc.getStartOfWeek()
1791    };
1792  } else {
1793    return {
1794      minDaysInFirstWeek: 4,
1795      startOfWeek: 1
1796    };
1797  }
1798}
1799function hasInvalidWeekData(obj, minDaysInFirstWeek = 4, startOfWeek = 1) {
1800  const validYear = isInteger(obj.weekYear),
1801    validWeek = integerBetween(obj.weekNumber, 1, weeksInWeekYear(obj.weekYear, minDaysInFirstWeek, startOfWeek)),
1802    validWeekday = integerBetween(obj.weekday, 1, 7);
1803  if (!validYear) {
1804    return unitOutOfRange("weekYear", obj.weekYear);
1805  } else if (!validWeek) {
1806    return unitOutOfRange("week", obj.weekNumber);
1807  } else if (!validWeekday) {
1808    return unitOutOfRange("weekday", obj.weekday);
1809  } else return false;
1810}
1811function hasInvalidOrdinalData(obj) {
1812  const validYear = isInteger(obj.year),
1813    validOrdinal = integerBetween(obj.ordinal, 1, daysInYear(obj.year));
1814  if (!validYear) {
1815    return unitOutOfRange("year", obj.year);
1816  } else if (!validOrdinal) {
1817    return unitOutOfRange("ordinal", obj.ordinal);
1818  } else return false;
1819}
1820function hasInvalidGregorianData(obj) {
1821  const validYear = isInteger(obj.year),
1822    validMonth = integerBetween(obj.month, 1, 12),
1823    validDay = integerBetween(obj.day, 1, daysInMonth(obj.year, obj.month));
1824  if (!validYear) {
1825    return unitOutOfRange("year", obj.year);
1826  } else if (!validMonth) {
1827    return unitOutOfRange("month", obj.month);
1828  } else if (!validDay) {
1829    return unitOutOfRange("day", obj.day);
1830  } else return false;
1831}
1832function hasInvalidTimeData(obj) {
1833  const {
1834    hour,
1835    minute,
1836    second,
1837    millisecond
1838  } = obj;
1839  const validHour = integerBetween(hour, 0, 23) || hour === 24 && minute === 0 && second === 0 && millisecond === 0,
1840    validMinute = integerBetween(minute, 0, 59),
1841    validSecond = integerBetween(second, 0, 59),
1842    validMillisecond = integerBetween(millisecond, 0, 999);
1843  if (!validHour) {
1844    return unitOutOfRange("hour", hour);
1845  } else if (!validMinute) {
1846    return unitOutOfRange("minute", minute);
1847  } else if (!validSecond) {
1848    return unitOutOfRange("second", second);
1849  } else if (!validMillisecond) {
1850    return unitOutOfRange("millisecond", millisecond);
1851  } else return false;
1852}
1853
1854/*
1855  This is just a junk drawer, containing anything used across multiple classes.
1856  Because Luxon is small(ish), this should stay small and we won't worry about splitting
1857  it up into, say, parsingUtil.js and basicUtil.js and so on. But they are divided up by feature area.
1858*/
1859
1860/**
1861 * @private
1862 */
1863
1864// TYPES
1865
1866function isUndefined(o) {
1867  return typeof o === "undefined";
1868}
1869function isNumber(o) {
1870  return typeof o === "number";
1871}
1872function isInteger(o) {
1873  return typeof o === "number" && o % 1 === 0;
1874}
1875function isString(o) {
1876  return typeof o === "string";
1877}
1878function isDate(o) {
1879  return Object.prototype.toString.call(o) === "[object Date]";
1880}
1881
1882// CAPABILITIES
1883
1884function hasRelative() {
1885  try {
1886    return typeof Intl !== "undefined" && !!Intl.RelativeTimeFormat;
1887  } catch (e) {
1888    return false;
1889  }
1890}
1891function hasLocaleWeekInfo() {
1892  try {
1893    return typeof Intl !== "undefined" && !!Intl.Locale && ("weekInfo" in Intl.Locale.prototype || "getWeekInfo" in Intl.Locale.prototype);
1894  } catch (e) {
1895    return false;
1896  }
1897}
1898
1899// OBJECTS AND ARRAYS
1900
1901function maybeArray(thing) {
1902  return Array.isArray(thing) ? thing : [thing];
1903}
1904function bestBy(arr, by, compare) {
1905  if (arr.length === 0) {
1906    return undefined;
1907  }
1908  return arr.reduce((best, next) => {
1909    const pair = [by(next), next];
1910    if (!best) {
1911      return pair;
1912    } else if (compare(best[0], pair[0]) === best[0]) {
1913      return best;
1914    } else {
1915      return pair;
1916    }
1917  }, null)[1];
1918}
1919function pick(obj, keys) {
1920  return keys.reduce((a, k) => {
1921    a[k] = obj[k];
1922    return a;
1923  }, {});
1924}
1925function hasOwnProperty(obj, prop) {
1926  return Object.prototype.hasOwnProperty.call(obj, prop);
1927}
1928function validateWeekSettings(settings) {
1929  if (settings == null) {
1930    return null;
1931  } else if (typeof settings !== "object") {
1932    throw new InvalidArgumentError("Week settings must be an object");
1933  } else {
1934    if (!integerBetween(settings.firstDay, 1, 7) || !integerBetween(settings.minimalDays, 1, 7) || !Array.isArray(settings.weekend) || settings.weekend.some(v => !integerBetween(v, 1, 7))) {
1935      throw new InvalidArgumentError("Invalid week settings");
1936    }
1937    return {
1938      firstDay: settings.firstDay,
1939      minimalDays: settings.minimalDays,
1940      weekend: Array.from(settings.weekend)
1941    };
1942  }
1943}
1944
1945// NUMBERS AND STRINGS
1946
1947function integerBetween(thing, bottom, top) {
1948  return isInteger(thing) && thing >= bottom && thing <= top;
1949}
1950
1951// x % n but takes the sign of n instead of x
1952function floorMod(x, n) {
1953  return x - n * Math.floor(x / n);
1954}
1955function padStart(input, n = 2) {
1956  const isNeg = input < 0;
1957  let padded;
1958  if (isNeg) {
1959    padded = "-" + ("" + -input).padStart(n, "0");
1960  } else {
1961    padded = ("" + input).padStart(n, "0");
1962  }
1963  return padded;
1964}
1965function parseInteger(string) {
1966  if (isUndefined(string) || string === null || string === "") {
1967    return undefined;
1968  } else {
1969    return parseInt(string, 10);
1970  }
1971}
1972function parseFloating(string) {
1973  if (isUndefined(string) || string === null || string === "") {
1974    return undefined;
1975  } else {
1976    return parseFloat(string);
1977  }
1978}
1979function parseMillis(fraction) {
1980  // Return undefined (instead of 0) in these cases, where fraction is not set
1981  if (isUndefined(fraction) || fraction === null || fraction === "") {
1982    return undefined;
1983  } else {
1984    const f = parseFloat("0." + fraction) * 1000;
1985    return Math.floor(f);
1986  }
1987}
1988function roundTo(number, digits, rounding = "round") {
1989  const factor = 10 ** digits;
1990  switch (rounding) {
1991    case "expand":
1992      return number > 0 ? Math.ceil(number * factor) / factor : Math.floor(number * factor) / factor;
1993    case "trunc":
1994      return Math.trunc(number * factor) / factor;
1995    case "round":
1996      return Math.round(number * factor) / factor;
1997    case "floor":
1998      return Math.floor(number * factor) / factor;
1999    case "ceil":
2000      return Math.ceil(number * factor) / factor;
2001    default:
2002      throw new RangeError(`Value rounding ${rounding} is out of range`);
2003  }
2004}
2005
2006// DATE BASICS
2007
2008function isLeapYear(year) {
2009  return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
2010}
2011function daysInYear(year) {
2012  return isLeapYear(year) ? 366 : 365;
2013}
2014function daysInMonth(year, month) {
2015  const modMonth = floorMod(month - 1, 12) + 1,
2016    modYear = year + (month - modMonth) / 12;
2017  if (modMonth === 2) {
2018    return isLeapYear(modYear) ? 29 : 28;
2019  } else {
2020    return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][modMonth - 1];
2021  }
2022}
2023
2024// convert a calendar object to a local timestamp (epoch, but with the offset baked in)
2025function objToLocalTS(obj) {
2026  let d = Date.UTC(obj.year, obj.month - 1, obj.day, obj.hour, obj.minute, obj.second, obj.millisecond);
2027
2028  // for legacy reasons, years between 0 and 99 are interpreted as 19XX; revert that
2029  if (obj.year < 100 && obj.year >= 0) {
2030    d = new Date(d);
2031    // set the month and day again, this is necessary because year 2000 is a leap year, but year 100 is not
2032    // so if obj.year is in 99, but obj.day makes it roll over into year 100,
2033    // the calculations done by Date.UTC are using year 2000 - which is incorrect
2034    d.setUTCFullYear(obj.year, obj.month - 1, obj.day);
2035  }
2036  return +d;
2037}
2038
2039// adapted from moment.js: https://github.com/moment/moment/blob/000ac1800e620f770f4eb31b5ae908f6167b0ab2/src/lib/units/week-calendar-utils.js
2040function firstWeekOffset(year, minDaysInFirstWeek, startOfWeek) {
2041  const fwdlw = isoWeekdayToLocal(dayOfWeek(year, 1, minDaysInFirstWeek), startOfWeek);
2042  return -fwdlw + minDaysInFirstWeek - 1;
2043}
2044function weeksInWeekYear(weekYear, minDaysInFirstWeek = 4, startOfWeek = 1) {
2045  const weekOffset = firstWeekOffset(weekYear, minDaysInFirstWeek, startOfWeek);
2046  const weekOffsetNext = firstWeekOffset(weekYear + 1, minDaysInFirstWeek, startOfWeek);
2047  return (daysInYear(weekYear) - weekOffset + weekOffsetNext) / 7;
2048}
2049function untruncateYear(year) {
2050  if (year > 99) {
2051    return year;
2052  } else return year > Settings.twoDigitCutoffYear ? 1900 + year : 2000 + year;
2053}
2054
2055// PARSING
2056
2057function parseZoneInfo(ts, offsetFormat, locale, timeZone = null) {
2058  const date = new Date(ts),
2059    intlOpts = {
2060      hourCycle: "h23",
2061      year: "numeric",
2062      month: "2-digit",
2063      day: "2-digit",
2064      hour: "2-digit",
2065      minute: "2-digit"
2066    };
2067  if (timeZone) {
2068    intlOpts.timeZone = timeZone;
2069  }
2070  const modified = {
2071    timeZoneName: offsetFormat,
2072    ...intlOpts
2073  };
2074  const parsed = new Intl.DateTimeFormat(locale, modified).formatToParts(date).find(m => m.type.toLowerCase() === "timezonename");
2075  return parsed ? parsed.value : null;
2076}
2077
2078// signedOffset('-5', '30') -> -330
2079function signedOffset(offHourStr, offMinuteStr) {
2080  let offHour = parseInt(offHourStr, 10);
2081
2082  // don't || this because we want to preserve -0
2083  if (Number.isNaN(offHour)) {
2084    offHour = 0;
2085  }
2086  const offMin = parseInt(offMinuteStr, 10) || 0,
2087    offMinSigned = offHour < 0 || Object.is(offHour, -0) ? -offMin : offMin;
2088  return offHour * 60 + offMinSigned;
2089}
2090
2091// COERCION
2092
2093function asNumber(value) {
2094  const numericValue = Number(value);
2095  if (typeof value === "boolean" || value === "" || !Number.isFinite(numericValue)) throw new InvalidArgumentError(`Invalid unit value ${value}`);
2096  return numericValue;
2097}
2098function normalizeObject(obj, normalizer) {
2099  const normalized = {};
2100  for (const u in obj) {
2101    if (hasOwnProperty(obj, u)) {
2102      const v = obj[u];
2103      if (v === undefined || v === null) continue;
2104      normalized[normalizer(u)] = asNumber(v);
2105    }
2106  }
2107  return normalized;
2108}
2109
2110/**
2111 * Returns the offset's value as a string
2112 * @param {number} ts - Epoch milliseconds for which to get the offset
2113 * @param {string} format - What style of offset to return.
2114 *                          Accepts 'narrow', 'short', or 'techie'. Returning '+6', '+06:00', or '+0600' respectively
2115 * @return {string}
2116 */
2117function formatOffset(offset, format) {
2118  const hours = Math.trunc(Math.abs(offset / 60)),
2119    minutes = Math.trunc(Math.abs(offset % 60)),
2120    sign = offset >= 0 ? "+" : "-";
2121  switch (format) {
2122    case "short":
2123      return `${sign}${padStart(hours, 2)}:${padStart(minutes, 2)}`;
2124    case "narrow":
2125      return `${sign}${hours}${minutes > 0 ? `:${minutes}` : ""}`;
2126    case "techie":
2127      return `${sign}${padStart(hours, 2)}${padStart(minutes, 2)}`;
2128    default:
2129      throw new RangeError(`Value format ${format} is out of range for property format`);
2130  }
2131}
2132function timeObject(obj) {
2133  return pick(obj, ["hour", "minute", "second", "millisecond"]);
2134}
2135
2136/**
2137 * @private
2138 */
2139
2140const monthsLong = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
2141const monthsShort = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
2142const monthsNarrow = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"];
2143function months(length) {
2144  switch (length) {
2145    case "narrow":
2146      return [...monthsNarrow];
2147    case "short":
2148      return [...monthsShort];
2149    case "long":
2150      return [...monthsLong];
2151    case "numeric":
2152      return ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
2153    case "2-digit":
2154      return ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
2155    default:
2156      return null;
2157  }
2158}
2159const weekdaysLong = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
2160const weekdaysShort = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
2161const weekdaysNarrow = ["M", "T", "W", "T", "F", "S", "S"];
2162function weekdays(length) {
2163  switch (length) {
2164    case "narrow":
2165      return [...weekdaysNarrow];
2166    case "short":
2167      return [...weekdaysShort];
2168    case "long":
2169      return [...weekdaysLong];
2170    case "numeric":
2171      return ["1", "2", "3", "4", "5", "6", "7"];
2172    default:
2173      return null;
2174  }
2175}
2176const meridiems = ["AM", "PM"];
2177const erasLong = ["Before Christ", "Anno Domini"];
2178const erasShort = ["BC", "AD"];
2179const erasNarrow = ["B", "A"];
2180function eras(length) {
2181  switch (length) {
2182    case "narrow":
2183      return [...erasNarrow];
2184    case "short":
2185      return [...erasShort];
2186    case "long":
2187      return [...erasLong];
2188    default:
2189      return null;
2190  }
2191}
2192function meridiemForDateTime(dt) {
2193  return meridiems[dt.hour < 12 ? 0 : 1];
2194}
2195function weekdayForDateTime(dt, length) {
2196  return weekdays(length)[dt.weekday - 1];
2197}
2198function monthForDateTime(dt, length) {
2199  return months(length)[dt.month - 1];
2200}
2201function eraForDateTime(dt, length) {
2202  return eras(length)[dt.year < 0 ? 0 : 1];
2203}
2204function formatRelativeTime(unit, count, numeric = "always", narrow = false) {
2205  const units = {
2206    years: ["year", "yr."],
2207    quarters: ["quarter", "qtr."],
2208    months: ["month", "mo."],
2209    weeks: ["week", "wk."],
2210    days: ["day", "day", "days"],
2211    hours: ["hour", "hr."],
2212    minutes: ["minute", "min."],
2213    seconds: ["second", "sec."]
2214  };
2215  const lastable = ["hours", "minutes", "seconds"].indexOf(unit) === -1;
2216  if (numeric === "auto" && lastable) {
2217    const isDay = unit === "days";
2218    switch (count) {
2219      case 1:
2220        return isDay ? "tomorrow" : `next ${units[unit][0]}`;
2221      case -1:
2222        return isDay ? "yesterday" : `last ${units[unit][0]}`;
2223      case 0:
2224        return isDay ? "today" : `this ${units[unit][0]}`;
2225    }
2226  }
2227
2228  const isInPast = Object.is(count, -0) || count < 0,
2229    fmtValue = Math.abs(count),
2230    singular = fmtValue === 1,
2231    lilUnits = units[unit],
2232    fmtUnit = narrow ? singular ? lilUnits[1] : lilUnits[2] || lilUnits[1] : singular ? units[unit][0] : unit;
2233  return isInPast ? `${fmtValue} ${fmtUnit} ago` : `in ${fmtValue} ${fmtUnit}`;
2234}
2235
2236function stringifyTokens(splits, tokenToString) {
2237  let s = "";
2238  for (const token of splits) {
2239    if (token.literal) {
2240      s += token.val;
2241    } else {
2242      s += tokenToString(token.val);
2243    }
2244  }
2245  return s;
2246}
2247const macroTokenToFormatOpts = {
2248  D: DATE_SHORT,
2249  DD: DATE_MED,
2250  DDD: DATE_FULL,
2251  DDDD: DATE_HUGE,
2252  t: TIME_SIMPLE,
2253  tt: TIME_WITH_SECONDS,
2254  ttt: TIME_WITH_SHORT_OFFSET,
2255  tttt: TIME_WITH_LONG_OFFSET,
2256  T: TIME_24_SIMPLE,
2257  TT: TIME_24_WITH_SECONDS,
2258  TTT: TIME_24_WITH_SHORT_OFFSET,
2259  TTTT: TIME_24_WITH_LONG_OFFSET,
2260  f: DATETIME_SHORT,
2261  ff: DATETIME_MED,
2262  fff: DATETIME_FULL,
2263  ffff: DATETIME_HUGE,
2264  F: DATETIME_SHORT_WITH_SECONDS,
2265  FF: DATETIME_MED_WITH_SECONDS,
2266  FFF: DATETIME_FULL_WITH_SECONDS,
2267  FFFF: DATETIME_HUGE_WITH_SECONDS
2268};
2269
2270/**
2271 * @private
2272 */
2273
2274class Formatter {
2275  static create(locale, opts = {}) {
2276    return new Formatter(locale, opts);
2277  }
2278  static parseFormat(fmt) {
2279    // white-space is always considered a literal in user-provided formats
2280    // the " " token has a special meaning (see unitForToken)
2281
2282    let current = null,
2283      currentFull = "",
2284      bracketed = false;
2285    const splits = [];
2286    for (let i = 0; i < fmt.length; i++) {
2287      const c = fmt.charAt(i);
2288      if (c === "'") {
2289        // turn '' into a literal signal quote instead of just skipping the empty literal
2290        if (currentFull.length > 0 || bracketed) {
2291          splits.push({
2292            literal: bracketed || /^\s+$/.test(currentFull),
2293            val: currentFull === "" ? "'" : currentFull
2294          });
2295        }
2296        current = null;
2297        currentFull = "";
2298        bracketed = !bracketed;
2299      } else if (bracketed) {
2300        currentFull += c;
2301      } else if (c === current) {
2302        currentFull += c;
2303      } else {
2304        if (currentFull.length > 0) {
2305          splits.push({
2306            literal: /^\s+$/.test(currentFull),
2307            val: currentFull
2308          });
2309        }
2310        currentFull = c;
2311        current = c;
2312      }
2313    }
2314    if (currentFull.length > 0) {
2315      splits.push({
2316        literal: bracketed || /^\s+$/.test(currentFull),
2317        val: currentFull
2318      });
2319    }
2320    return splits;
2321  }
2322  static macroTokenToFormatOpts(token) {
2323    return macroTokenToFormatOpts[token];
2324  }
2325  constructor(locale, formatOpts) {
2326    this.opts = formatOpts;
2327    this.loc = locale;
2328    this.systemLoc = null;
2329  }
2330  formatWithSystemDefault(dt, opts) {
2331    if (this.systemLoc === null) {
2332      this.systemLoc = this.loc.redefaultToSystem();
2333    }
2334    const df = this.systemLoc.dtFormatter(dt, {
2335      ...this.opts,
2336      ...opts
2337    });
2338    return df.format();
2339  }
2340  dtFormatter(dt, opts = {}) {
2341    return this.loc.dtFormatter(dt, {
2342      ...this.opts,
2343      ...opts
2344    });
2345  }
2346  formatDateTime(dt, opts) {
2347    return this.dtFormatter(dt, opts).format();
2348  }
2349  formatDateTimeParts(dt, opts) {
2350    return this.dtFormatter(dt, opts).formatToParts();
2351  }
2352  formatInterval(interval, opts) {
2353    const df = this.dtFormatter(interval.start, opts);
2354    return df.dtf.formatRange(interval.start.toJSDate(), interval.end.toJSDate());
2355  }
2356  resolvedOptions(dt, opts) {
2357    return this.dtFormatter(dt, opts).resolvedOptions();
2358  }
2359  num(n, p = 0, signDisplay = undefined) {
2360    // we get some perf out of doing this here, annoyingly
2361    if (this.opts.forceSimple) {
2362      return padStart(n, p);
2363    }
2364    const opts = {
2365      ...this.opts
2366    };
2367    if (p > 0) {
2368      opts.padTo = p;
2369    }
2370    if (signDisplay) {
2371      opts.signDisplay = signDisplay;
2372    }
2373    return this.loc.numberFormatter(opts).format(n);
2374  }
2375  formatDateTimeFromString(dt, fmt) {
2376    const knownEnglish = this.loc.listingMode() === "en",
2377      useDateTimeFormatter = this.loc.outputCalendar && this.loc.outputCalendar !== "gregory",
2378      string = (opts, extract) => this.loc.extract(dt, opts, extract),
2379      formatOffset = opts => {
2380        if (dt.isOffsetFixed && dt.offset === 0 && opts.allowZ) {
2381          return "Z";
2382        }
2383        return dt.isValid ? dt.zone.formatOffset(dt.ts, opts.format) : "";
2384      },
2385      meridiem = () => knownEnglish ? meridiemForDateTime(dt) : string({
2386        hour: "numeric",
2387        hourCycle: "h12"
2388      }, "dayperiod"),
2389      month = (length, standalone) => knownEnglish ? monthForDateTime(dt, length) : string(standalone ? {
2390        month: length
2391      } : {
2392        month: length,
2393        day: "numeric"
2394      }, "month"),
2395      weekday = (length, standalone) => knownEnglish ? weekdayForDateTime(dt, length) : string(standalone ? {
2396        weekday: length
2397      } : {
2398        weekday: length,
2399        month: "long",
2400        day: "numeric"
2401      }, "weekday"),
2402      maybeMacro = token => {
2403        const formatOpts = Formatter.macroTokenToFormatOpts(token);
2404        if (formatOpts) {
2405          return this.formatWithSystemDefault(dt, formatOpts);
2406        } else {
2407          return token;
2408        }
2409      },
2410      era = length => knownEnglish ? eraForDateTime(dt, length) : string({
2411        era: length
2412      }, "era"),
2413      tokenToString = token => {
2414        // Where possible: https://cldr.unicode.org/translation/date-time/date-time-symbols
2415        switch (token) {
2416          // ms
2417          case "S":
2418            return this.num(dt.millisecond);
2419          case "u":
2420          // falls through
2421          case "SSS":
2422            return this.num(dt.millisecond, 3);
2423          // seconds
2424          case "s":
2425            return this.num(dt.second);
2426          case "ss":
2427            return this.num(dt.second, 2);
2428          // fractional seconds
2429          case "uu":
2430            return this.num(Math.floor(dt.millisecond / 10), 2);
2431          case "uuu":
2432            return this.num(Math.floor(dt.millisecond / 100));
2433          // minutes
2434          case "m":
2435            return this.num(dt.minute);
2436          case "mm":
2437            return this.num(dt.minute, 2);
2438          // hours
2439          case "h":
2440            return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12);
2441          case "hh":
2442            return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12, 2);
2443          case "H":
2444            return this.num(dt.hour);
2445          case "HH":
2446            return this.num(dt.hour, 2);
2447          // offset
2448          case "Z":
2449            // like +6
2450            return formatOffset({
2451              format: "narrow",
2452              allowZ: this.opts.allowZ
2453            });
2454          case "ZZ":
2455            // like +06:00
2456            return formatOffset({
2457              format: "short",
2458              allowZ: this.opts.allowZ
2459            });
2460          case "ZZZ":
2461            // like +0600
2462            return formatOffset({
2463              format: "techie",
2464              allowZ: this.opts.allowZ
2465            });
2466          case "ZZZZ":
2467            // like EST
2468            return dt.zone.offsetName(dt.ts, {
2469              format: "short",
2470              locale: this.loc.locale
2471            });
2472          case "ZZZZZ":
2473            // like Eastern Standard Time
2474            return dt.zone.offsetName(dt.ts, {
2475              format: "long",
2476              locale: this.loc.locale
2477            });
2478          // zone
2479          case "z":
2480            // like America/New_York
2481            return dt.zoneName;
2482          // meridiems
2483          case "a":
2484            return meridiem();
2485          // dates
2486          case "d":
2487            return useDateTimeFormatter ? string({
2488              day: "numeric"
2489            }, "day") : this.num(dt.day);
2490          case "dd":
2491            return useDateTimeFormatter ? string({
2492              day: "2-digit"
2493            }, "day") : this.num(dt.day, 2);
2494          // weekdays - standalone
2495          case "c":
2496            // like 1
2497            return this.num(dt.weekday);
2498          case "ccc":
2499            // like 'Tues'
2500            return weekday("short", true);
2501          case "cccc":
2502            // like 'Tuesday'
2503            return weekday("long", true);
2504          case "ccccc":
2505            // like 'T'
2506            return weekday("narrow", true);
2507          // weekdays - format
2508          case "E":
2509            // like 1
2510            return this.num(dt.weekday);
2511          case "EEE":
2512            // like 'Tues'
2513            return weekday("short", false);
2514          case "EEEE":
2515            // like 'Tuesday'
2516            return weekday("long", false);
2517          case "EEEEE":
2518            // like 'T'
2519            return weekday("narrow", false);
2520          // months - standalone
2521          case "L":
2522            // like 1
2523            return useDateTimeFormatter ? string({
2524              month: "numeric",
2525              day: "numeric"
2526            }, "month") : this.num(dt.month);
2527          case "LL":
2528            // like 01, doesn't seem to work
2529            return useDateTimeFormatter ? string({
2530              month: "2-digit",
2531              day: "numeric"
2532            }, "month") : this.num(dt.month, 2);
2533          case "LLL":
2534            // like Jan
2535            return month("short", true);
2536          case "LLLL":
2537            // like January
2538            return month("long", true);
2539          case "LLLLL":
2540            // like J
2541            return month("narrow", true);
2542          // months - format
2543          case "M":
2544            // like 1
2545            return useDateTimeFormatter ? string({
2546              month: "numeric"
2547            }, "month") : this.num(dt.month);
2548          case "MM":
2549            // like 01
2550            return useDateTimeFormatter ? string({
2551              month: "2-digit"
2552            }, "month") : this.num(dt.month, 2);
2553          case "MMM":
2554            // like Jan
2555            return month("short", false);
2556          case "MMMM":
2557            // like January
2558            return month("long", false);
2559          case "MMMMM":
2560            // like J
2561            return month("narrow", false);
2562          // years
2563          case "y":
2564            // like 2014
2565            return useDateTimeFormatter ? string({
2566              year: "numeric"
2567            }, "year") : this.num(dt.year);
2568          case "yy":
2569            // like 14
2570            return useDateTimeFormatter ? string({
2571              year: "2-digit"
2572            }, "year") : this.num(dt.year.toString().slice(-2), 2);
2573          case "yyyy":
2574            // like 0012
2575            return useDateTimeFormatter ? string({
2576              year: "numeric"
2577            }, "year") : this.num(dt.year, 4);
2578          case "yyyyyy":
2579            // like 000012
2580            return useDateTimeFormatter ? string({
2581              year: "numeric"
2582            }, "year") : this.num(dt.year, 6);
2583          // eras
2584          case "G":
2585            // like AD
2586            return era("short");
2587          case "GG":
2588            // like Anno Domini
2589            return era("long");
2590          case "GGGGG":
2591            return era("narrow");
2592          case "kk":
2593            return this.num(dt.weekYear.toString().slice(-2), 2);
2594          case "kkkk":
2595            return this.num(dt.weekYear, 4);
2596          case "W":
2597            return this.num(dt.weekNumber);
2598          case "WW":
2599            return this.num(dt.weekNumber, 2);
2600          case "n":
2601            return this.num(dt.localWeekNumber);
2602          case "nn":
2603            return this.num(dt.localWeekNumber, 2);
2604          case "ii":
2605            return this.num(dt.localWeekYear.toString().slice(-2), 2);
2606          case "iiii":
2607            return this.num(dt.localWeekYear, 4);
2608          case "o":
2609            return this.num(dt.ordinal);
2610          case "ooo":
2611            return this.num(dt.ordinal, 3);
2612          case "q":
2613            // like 1
2614            return this.num(dt.quarter);
2615          case "qq":
2616            // like 01
2617            return this.num(dt.quarter, 2);
2618          case "X":
2619            return this.num(Math.floor(dt.ts / 1000));
2620          case "x":
2621            return this.num(dt.ts);
2622          default:
2623            return maybeMacro(token);
2624        }
2625      };
2626    return stringifyTokens(Formatter.parseFormat(fmt), tokenToString);
2627  }
2628  formatDurationFromString(dur, fmt) {
2629    const invertLargest = this.opts.signMode === "negativeLargestOnly" ? -1 : 1;
2630    const tokenToField = token => {
2631        switch (token[0]) {
2632          case "S":
2633            return "milliseconds";
2634          case "s":
2635            return "seconds";
2636          case "m":
2637            return "minutes";
2638          case "h":
2639            return "hours";
2640          case "d":
2641            return "days";
2642          case "w":
2643            return "weeks";
2644          case "M":
2645            return "months";
2646          case "y":
2647            return "years";
2648          default:
2649            return null;
2650        }
2651      },
2652      tokenToString = (lildur, info) => token => {
2653        const mapped = tokenToField(token);
2654        if (mapped) {
2655          const inversionFactor = info.isNegativeDuration && mapped !== info.largestUnit ? invertLargest : 1;
2656          let signDisplay;
2657          if (this.opts.signMode === "negativeLargestOnly" && mapped !== info.largestUnit) {
2658            signDisplay = "never";
2659          } else if (this.opts.signMode === "all") {
2660            signDisplay = "always";
2661          } else {
2662            // "auto" and "negative" are the same, but "auto" has better support
2663            signDisplay = "auto";
2664          }
2665          return this.num(lildur.get(mapped) * inversionFactor, token.length, signDisplay);
2666        } else {
2667          return token;
2668        }
2669      },
2670      tokens = Formatter.parseFormat(fmt),
2671      realTokens = tokens.reduce((found, {
2672        literal,
2673        val
2674      }) => literal ? found : found.concat(val), []),
2675      collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter(t => t)),
2676      durationInfo = {
2677        isNegativeDuration: collapsed < 0,
2678        // this relies on "collapsed" being based on "shiftTo", which builds up the object
2679        // in order
2680        largestUnit: Object.keys(collapsed.values)[0]
2681      };
2682    return stringifyTokens(tokens, tokenToString(collapsed, durationInfo));
2683  }
2684}
2685
2686/*
2687 * This file handles parsing for well-specified formats. Here's how it works:
2688 * Two things go into parsing: a regex to match with and an extractor to take apart the groups in the match.
2689 * An extractor is just a function that takes a regex match array and returns a { year: ..., month: ... } object
2690 * parse() does the work of executing the regex and applying the extractor. It takes multiple regex/extractor pairs to try in sequence.
2691 * Extractors can take a "cursor" representing the offset in the match to look at. This makes it easy to combine extractors.
2692 * combineExtractors() does the work of combining them, keeping track of the cursor through multiple extractions.
2693 * Some extractions are super dumb and simpleParse and fromStrings help DRY them.
2694 */
2695
2696const ianaRegex = /[A-Za-z_+-]{1,256}(?::?\/[A-Za-z0-9_+-]{1,256}(?:\/[A-Za-z0-9_+-]{1,256})?)?/;
2697function combineRegexes(...regexes) {
2698  const full = regexes.reduce((f, r) => f + r.source, "");
2699  return RegExp(`^${full}$`);
2700}
2701function combineExtractors(...extractors) {
2702  return m => extractors.reduce(([mergedVals, mergedZone, cursor], ex) => {
2703    const [val, zone, next] = ex(m, cursor);
2704    return [{
2705      ...mergedVals,
2706      ...val
2707    }, zone || mergedZone, next];
2708  }, [{}, null, 1]).slice(0, 2);
2709}
2710function parse(s, ...patterns) {
2711  if (s == null) {
2712    return [null, null];
2713  }
2714  for (const [regex, extractor] of patterns) {
2715    const m = regex.exec(s);
2716    if (m) {
2717      return extractor(m);
2718    }
2719  }
2720  return [null, null];
2721}
2722function simpleParse(...keys) {
2723  return (match, cursor) => {
2724    const ret = {};
2725    let i;
2726    for (i = 0; i < keys.length; i++) {
2727      ret[keys[i]] = parseInteger(match[cursor + i]);
2728    }
2729    return [ret, null, cursor + i];
2730  };
2731}
2732
2733// ISO and SQL parsing
2734const offsetRegex = /(?:([Zz])|([+-]\d\d)(?::?(\d\d))?)/;
2735const isoExtendedZone = `(?:${offsetRegex.source}?(?:\\[(${ianaRegex.source})\\])?)?`;
2736const isoTimeBaseRegex = /(\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,30}))?)?)?/;
2737const isoTimeRegex = RegExp(`${isoTimeBaseRegex.source}${isoExtendedZone}`);
2738const isoTimeExtensionRegex = RegExp(`(?:[Tt]${isoTimeRegex.source})?`);
2739const isoYmdRegex = /([+-]\d{6}|\d{4})(?:-?(\d\d)(?:-?(\d\d))?)?/;
2740const isoWeekRegex = /(\d{4})-?W(\d\d)(?:-?(\d))?/;
2741const isoOrdinalRegex = /(\d{4})-?(\d{3})/;
2742const extractISOWeekData = simpleParse("weekYear", "weekNumber", "weekDay");
2743const extractISOOrdinalData = simpleParse("year", "ordinal");
2744const sqlYmdRegex = /(\d{4})-(\d\d)-(\d\d)/; // dumbed-down version of the ISO one
2745const sqlTimeRegex = RegExp(`${isoTimeBaseRegex.source} ?(?:${offsetRegex.source}|(${ianaRegex.source}))?`);
2746const sqlTimeExtensionRegex = RegExp(`(?: ${sqlTimeRegex.source})?`);
2747function int(match, pos, fallback) {
2748  const m = match[pos];
2749  return isUndefined(m) ? fallback : parseInteger(m);
2750}
2751function extractISOYmd(match, cursor) {
2752  const item = {
2753    year: int(match, cursor),
2754    month: int(match, cursor + 1, 1),
2755    day: int(match, cursor + 2, 1)
2756  };
2757  return [item, null, cursor + 3];
2758}
2759function extractISOTime(match, cursor) {
2760  const item = {
2761    hours: int(match, cursor, 0),
2762    minutes: int(match, cursor + 1, 0),
2763    seconds: int(match, cursor + 2, 0),
2764    milliseconds: parseMillis(match[cursor + 3])
2765  };
2766  return [item, null, cursor + 4];
2767}
2768function extractISOOffset(match, cursor) {
2769  const local = !match[cursor] && !match[cursor + 1],
2770    fullOffset = signedOffset(match[cursor + 1], match[cursor + 2]),
2771    zone = local ? null : FixedOffsetZone.instance(fullOffset);
2772  return [{}, zone, cursor + 3];
2773}
2774function extractIANAZone(match, cursor) {
2775  const zone = match[cursor] ? IANAZone.create(match[cursor]) : null;
2776  return [{}, zone, cursor + 1];
2777}
2778
2779// ISO time parsing
2780
2781const isoTimeOnly = RegExp(`^T?${isoTimeBaseRegex.source}$`);
2782
2783// ISO duration parsing
2784
2785const isoDuration = /^-?P(?:(?:(-?\d{1,20}(?:\.\d{1,20})?)Y)?(?:(-?\d{1,20}(?:\.\d{1,20})?)M)?(?:(-?\d{1,20}(?:\.\d{1,20})?)W)?(?:(-?\d{1,20}(?:\.\d{1,20})?)D)?(?:T(?:(-?\d{1,20}(?:\.\d{1,20})?)H)?(?:(-?\d{1,20}(?:\.\d{1,20})?)M)?(?:(-?\d{1,20})(?:[.,](-?\d{1,20}))?S)?)?)$/;
2786function extractISODuration(match) {
2787  const [s, yearStr, monthStr, weekStr, dayStr, hourStr, minuteStr, secondStr, millisecondsStr] = match;
2788  const hasNegativePrefix = s[0] === "-";
2789  const negativeSeconds = secondStr && secondStr[0] === "-";
2790  const maybeNegate = (num, force = false) => num !== undefined && (force || num && hasNegativePrefix) ? -num : num;
2791  return [{
2792    years: maybeNegate(parseFloating(yearStr)),
2793    months: maybeNegate(parseFloating(monthStr)),
2794    weeks: maybeNegate(parseFloating(weekStr)),
2795    days: maybeNegate(parseFloating(dayStr)),
2796    hours: maybeNegate(parseFloating(hourStr)),
2797    minutes: maybeNegate(parseFloating(minuteStr)),
2798    seconds: maybeNegate(parseFloating(secondStr), secondStr === "-0"),
2799    milliseconds: maybeNegate(parseMillis(millisecondsStr), negativeSeconds)
2800  }];
2801}
2802
2803// These are a little braindead. EDT *should* tell us that we're in, say, America/New_York
2804// and not just that we're in -240 *right now*. But since I don't think these are used that often
2805// I'm just going to ignore that
2806const obsOffsets = {
2807  GMT: 0,
2808  EDT: -4 * 60,
2809  EST: -5 * 60,
2810  CDT: -5 * 60,
2811  CST: -6 * 60,
2812  MDT: -6 * 60,
2813  MST: -7 * 60,
2814  PDT: -7 * 60,
2815  PST: -8 * 60
2816};
2817function fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
2818  const result = {
2819    year: yearStr.length === 2 ? untruncateYear(parseInteger(yearStr)) : parseInteger(yearStr),
2820    month: monthsShort.indexOf(monthStr) + 1,
2821    day: parseInteger(dayStr),
2822    hour: parseInteger(hourStr),
2823    minute: parseInteger(minuteStr)
2824  };
2825  if (secondStr) result.second = parseInteger(secondStr);
2826  if (weekdayStr) {
2827    result.weekday = weekdayStr.length > 3 ? weekdaysLong.indexOf(weekdayStr) + 1 : weekdaysShort.indexOf(weekdayStr) + 1;
2828  }
2829  return result;
2830}
2831
2832// RFC 2822/5322
2833const rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|(?:([+-]\d\d)(\d\d)))$/;
2834function extractRFC2822(match) {
2835  const [, weekdayStr, dayStr, monthStr, yearStr, hourStr, minuteStr, secondStr, obsOffset, milOffset, offHourStr, offMinuteStr] = match,
2836    result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr);
2837  let offset;
2838  if (obsOffset) {
2839    offset = obsOffsets[obsOffset];
2840  } else if (milOffset) {
2841    offset = 0;
2842  } else {
2843    offset = signedOffset(offHourStr, offMinuteStr);
2844  }
2845  return [result, new FixedOffsetZone(offset)];
2846}
2847function preprocessRFC2822(s) {
2848  // Remove comments and folding whitespace and replace multiple-spaces with a single space
2849  return s.replace(/\([^()]*\)|[\n\t]/g, " ").replace(/(\s\s+)/g, " ").trim();
2850}
2851
2852// http date
2853
2854const rfc1123 = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d\d) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d\d):(\d\d):(\d\d) GMT$/,
2855  rfc850 = /^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (\d\d)-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d\d) (\d\d):(\d\d):(\d\d) GMT$/,
2856  ascii = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ( \d|\d\d) (\d\d):(\d\d):(\d\d) (\d{4})$/;
2857function extractRFC1123Or850(match) {
2858  const [, weekdayStr, dayStr, monthStr, yearStr, hourStr, minuteStr, secondStr] = match,
2859    result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr);
2860  return [result, FixedOffsetZone.utcInstance];
2861}
2862function extractASCII(match) {
2863  const [, weekdayStr, monthStr, dayStr, hourStr, minuteStr, secondStr, yearStr] = match,
2864    result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr);
2865  return [result, FixedOffsetZone.utcInstance];
2866}
2867const isoYmdWithTimeExtensionRegex = combineRegexes(isoYmdRegex, isoTimeExtensionRegex);
2868const isoWeekWithTimeExtensionRegex = combineRegexes(isoWeekRegex, isoTimeExtensionRegex);
2869const isoOrdinalWithTimeExtensionRegex = combineRegexes(isoOrdinalRegex, isoTimeExtensionRegex);
2870const isoTimeCombinedRegex = combineRegexes(isoTimeRegex);
2871const extractISOYmdTimeAndOffset = combineExtractors(extractISOYmd, extractISOTime, extractISOOffset, extractIANAZone);
2872const extractISOWeekTimeAndOffset = combineExtractors(extractISOWeekData, extractISOTime, extractISOOffset, extractIANAZone);
2873const extractISOOrdinalDateAndTime = combineExtractors(extractISOOrdinalData, extractISOTime, extractISOOffset, extractIANAZone);
2874const extractISOTimeAndOffset = combineExtractors(extractISOTime, extractISOOffset, extractIANAZone);
2875
2876/*
2877 * @private
2878 */
2879
2880function parseISODate(s) {
2881  return parse(s, [isoYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset], [isoWeekWithTimeExtensionRegex, extractISOWeekTimeAndOffset], [isoOrdinalWithTimeExtensionRegex, extractISOOrdinalDateAndTime], [isoTimeCombinedRegex, extractISOTimeAndOffset]);
2882}
2883function parseRFC2822Date(s) {
2884  return parse(preprocessRFC2822(s), [rfc2822, extractRFC2822]);
2885}
2886function parseHTTPDate(s) {
2887  return parse(s, [rfc1123, extractRFC1123Or850], [rfc850, extractRFC1123Or850], [ascii, extractASCII]);
2888}
2889function parseISODuration(s) {
2890  return parse(s, [isoDuration, extractISODuration]);
2891}
2892const extractISOTimeOnly = combineExtractors(extractISOTime);
2893function parseISOTimeOnly(s) {
2894  return parse(s, [isoTimeOnly, extractISOTimeOnly]);
2895}
2896const sqlYmdWithTimeExtensionRegex = combineRegexes(sqlYmdRegex, sqlTimeExtensionRegex);
2897const sqlTimeCombinedRegex = combineRegexes(sqlTimeRegex);
2898const extractISOTimeOffsetAndIANAZone = combineExtractors(extractISOTime, extractISOOffset, extractIANAZone);
2899function parseSQL(s) {
2900  return parse(s, [sqlYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset], [sqlTimeCombinedRegex, extractISOTimeOffsetAndIANAZone]);
2901}
2902
2903const INVALID$2 = "Invalid Duration";
2904
2905// unit conversion constants
2906const lowOrderMatrix = {
2907    weeks: {
2908      days: 7,
2909      hours: 7 * 24,
2910      minutes: 7 * 24 * 60,
2911      seconds: 7 * 24 * 60 * 60,
2912      milliseconds: 7 * 24 * 60 * 60 * 1000
2913    },
2914    days: {
2915      hours: 24,
2916      minutes: 24 * 60,
2917      seconds: 24 * 60 * 60,
2918      milliseconds: 24 * 60 * 60 * 1000
2919    },
2920    hours: {
2921      minutes: 60,
2922      seconds: 60 * 60,
2923      milliseconds: 60 * 60 * 1000
2924    },
2925    minutes: {
2926      seconds: 60,
2927      milliseconds: 60 * 1000
2928    },
2929    seconds: {
2930      milliseconds: 1000
2931    }
2932  },
2933  casualMatrix = {
2934    years: {
2935      quarters: 4,
2936      months: 12,
2937      weeks: 52,
2938      days: 365,
2939      hours: 365 * 24,
2940      minutes: 365 * 24 * 60,
2941      seconds: 365 * 24 * 60 * 60,
2942      milliseconds: 365 * 24 * 60 * 60 * 1000
2943    },
2944    quarters: {
2945      months: 3,
2946      weeks: 13,
2947      days: 91,
2948      hours: 91 * 24,
2949      minutes: 91 * 24 * 60,
2950      seconds: 91 * 24 * 60 * 60,
2951      milliseconds: 91 * 24 * 60 * 60 * 1000
2952    },
2953    months: {
2954      weeks: 4,
2955      days: 30,
2956      hours: 30 * 24,
2957      minutes: 30 * 24 * 60,
2958      seconds: 30 * 24 * 60 * 60,
2959      milliseconds: 30 * 24 * 60 * 60 * 1000
2960    },
2961    ...lowOrderMatrix
2962  },
2963  daysInYearAccurate = 146097.0 / 400,
2964  daysInMonthAccurate = 146097.0 / 4800,
2965  accurateMatrix = {
2966    years: {
2967      quarters: 4,
2968      months: 12,
2969      weeks: daysInYearAccurate / 7,
2970      days: daysInYearAccurate,
2971      hours: daysInYearAccurate * 24,
2972      minutes: daysInYearAccurate * 24 * 60,
2973      seconds: daysInYearAccurate * 24 * 60 * 60,
2974      milliseconds: daysInYearAccurate * 24 * 60 * 60 * 1000
2975    },
2976    quarters: {
2977      months: 3,
2978      weeks: daysInYearAccurate / 28,
2979      days: daysInYearAccurate / 4,
2980      hours: daysInYearAccurate * 24 / 4,
2981      minutes: daysInYearAccurate * 24 * 60 / 4,
2982      seconds: daysInYearAccurate * 24 * 60 * 60 / 4,
2983      milliseconds: daysInYearAccurate * 24 * 60 * 60 * 1000 / 4
2984    },
2985    months: {
2986      weeks: daysInMonthAccurate / 7,
2987      days: daysInMonthAccurate,
2988      hours: daysInMonthAccurate * 24,
2989      minutes: daysInMonthAccurate * 24 * 60,
2990      seconds: daysInMonthAccurate * 24 * 60 * 60,
2991      milliseconds: daysInMonthAccurate * 24 * 60 * 60 * 1000
2992    },
2993    ...lowOrderMatrix
2994  };
2995
2996// units ordered by size
2997const orderedUnits$1 = ["years", "quarters", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds"];
2998const reverseUnits = orderedUnits$1.slice(0).reverse();
2999
3000// clone really means "create another instance just like this one, but with these changes"
3001function clone$1(dur, alts, clear = false) {
3002  // deep merge for vals
3003  const conf = {
3004    values: clear ? alts.values : {
3005      ...dur.values,
3006      ...(alts.values || {})
3007    },
3008    loc: dur.loc.clone(alts.loc),
3009    conversionAccuracy: alts.conversionAccuracy || dur.conversionAccuracy,
3010    matrix: alts.matrix || dur.matrix
3011  };
3012  return new Duration(conf);
3013}
3014function durationToMillis(matrix, vals) {
3015  var _vals$milliseconds;
3016  let sum = (_vals$milliseconds = vals.milliseconds) != null ? _vals$milliseconds : 0;
3017  for (const unit of reverseUnits.slice(1)) {
3018    if (vals[unit]) {
3019      sum += vals[unit] * matrix[unit]["milliseconds"];
3020    }
3021  }
3022  return sum;
3023}
3024
3025// NB: mutates parameters
3026function normalizeValues(matrix, vals) {
3027  // the logic below assumes the overall value of the duration is positive
3028  // if this is not the case, factor is used to make it so
3029  const factor = durationToMillis(matrix, vals) < 0 ? -1 : 1;
3030  orderedUnits$1.reduceRight((previous, current) => {
3031    if (!isUndefined(vals[current])) {
3032      if (previous) {
3033        const previousVal = vals[previous] * factor;
3034        const conv = matrix[current][previous];
3035
3036        // if (previousVal < 0):
3037        // lower order unit is negative (e.g. { years: 2, days: -2 })
3038        // normalize this by reducing the higher order unit by the appropriate amount
3039        // and increasing the lower order unit
3040        // this can never make the higher order unit negative, because this function only operates
3041        // on positive durations, so the amount of time represented by the lower order unit cannot
3042        // be larger than the higher order unit
3043        // else:
3044        // lower order unit is positive (e.g. { years: 2, days: 450 } or { years: -2, days: 450 })
3045        // in this case we attempt to convert as much as possible from the lower order unit into
3046        // the higher order one
3047        //
3048        // Math.floor takes care of both of these cases, rounding away from 0
3049        // if previousVal < 0 it makes the absolute value larger
3050        // if previousVal >= it makes the absolute value smaller
3051        const rollUp = Math.floor(previousVal / conv);
3052        vals[current] += rollUp * factor;
3053        vals[previous] -= rollUp * conv * factor;
3054      }
3055      return current;
3056    } else {
3057      return previous;
3058    }
3059  }, null);
3060
3061  // try to convert any decimals into smaller units if possible
3062  // for example for { years: 2.5, days: 0, seconds: 0 } we want to get { years: 2, days: 182, hours: 12 }
3063  orderedUnits$1.reduce((previous, current) => {
3064    if (!isUndefined(vals[current])) {
3065      if (previous) {
3066        const fraction = vals[previous] % 1;
3067        vals[previous] -= fraction;
3068        vals[current] += fraction * matrix[previous][current];
3069      }
3070      return current;
3071    } else {
3072      return previous;
3073    }
3074  }, null);
3075}
3076
3077// Remove all properties with a value of 0 from an object
3078function removeZeroes(vals) {
3079  const newVals = {};
3080  for (const [key, value] of Object.entries(vals)) {
3081    if (value !== 0) {
3082      newVals[key] = value;
3083    }
3084  }
3085  return newVals;
3086}
3087
3088/**
3089 * A Duration object represents a period of time, like "2 months" or "1 day, 1 hour". Conceptually, it's just a map of units to their quantities, accompanied by some additional configuration and methods for creating, parsing, interrogating, transforming, and formatting them. They can be used on their own or in conjunction with other Luxon types; for example, you can use {@link DateTime#plus} to add a Duration object to a DateTime, producing another DateTime.
3090 *
3091 * Here is a brief overview of commonly used methods and getters in Duration:
3092 *
3093 * * **Creation** To create a Duration, use {@link Duration.fromMillis}, {@link Duration.fromObject}, or {@link Duration.fromISO}.
3094 * * **Unit values** See the {@link Duration#years}, {@link Duration#months}, {@link Duration#weeks}, {@link Duration#days}, {@link Duration#hours}, {@link Duration#minutes}, {@link Duration#seconds}, {@link Duration#milliseconds} accessors.
3095 * * **Configuration** See  {@link Duration#locale} and {@link Duration#numberingSystem} accessors.
3096 * * **Transformation** To create new Durations out of old ones use {@link Duration#plus}, {@link Duration#minus}, {@link Duration#normalize}, {@link Duration#set}, {@link Duration#reconfigure}, {@link Duration#shiftTo}, and {@link Duration#negate}.
3097 * * **Output** To convert the Duration into other representations, see {@link Duration#as}, {@link Duration#toISO}, {@link Duration#toFormat}, and {@link Duration#toJSON}
3098 *
3099 * There's are more methods documented below. In addition, for more information on subtler topics like internationalization and validity, see the external documentation.
3100 */
3101class Duration {
3102  /**
3103   * @private
3104   */
3105  constructor(config) {
3106    const accurate = config.conversionAccuracy === "longterm" || false;
3107    let matrix = accurate ? accurateMatrix : casualMatrix;
3108    if (config.matrix) {
3109      matrix = config.matrix;
3110    }
3111
3112    /**
3113     * @access private
3114     */
3115    this.values = config.values;
3116    /**
3117     * @access private
3118     */
3119    this.loc = config.loc || Locale.create();
3120    /**
3121     * @access private
3122     */
3123    this.conversionAccuracy = accurate ? "longterm" : "casual";
3124    /**
3125     * @access private
3126     */
3127    this.invalid = config.invalid || null;
3128    /**
3129     * @access private
3130     */
3131    this.matrix = matrix;
3132    /**
3133     * @access private
3134     */
3135    this.isLuxonDuration = true;
3136  }
3137
3138  /**
3139   * Create Duration from a number of milliseconds.
3140   * @param {number} count of milliseconds
3141   * @param {Object} opts - options for parsing
3142   * @param {string} [opts.locale='en-US'] - the locale to use
3143   * @param {string} opts.numberingSystem - the numbering system to use
3144   * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use
3145   * @return {Duration}
3146   */
3147  static fromMillis(count, opts) {
3148    return Duration.fromObject({
3149      milliseconds: count
3150    }, opts);
3151  }
3152
3153  /**
3154   * Create a Duration from a JavaScript object with keys like 'years' and 'hours'.
3155   * If this object is empty then a zero milliseconds duration is returned.
3156   * @param {Object} obj - the object to create the DateTime from
3157   * @param {number} obj.years
3158   * @param {number} obj.quarters
3159   * @param {number} obj.months
3160   * @param {number} obj.weeks
3161   * @param {number} obj.days
3162   * @param {number} obj.hours
3163   * @param {number} obj.minutes
3164   * @param {number} obj.seconds
3165   * @param {number} obj.milliseconds
3166   * @param {Object} [opts=[]] - options for creating this Duration
3167   * @param {string} [opts.locale='en-US'] - the locale to use
3168   * @param {string} opts.numberingSystem - the numbering system to use
3169   * @param {string} [opts.conversionAccuracy='casual'] - the preset conversion system to use
3170   * @param {string} [opts.matrix=Object] - the custom conversion system to use
3171   * @return {Duration}
3172   */
3173  static fromObject(obj, opts = {}) {
3174    if (obj == null || typeof obj !== "object") {
3175      throw new InvalidArgumentError(`Duration.fromObject: argument expected to be an object, got ${obj === null ? "null" : typeof obj}`);
3176    }
3177    return new Duration({
3178      values: normalizeObject(obj, Duration.normalizeUnit),
3179      loc: Locale.fromObject(opts),
3180      conversionAccuracy: opts.conversionAccuracy,
3181      matrix: opts.matrix
3182    });
3183  }
3184
3185  /**
3186   * Create a Duration from DurationLike.
3187   *
3188   * @param {Object | number | Duration} durationLike
3189   * One of:
3190   * - object with keys like 'years' and 'hours'.
3191   * - number representing milliseconds
3192   * - Duration instance
3193   * @return {Duration}
3194   */
3195  static fromDurationLike(durationLike) {
3196    if (isNumber(durationLike)) {
3197      return Duration.fromMillis(durationLike);
3198    } else if (Duration.isDuration(durationLike)) {
3199      return durationLike;
3200    } else if (typeof durationLike === "object") {
3201      return Duration.fromObject(durationLike);
3202    } else {
3203      throw new InvalidArgumentError(`Unknown duration argument ${durationLike} of type ${typeof durationLike}`);
3204    }
3205  }
3206
3207  /**
3208   * Create a Duration from an ISO 8601 duration string.
3209   * @param {string} text - text to parse
3210   * @param {Object} opts - options for parsing
3211   * @param {string} [opts.locale='en-US'] - the locale to use
3212   * @param {string} opts.numberingSystem - the numbering system to use
3213   * @param {string} [opts.conversionAccuracy='casual'] - the preset conversion system to use
3214   * @param {string} [opts.matrix=Object] - the preset conversion system to use
3215   * @see https://en.wikipedia.org/wiki/ISO_8601#Durations
3216   * @example Duration.fromISO('P3Y6M1W4DT12H30M5S').toObject() //=> { years: 3, months: 6, weeks: 1, days: 4, hours: 12, minutes: 30, seconds: 5 }
3217   * @example Duration.fromISO('PT23H').toObject() //=> { hours: 23 }
3218   * @example Duration.fromISO('P5Y3M').toObject() //=> { years: 5, months: 3 }
3219   * @return {Duration}
3220   */
3221  static fromISO(text, opts) {
3222    const [parsed] = parseISODuration(text);
3223    if (parsed) {
3224      return Duration.fromObject(parsed, opts);
3225    } else {
3226      return Duration.invalid("unparsable", `the input "${text}" can't be parsed as ISO 8601`);
3227    }
3228  }
3229
3230  /**
3231   * Create a Duration from an ISO 8601 time string.
3232   * @param {string} text - text to parse
3233   * @param {Object} opts - options for parsing
3234   * @param {string} [opts.locale='en-US'] - the locale to use
3235   * @param {string} opts.numberingSystem - the numbering system to use
3236   * @param {string} [opts.conversionAccuracy='casual'] - the preset conversion system to use
3237   * @param {string} [opts.matrix=Object] - the conversion system to use
3238   * @see https://en.wikipedia.org/wiki/ISO_8601#Times
3239   * @example Duration.fromISOTime('11:22:33.444').toObject() //=> { hours: 11, minutes: 22, seconds: 33, milliseconds: 444 }
3240   * @example Duration.fromISOTime('11:00').toObject() //=> { hours: 11, minutes: 0, seconds: 0 }
3241   * @example Duration.fromISOTime('T11:00').toObject() //=> { hours: 11, minutes: 0, seconds: 0 }
3242   * @example Duration.fromISOTime('1100').toObject() //=> { hours: 11, minutes: 0, seconds: 0 }
3243   * @example Duration.fromISOTime('T1100').toObject() //=> { hours: 11, minutes: 0, seconds: 0 }
3244   * @return {Duration}
3245   */
3246  static fromISOTime(text, opts) {
3247    const [parsed] = parseISOTimeOnly(text);
3248    if (parsed) {
3249      return Duration.fromObject(parsed, opts);
3250    } else {
3251      return Duration.invalid("unparsable", `the input "${text}" can't be parsed as ISO 8601`);
3252    }
3253  }
3254
3255  /**
3256   * Create an invalid Duration.
3257   * @param {string} reason - simple string of why this datetime is invalid. Should not contain parameters or anything else data-dependent
3258   * @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information
3259   * @return {Duration}
3260   */
3261  static invalid(reason, explanation = null) {
3262    if (!reason) {
3263      throw new InvalidArgumentError("need to specify a reason the Duration is invalid");
3264    }
3265    const invalid = reason instanceof Invalid ? reason : new Invalid(reason, explanation);
3266    if (Settings.throwOnInvalid) {
3267      throw new InvalidDurationError(invalid);
3268    } else {
3269      return new Duration({
3270        invalid
3271      });
3272    }
3273  }
3274
3275  /**
3276   * @private
3277   */
3278  static normalizeUnit(unit) {
3279    const normalized = {
3280      year: "years",
3281      years: "years",
3282      quarter: "quarters",
3283      quarters: "quarters",
3284      month: "months",
3285      months: "months",
3286      week: "weeks",
3287      weeks: "weeks",
3288      day: "days",
3289      days: "days",
3290      hour: "hours",
3291      hours: "hours",
3292      minute: "minutes",
3293      minutes: "minutes",
3294      second: "seconds",
3295      seconds: "seconds",
3296      millisecond: "milliseconds",
3297      milliseconds: "milliseconds"
3298    }[unit ? unit.toLowerCase() : unit];
3299    if (!normalized) throw new InvalidUnitError(unit);
3300    return normalized;
3301  }
3302
3303  /**
3304   * Check if an object is a Duration. Works across context boundaries
3305   * @param {object} o
3306   * @return {boolean}
3307   */
3308  static isDuration(o) {
3309    return o && o.isLuxonDuration || false;
3310  }
3311
3312  /**
3313   * Get  the locale of a Duration, such 'en-GB'
3314   * @type {string}
3315   */
3316  get locale() {
3317    return this.isValid ? this.loc.locale : null;
3318  }
3319
3320  /**
3321   * Get the numbering system of a Duration, such 'beng'. The numbering system is used when formatting the Duration
3322   *
3323   * @type {string}
3324   */
3325  get numberingSystem() {
3326    return this.isValid ? this.loc.numberingSystem : null;
3327  }
3328
3329  /**
3330   * Returns a string representation of this Duration formatted according to the specified format string. You may use these tokens:
3331   * * `S` for milliseconds
3332   * * `s` for seconds
3333   * * `m` for minutes
3334   * * `h` for hours
3335   * * `d` for days
3336   * * `w` for weeks
3337   * * `M` for months
3338   * * `y` for years
3339   * Notes:
3340   * * Add padding by repeating the token, e.g. "yy" pads the years to two digits, "hhhh" pads the hours out to four digits
3341   * * Tokens can be escaped by wrapping with single quotes.
3342   * * The duration will be converted to the set of units in the format string using {@link Duration#shiftTo} and the Durations's conversion accuracy setting.
3343   * @param {string} fmt - the format string
3344   * @param {Object} opts - options
3345   * @param {boolean} [opts.floor=true] - floor numerical values
3346   * @param {'negative'|'all'|'negativeLargestOnly'} [opts.signMode=negative] - How to handle signs
3347   * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("y d s") //=> "1 6 2"
3348   * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("yy dd sss") //=> "01 06 002"
3349   * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("M S") //=> "12 518402000"
3350   * @example Duration.fromObject({ days: 6, seconds: 2 }).toFormat("d s", { signMode: "all" }) //=> "+6 +2"
3351   * @example Duration.fromObject({ days: -6, seconds: -2 }).toFormat("d s", { signMode: "all" }) //=> "-6 -2"
3352   * @example Duration.fromObject({ days: -6, seconds: -2 }).toFormat("d s", { signMode: "negativeLargestOnly" }) //=> "-6 2"
3353   * @return {string}
3354   */
3355  toFormat(fmt, opts = {}) {
3356    // reverse-compat since 1.2; we always round down now, never up, and we do it by default
3357    const fmtOpts = {
3358      ...opts,
3359      floor: opts.round !== false && opts.floor !== false
3360    };
3361    return this.isValid ? Formatter.create(this.loc, fmtOpts).formatDurationFromString(this, fmt) : INVALID$2;
3362  }
3363
3364  /**
3365   * Returns a string representation of a Duration with all units included.
3366   * To modify its behavior, use `listStyle` and any Intl.NumberFormat option, though `unitDisplay` is especially relevant.
3367   * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options
3368   * @param {Object} opts - Formatting options. Accepts the same keys as the options parameter of the native `Intl.NumberFormat` constructor, as well as `listStyle`.
3369   * @param {string} [opts.listStyle='narrow'] - How to format the merged list. Corresponds to the `style` property of the options parameter of the native `Intl.ListFormat` constructor.
3370   * @param {boolean} [opts.showZeros=true] - Show all units previously used by the duration even if they are zero
3371   * @example
3372   * ```js
3373   * var dur = Duration.fromObject({ months: 1, weeks: 0, hours: 5, minutes: 6 })
3374   * dur.toHuman() //=> '1 month, 0 weeks, 5 hours, 6 minutes'
3375   * dur.toHuman({ listStyle: "long" }) //=> '1 month, 0 weeks, 5 hours, and 6 minutes'
3376   * dur.toHuman({ unitDisplay: "short" }) //=> '1 mth, 0 wks, 5 hr, 6 min'
3377   * dur.toHuman({ showZeros: false }) //=> '1 month, 5 hours, 6 minutes'
3378   * ```
3379   */
3380  toHuman(opts = {}) {
3381    if (!this.isValid) return INVALID$2;
3382    const showZeros = opts.showZeros !== false;
3383    const l = orderedUnits$1.map(unit => {
3384      const val = this.values[unit];
3385      if (isUndefined(val) || val === 0 && !showZeros) {
3386        return null;
3387      }
3388      return this.loc.numberFormatter({
3389        style: "unit",
3390        unitDisplay: "long",
3391        ...opts,
3392        unit: unit.slice(0, -1)
3393      }).format(val);
3394    }).filter(n => n);
3395    return this.loc.listFormatter({
3396      type: "conjunction",
3397      style: opts.listStyle || "narrow",
3398      ...opts
3399    }).format(l);
3400  }
3401
3402  /**
3403   * Returns a JavaScript object with this Duration's values.
3404   * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toObject() //=> { years: 1, days: 6, seconds: 2 }
3405   * @return {Object}
3406   */
3407  toObject() {
3408    if (!this.isValid) return {};
3409    return {
3410      ...this.values
3411    };
3412  }
3413
3414  /**
3415   * Returns an ISO 8601-compliant string representation of this Duration.
3416   * @see https://en.wikipedia.org/wiki/ISO_8601#Durations
3417   * @example Duration.fromObject({ years: 3, seconds: 45 }).toISO() //=> 'P3YT45S'
3418   * @example Duration.fromObject({ months: 4, seconds: 45 }).toISO() //=> 'P4MT45S'
3419   * @example Duration.fromObject({ months: 5 }).toISO() //=> 'P5M'
3420   * @example Duration.fromObject({ minutes: 5 }).toISO() //=> 'PT5M'
3421   * @example Duration.fromObject({ milliseconds: 6 }).toISO() //=> 'PT0.006S'
3422   * @return {string}
3423   */
3424  toISO() {
3425    // we could use the formatter, but this is an easier way to get the minimum string
3426    if (!this.isValid) return null;
3427    let s = "P";
3428    if (this.years !== 0) s += this.years + "Y";
3429    if (this.months !== 0 || this.quarters !== 0) s += this.months + this.quarters * 3 + "M";
3430    if (this.weeks !== 0) s += this.weeks + "W";
3431    if (this.days !== 0) s += this.days + "D";
3432    if (this.hours !== 0 || this.minutes !== 0 || this.seconds !== 0 || this.milliseconds !== 0) s += "T";
3433    if (this.hours !== 0) s += this.hours + "H";
3434    if (this.minutes !== 0) s += this.minutes + "M";
3435    if (this.seconds !== 0 || this.milliseconds !== 0)
3436      // this will handle "floating point madness" by removing extra decimal places
3437      // https://stackoverflow.com/questions/588004/is-floating-point-math-broken
3438      s += roundTo(this.seconds + this.milliseconds / 1000, 3) + "S";
3439    if (s === "P") s += "T0S";
3440    return s;
3441  }
3442
3443  /**
3444   * Returns an ISO 8601-compliant string representation of this Duration, formatted as a time of day.
3445   * Note that this will return null if the duration is invalid, negative, or equal to or greater than 24 hours.
3446   * @see https://en.wikipedia.org/wiki/ISO_8601#Times
3447   * @param {Object} opts - options
3448   * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0
3449   * @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0
3450   * @param {boolean} [opts.includePrefix=false] - include the `T` prefix
3451   * @param {string} [opts.format='extended'] - choose between the basic and extended format
3452   * @example Duration.fromObject({ hours: 11 }).toISOTime() //=> '11:00:00.000'
3453   * @example Duration.fromObject({ hours: 11 }).toISOTime({ suppressMilliseconds: true }) //=> '11:00:00'
3454   * @example Duration.fromObject({ hours: 11 }).toISOTime({ suppressSeconds: true }) //=> '11:00'
3455   * @example Duration.fromObject({ hours: 11 }).toISOTime({ includePrefix: true }) //=> 'T11:00:00.000'
3456   * @example Duration.fromObject({ hours: 11 }).toISOTime({ format: 'basic' }) //=> '110000.000'
3457   * @return {string}
3458   */
3459  toISOTime(opts = {}) {
3460    if (!this.isValid) return null;
3461    const millis = this.toMillis();
3462    if (millis < 0 || millis >= 86400000) return null;
3463    opts = {
3464      suppressMilliseconds: false,
3465      suppressSeconds: false,
3466      includePrefix: false,
3467      format: "extended",
3468      ...opts,
3469      includeOffset: false
3470    };
3471    const dateTime = DateTime.fromMillis(millis, {
3472      zone: "UTC"
3473    });
3474    return dateTime.toISOTime(opts);
3475  }
3476
3477  /**
3478   * Returns an ISO 8601 representation of this Duration appropriate for use in JSON.
3479   * @return {string}
3480   */
3481  toJSON() {
3482    return this.toISO();
3483  }
3484
3485  /**
3486   * Returns an ISO 8601 representation of this Duration appropriate for use in debugging.
3487   * @return {string}
3488   */
3489  toString() {
3490    return this.toISO();
3491  }
3492
3493  /**
3494   * Returns a string representation of this Duration appropriate for the REPL.
3495   * @return {string}
3496   */
3497  [Symbol.for("nodejs.util.inspect.custom")]() {
3498    if (this.isValid) {
3499      return `Duration { values: ${JSON.stringify(this.values)} }`;
3500    } else {
3501      return `Duration { Invalid, reason: ${this.invalidReason} }`;
3502    }
3503  }
3504
3505  /**
3506   * Returns an milliseconds value of this Duration.
3507   * @return {number}
3508   */
3509  toMillis() {
3510    if (!this.isValid) return NaN;
3511    return durationToMillis(this.matrix, this.values);
3512  }
3513
3514  /**
3515   * Returns an milliseconds value of this Duration. Alias of {@link toMillis}
3516   * @return {number}
3517   */
3518  valueOf() {
3519    return this.toMillis();
3520  }
3521
3522  /**
3523   * Make this Duration longer by the specified amount. Return a newly-constructed Duration.
3524   * @param {Duration|Object|number} duration - The amount to add. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject()
3525   * @return {Duration}
3526   */
3527  plus(duration) {
3528    if (!this.isValid) return this;
3529    const dur = Duration.fromDurationLike(duration),
3530      result = {};
3531    for (const k of orderedUnits$1) {
3532      if (hasOwnProperty(dur.values, k) || hasOwnProperty(this.values, k)) {
3533        result[k] = dur.get(k) + this.get(k);
3534      }
3535    }
3536    return clone$1(this, {
3537      values: result
3538    }, true);
3539  }
3540
3541  /**
3542   * Make this Duration shorter by the specified amount. Return a newly-constructed Duration.
3543   * @param {Duration|Object|number} duration - The amount to subtract. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject()
3544   * @return {Duration}
3545   */
3546  minus(duration) {
3547    if (!this.isValid) return this;
3548    const dur = Duration.fromDurationLike(duration);
3549    return this.plus(dur.negate());
3550  }
3551
3552  /**
3553   * Scale this Duration by the specified amount. Return a newly-constructed Duration.
3554   * @param {function} fn - The function to apply to each unit. Arity is 1 or 2: the value of the unit and, optionally, the unit name. Must return a number.
3555   * @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnits(x => x * 2) //=> { hours: 2, minutes: 60 }
3556   * @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnits((x, u) => u === "hours" ? x * 2 : x) //=> { hours: 2, minutes: 30 }
3557   * @return {Duration}
3558   */
3559  mapUnits(fn) {
3560    if (!this.isValid) return this;
3561    const result = {};
3562    for (const k of Object.keys(this.values)) {
3563      result[k] = asNumber(fn(this.values[k], k));
3564    }
3565    return clone$1(this, {
3566      values: result
3567    }, true);
3568  }
3569
3570  /**
3571   * Get the value of unit.
3572   * @param {string} unit - a unit such as 'minute' or 'day'
3573   * @example Duration.fromObject({years: 2, days: 3}).get('years') //=> 2
3574   * @example Duration.fromObject({years: 2, days: 3}).get('months') //=> 0
3575   * @example Duration.fromObject({years: 2, days: 3}).get('days') //=> 3
3576   * @return {number}
3577   */
3578  get(unit) {
3579    return this[Duration.normalizeUnit(unit)];
3580  }
3581
3582  /**
3583   * "Set" the values of specified units. Return a newly-constructed Duration.
3584   * @param {Object} values - a mapping of units to numbers
3585   * @example dur.set({ years: 2017 })
3586   * @example dur.set({ hours: 8, minutes: 30 })
3587   * @return {Duration}
3588   */
3589  set(values) {
3590    if (!this.isValid) return this;
3591    const mixed = {
3592      ...this.values,
3593      ...normalizeObject(values, Duration.normalizeUnit)
3594    };
3595    return clone$1(this, {
3596      values: mixed
3597    });
3598  }
3599
3600  /**
3601   * "Set" the locale and/or numberingSystem.  Returns a newly-constructed Duration.
3602   * @example dur.reconfigure({ locale: 'en-GB' })
3603   * @return {Duration}
3604   */
3605  reconfigure({
3606    locale,
3607    numberingSystem,
3608    conversionAccuracy,
3609    matrix
3610  } = {}) {
3611    const loc = this.loc.clone({
3612      locale,
3613      numberingSystem
3614    });
3615    const opts = {
3616      loc,
3617      matrix,
3618      conversionAccuracy
3619    };
3620    return clone$1(this, opts);
3621  }
3622
3623  /**
3624   * Return the length of the duration in the specified unit.
3625   * @param {string} unit - a unit such as 'minutes' or 'days'
3626   * @example Duration.fromObject({years: 1}).as('days') //=> 365
3627   * @example Duration.fromObject({years: 1}).as('months') //=> 12
3628   * @example Duration.fromObject({hours: 60}).as('days') //=> 2.5
3629   * @return {number}
3630   */
3631  as(unit) {
3632    return this.isValid ? this.shiftTo(unit).get(unit) : NaN;
3633  }
3634
3635  /**
3636   * Reduce this Duration to its canonical representation in its current units.
3637   * Assuming the overall value of the Duration is positive, this means:
3638   * - excessive values for lower-order units are converted to higher-order units (if possible, see first and second example)
3639   * - negative lower-order units are converted to higher order units (there must be such a higher order unit, otherwise
3640   *   the overall value would be negative, see third example)
3641   * - fractional values for higher-order units are converted to lower-order units (if possible, see fourth example)
3642   *
3643   * If the overall value is negative, the result of this method is equivalent to `this.negate().normalize().negate()`.
3644   * @example Duration.fromObject({ years: 2, days: 5000 }).normalize().toObject() //=> { years: 15, days: 255 }
3645   * @example Duration.fromObject({ days: 5000 }).normalize().toObject() //=> { days: 5000 }
3646   * @example Duration.fromObject({ hours: 12, minutes: -45 }).normalize().toObject() //=> { hours: 11, minutes: 15 }
3647   * @example Duration.fromObject({ years: 2.5, days: 0, hours: 0 }).normalize().toObject() //=> { years: 2, days: 182, hours: 12 }
3648   * @return {Duration}
3649   */
3650  normalize() {
3651    if (!this.isValid) return this;
3652    const vals = this.toObject();
3653    normalizeValues(this.matrix, vals);
3654    return clone$1(this, {
3655      values: vals
3656    }, true);
3657  }
3658
3659  /**
3660   * Rescale units to its largest representation
3661   * @example Duration.fromObject({ milliseconds: 90000 }).rescale().toObject() //=> { minutes: 1, seconds: 30 }
3662   * @return {Duration}
3663   */
3664  rescale() {
3665    if (!this.isValid) return this;
3666    const vals = removeZeroes(this.normalize().shiftToAll().toObject());
3667    return clone$1(this, {
3668      values: vals
3669    }, true);
3670  }
3671
3672  /**
3673   * Convert this Duration into its representation in a different set of units.
3674   * @example Duration.fromObject({ hours: 1, seconds: 30 }).shiftTo('minutes', 'milliseconds').toObject() //=> { minutes: 60, milliseconds: 30000 }
3675   * @return {Duration}
3676   */
3677  shiftTo(...units) {
3678    if (!this.isValid) return this;
3679    if (units.length === 0) {
3680      return this;
3681    }
3682    units = units.map(u => Duration.normalizeUnit(u));
3683    const built = {},
3684      accumulated = {},
3685      vals = this.toObject();
3686    let lastUnit;
3687    for (const k of orderedUnits$1) {
3688      if (units.indexOf(k) >= 0) {
3689        lastUnit = k;
3690        let own = 0;
3691
3692        // anything we haven't boiled down yet should get boiled to this unit
3693        for (const ak in accumulated) {
3694          own += this.matrix[ak][k] * accumulated[ak];
3695          accumulated[ak] = 0;
3696        }
3697
3698        // plus anything that's already in this unit
3699        if (isNumber(vals[k])) {
3700          own += vals[k];
3701        }
3702
3703        // only keep the integer part for now in the hopes of putting any decimal part
3704        // into a smaller unit later
3705        const i = Math.trunc(own);
3706        built[k] = i;
3707        accumulated[k] = (own * 1000 - i * 1000) / 1000;
3708
3709        // otherwise, keep it in the wings to boil it later
3710      } else if (isNumber(vals[k])) {
3711        accumulated[k] = vals[k];
3712      }
3713    }
3714
3715    // anything leftover becomes the decimal for the last unit
3716    // lastUnit must be defined since units is not empty
3717    for (const key in accumulated) {
3718      if (accumulated[key] !== 0) {
3719        built[lastUnit] += key === lastUnit ? accumulated[key] : accumulated[key] / this.matrix[lastUnit][key];
3720      }
3721    }
3722    normalizeValues(this.matrix, built);
3723    return clone$1(this, {
3724      values: built
3725    }, true);
3726  }
3727
3728  /**
3729   * Shift this Duration to all available units.
3730   * Same as shiftTo("years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds")
3731   * @return {Duration}
3732   */
3733  shiftToAll() {
3734    if (!this.isValid) return this;
3735    return this.shiftTo("years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds");
3736  }
3737
3738  /**
3739   * Return the negative of this Duration.
3740   * @example Duration.fromObject({ hours: 1, seconds: 30 }).negate().toObject() //=> { hours: -1, seconds: -30 }
3741   * @return {Duration}
3742   */
3743  negate() {
3744    if (!this.isValid) return this;
3745    const negated = {};
3746    for (const k of Object.keys(this.values)) {
3747      negated[k] = this.values[k] === 0 ? 0 : -this.values[k];
3748    }
3749    return clone$1(this, {
3750      values: negated
3751    }, true);
3752  }
3753
3754  /**
3755   * Removes all units with values equal to 0 from this Duration.
3756   * @example Duration.fromObject({ years: 2, days: 0, hours: 0, minutes: 0 }).removeZeros().toObject() //=> { years: 2 }
3757   * @return {Duration}
3758   */
3759  removeZeros() {
3760    if (!this.isValid) return this;
3761    const vals = removeZeroes(this.values);
3762    return clone$1(this, {
3763      values: vals
3764    }, true);
3765  }
3766
3767  /**
3768   * Get the years.
3769   * @type {number}
3770   */
3771  get years() {
3772    return this.isValid ? this.values.years || 0 : NaN;
3773  }
3774
3775  /**
3776   * Get the quarters.
3777   * @type {number}
3778   */
3779  get quarters() {
3780    return this.isValid ? this.values.quarters || 0 : NaN;
3781  }
3782
3783  /**
3784   * Get the months.
3785   * @type {number}
3786   */
3787  get months() {
3788    return this.isValid ? this.values.months || 0 : NaN;
3789  }
3790
3791  /**
3792   * Get the weeks
3793   * @type {number}
3794   */
3795  get weeks() {
3796    return this.isValid ? this.values.weeks || 0 : NaN;
3797  }
3798
3799  /**
3800   * Get the days.
3801   * @type {number}
3802   */
3803  get days() {
3804    return this.isValid ? this.values.days || 0 : NaN;
3805  }
3806
3807  /**
3808   * Get the hours.
3809   * @type {number}
3810   */
3811  get hours() {
3812    return this.isValid ? this.values.hours || 0 : NaN;
3813  }
3814
3815  /**
3816   * Get the minutes.
3817   * @type {number}
3818   */
3819  get minutes() {
3820    return this.isValid ? this.values.minutes || 0 : NaN;
3821  }
3822
3823  /**
3824   * Get the seconds.
3825   * @return {number}
3826   */
3827  get seconds() {
3828    return this.isValid ? this.values.seconds || 0 : NaN;
3829  }
3830
3831  /**
3832   * Get the milliseconds.
3833   * @return {number}
3834   */
3835  get milliseconds() {
3836    return this.isValid ? this.values.milliseconds || 0 : NaN;
3837  }
3838
3839  /**
3840   * Returns whether the Duration is invalid. Invalid durations are returned by diff operations
3841   * on invalid DateTimes or Intervals.
3842   * @return {boolean}
3843   */
3844  get isValid() {
3845    return this.invalid === null;
3846  }
3847
3848  /**
3849   * Returns an error code if this Duration became invalid, or null if the Duration is valid
3850   * @return {string}
3851   */
3852  get invalidReason() {
3853    return this.invalid ? this.invalid.reason : null;
3854  }
3855
3856  /**
3857   * Returns an explanation of why this Duration became invalid, or null if the Duration is valid
3858   * @type {string}
3859   */
3860  get invalidExplanation() {
3861    return this.invalid ? this.invalid.explanation : null;
3862  }
3863
3864  /**
3865   * Equality check
3866   * Two Durations are equal iff they have the same units and the same values for each unit.
3867   * @param {Duration} other
3868   * @return {boolean}
3869   */
3870  equals(other) {
3871    if (!this.isValid || !other.isValid) {
3872      return false;
3873    }
3874    if (!this.loc.equals(other.loc)) {
3875      return false;
3876    }
3877    function eq(v1, v2) {
3878      // Consider 0 and undefined as equal
3879      if (v1 === undefined || v1 === 0) return v2 === undefined || v2 === 0;
3880      return v1 === v2;
3881    }
3882    for (const u of orderedUnits$1) {
3883      if (!eq(this.values[u], other.values[u])) {
3884        return false;
3885      }
3886    }
3887    return true;
3888  }
3889}
3890
3891const INVALID$1 = "Invalid Interval";
3892
3893// checks if the start is equal to or before the end
3894function validateStartEnd(start, end) {
3895  if (!start || !start.isValid) {
3896    return Interval.invalid("missing or invalid start");
3897  } else if (!end || !end.isValid) {
3898    return Interval.invalid("missing or invalid end");
3899  } else if (end < start) {
3900    return Interval.invalid("end before start", `The end of an interval must be after its start, but you had start=${start.toISO()} and end=${end.toISO()}`);
3901  } else {
3902    return null;
3903  }
3904}
3905
3906/**
3907 * An Interval object represents a half-open interval of time, where each endpoint is a {@link DateTime}. Conceptually, it's a container for those two endpoints, accompanied by methods for creating, parsing, interrogating, comparing, transforming, and formatting them.
3908 *
3909 * Here is a brief overview of the most commonly used methods and getters in Interval:
3910 *
3911 * * **Creation** To create an Interval, use {@link Interval.fromDateTimes}, {@link Interval.after}, {@link Interval.before}, or {@link Interval.fromISO}.
3912 * * **Accessors** Use {@link Interval#start} and {@link Interval#end} to get the start and end.
3913 * * **Interrogation** To analyze the Interval, use {@link Interval#count}, {@link Interval#length}, {@link Interval#hasSame}, {@link Interval#contains}, {@link Interval#isAfter}, or {@link Interval#isBefore}.
3914 * * **Transformation** To create other Intervals out of this one, use {@link Interval#set}, {@link Interval#splitAt}, {@link Interval#splitBy}, {@link Interval#divideEqually}, {@link Interval.merge}, {@link Interval.xor}, {@link Interval#union}, {@link Interval#intersection}, or {@link Interval#difference}.
3915 * * **Comparison** To compare this Interval to another one, use {@link Interval#equals}, {@link Interval#overlaps}, {@link Interval#abutsStart}, {@link Interval#abutsEnd}, {@link Interval#engulfs}
3916 * * **Output** To convert the Interval into other representations, see {@link Interval#toString}, {@link Interval#toLocaleString}, {@link Interval#toISO}, {@link Interval#toISODate}, {@link Interval#toISOTime}, {@link Interval#toFormat}, and {@link Interval#toDuration}.
3917 */
3918class Interval {
3919  /**
3920   * @private
3921   */
3922  constructor(config) {
3923    /**
3924     * @access private
3925     */
3926    this.s = config.start;
3927    /**
3928     * @access private
3929     */
3930    this.e = config.end;
3931    /**
3932     * @access private
3933     */
3934    this.invalid = config.invalid || null;
3935    /**
3936     * @access private
3937     */
3938    this.isLuxonInterval = true;
3939  }
3940
3941  /**
3942   * Create an invalid Interval.
3943   * @param {string} reason - simple string of why this Interval is invalid. Should not contain parameters or anything else data-dependent
3944   * @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information
3945   * @return {Interval}
3946   */
3947  static invalid(reason, explanation = null) {
3948    if (!reason) {
3949      throw new InvalidArgumentError("need to specify a reason the Interval is invalid");
3950    }
3951    const invalid = reason instanceof Invalid ? reason : new Invalid(reason, explanation);
3952    if (Settings.throwOnInvalid) {
3953      throw new InvalidIntervalError(invalid);
3954    } else {
3955      return new Interval({
3956        invalid
3957      });
3958    }
3959  }
3960
3961  /**
3962   * Create an Interval from a start DateTime and an end DateTime. Inclusive of the start but not the end.
3963   * @param {DateTime|Date|Object} start
3964   * @param {DateTime|Date|Object} end
3965   * @return {Interval}
3966   */
3967  static fromDateTimes(start, end) {
3968    const builtStart = friendlyDateTime(start),
3969      builtEnd = friendlyDateTime(end);
3970    const validateError = validateStartEnd(builtStart, builtEnd);
3971    if (validateError == null) {
3972      return new Interval({
3973        start: builtStart,
3974        end: builtEnd
3975      });
3976    } else {
3977      return validateError;
3978    }
3979  }
3980
3981  /**
3982   * Create an Interval from a start DateTime and a Duration to extend to.
3983   * @param {DateTime|Date|Object} start
3984   * @param {Duration|Object|number} duration - the length of the Interval.
3985   * @return {Interval}
3986   */
3987  static after(start, duration) {
3988    const dur = Duration.fromDurationLike(duration),
3989      dt = friendlyDateTime(start);
3990    return Interval.fromDateTimes(dt, dt.plus(dur));
3991  }
3992
3993  /**
3994   * Create an Interval from an end DateTime and a Duration to extend backwards to.
3995   * @param {DateTime|Date|Object} end
3996   * @param {Duration|Object|number} duration - the length of the Interval.
3997   * @return {Interval}
3998   */
3999  static before(end, duration) {
4000    const dur = Duration.fromDurationLike(duration),
4001      dt = friendlyDateTime(end);
4002    return Interval.fromDateTimes(dt.minus(dur), dt);
4003  }
4004
4005  /**
4006   * Create an Interval from an ISO 8601 string.
4007   * Accepts `<start>/<end>`, `<start>/<duration>`, and `<duration>/<end>` formats.
4008   * @param {string} text - the ISO string to parse
4009   * @param {Object} [opts] - options to pass {@link DateTime#fromISO} and optionally {@link Duration#fromISO}
4010   * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals
4011   * @return {Interval}
4012   */
4013  static fromISO(text, opts) {
4014    const [s, e] = (text || "").split("/", 2);
4015    if (s && e) {
4016      let start, startIsValid;
4017      try {
4018        start = DateTime.fromISO(s, opts);
4019        startIsValid = start.isValid;
4020      } catch (e) {
4021        startIsValid = false;
4022      }
4023      let end, endIsValid;
4024      try {
4025        end = DateTime.fromISO(e, opts);
4026        endIsValid = end.isValid;
4027      } catch (e) {
4028        endIsValid = false;
4029      }
4030      if (startIsValid && endIsValid) {
4031        return Interval.fromDateTimes(start, end);
4032      }
4033      if (startIsValid) {
4034        const dur = Duration.fromISO(e, opts);
4035        if (dur.isValid) {
4036          return Interval.after(start, dur);
4037        }
4038      } else if (endIsValid) {
4039        const dur = Duration.fromISO(s, opts);
4040        if (dur.isValid) {
4041          return Interval.before(end, dur);
4042        }
4043      }
4044    }
4045    return Interval.invalid("unparsable", `the input "${text}" can't be parsed as ISO 8601`);
4046  }
4047
4048  /**
4049   * Check if an object is an Interval. Works across context boundaries
4050   * @param {object} o
4051   * @return {boolean}
4052   */
4053  static isInterval(o) {
4054    return o && o.isLuxonInterval || false;
4055  }
4056
4057  /**
4058   * Returns the start of the Interval
4059   * @type {DateTime}
4060   */
4061  get start() {
4062    return this.isValid ? this.s : null;
4063  }
4064
4065  /**
4066   * Returns the end of the Interval. This is the first instant which is not part of the interval
4067   * (Interval is half-open).
4068   * @type {DateTime}
4069   */
4070  get end() {
4071    return this.isValid ? this.e : null;
4072  }
4073
4074  /**
4075   * Returns the last DateTime included in the interval (since end is not part of the interval)
4076   * @type {DateTime}
4077   */
4078  get lastDateTime() {
4079    return this.isValid ? this.e ? this.e.minus(1) : null : null;
4080  }
4081
4082  /**
4083   * Returns whether this Interval's end is at least its start, meaning that the Interval isn't 'backwards'.
4084   * @type {boolean}
4085   */
4086  get isValid() {
4087    return this.invalidReason === null;
4088  }
4089
4090  /**
4091   * Returns an error code if this Interval is invalid, or null if the Interval is valid
4092   * @type {string}
4093   */
4094  get invalidReason() {
4095    return this.invalid ? this.invalid.reason : null;
4096  }
4097
4098  /**
4099   * Returns an explanation of why this Interval became invalid, or null if the Interval is valid
4100   * @type {string}
4101   */
4102  get invalidExplanation() {
4103    return this.invalid ? this.invalid.explanation : null;
4104  }
4105
4106  /**
4107   * Returns the length of the Interval in the specified unit.
4108   * @param {string} unit - the unit (such as 'hours' or 'days') to return the length in.
4109   * @return {number}
4110   */
4111  length(unit = "milliseconds") {
4112    return this.isValid ? this.toDuration(...[unit]).get(unit) : NaN;
4113  }
4114
4115  /**
4116   * Returns the count of minutes, hours, days, months, or years included in the Interval, even in part.
4117   * Unlike {@link Interval#length} this counts sections of the calendar, not periods of time, e.g. specifying 'day'
4118   * asks 'what dates are included in this interval?', not 'how many days long is this interval?'
4119   * @param {string} [unit='milliseconds'] - the unit of time to count.
4120   * @param {Object} opts - options
4121   * @param {boolean} [opts.useLocaleWeeks=false] - If true, use weeks based on the locale, i.e. use the locale-dependent start of the week; this operation will always use the locale of the start DateTime
4122   * @return {number}
4123   */
4124  count(unit = "milliseconds", opts) {
4125    if (!this.isValid) return NaN;
4126    const start = this.start.startOf(unit, opts);
4127    let end;
4128    if (opts != null && opts.useLocaleWeeks) {
4129      end = this.end.reconfigure({
4130        locale: start.locale
4131      });
4132    } else {
4133      end = this.end;
4134    }
4135    end = end.startOf(unit, opts);
4136    return Math.floor(end.diff(start, unit).get(unit)) + (end.valueOf() !== this.end.valueOf());
4137  }
4138
4139  /**
4140   * Returns whether this Interval's start and end are both in the same unit of time
4141   * @param {string} unit - the unit of time to check sameness on
4142   * @return {boolean}
4143   */
4144  hasSame(unit) {
4145    return this.isValid ? this.isEmpty() || this.e.minus(1).hasSame(this.s, unit) : false;
4146  }
4147
4148  /**
4149   * Return whether this Interval has the same start and end DateTimes.
4150   * @return {boolean}
4151   */
4152  isEmpty() {
4153    return this.s.valueOf() === this.e.valueOf();
4154  }
4155
4156  /**
4157   * Return whether this Interval's start is after the specified DateTime.
4158   * @param {DateTime} dateTime
4159   * @return {boolean}
4160   */
4161  isAfter(dateTime) {
4162    if (!this.isValid) return false;
4163    return this.s > dateTime;
4164  }
4165
4166  /**
4167   * Return whether this Interval's end is before the specified DateTime.
4168   * @param {DateTime} dateTime
4169   * @return {boolean}
4170   */
4171  isBefore(dateTime) {
4172    if (!this.isValid) return false;
4173    return this.e <= dateTime;
4174  }
4175
4176  /**
4177   * Return whether this Interval contains the specified DateTime.
4178   * @param {DateTime} dateTime
4179   * @return {boolean}
4180   */
4181  contains(dateTime) {
4182    if (!this.isValid) return false;
4183    return this.s <= dateTime && this.e > dateTime;
4184  }
4185
4186  /**
4187   * "Sets" the start and/or end dates. Returns a newly-constructed Interval.
4188   * @param {Object} values - the values to set
4189   * @param {DateTime} values.start - the starting DateTime
4190   * @param {DateTime} values.end - the ending DateTime
4191   * @return {Interval}
4192   */
4193  set({
4194    start,
4195    end
4196  } = {}) {
4197    if (!this.isValid) return this;
4198    return Interval.fromDateTimes(start || this.s, end || this.e);
4199  }
4200
4201  /**
4202   * Split this Interval at each of the specified DateTimes
4203   * @param {...DateTime} dateTimes - the unit of time to count.
4204   * @return {Array}
4205   */
4206  splitAt(...dateTimes) {
4207    if (!this.isValid) return [];
4208    const sorted = dateTimes.map(friendlyDateTime).filter(d => this.contains(d)).sort((a, b) => a.toMillis() - b.toMillis()),
4209      results = [];
4210    let {
4211        s
4212      } = this,
4213      i = 0;
4214    while (s < this.e) {
4215      const added = sorted[i] || this.e,
4216        next = +added > +this.e ? this.e : added;
4217      results.push(Interval.fromDateTimes(s, next));
4218      s = next;
4219      i += 1;
4220    }
4221    return results;
4222  }
4223
4224  /**
4225   * Split this Interval into smaller Intervals, each of the specified length.
4226   * Left over time is grouped into a smaller interval
4227   * @param {Duration|Object|number} duration - The length of each resulting interval.
4228   * @return {Array}
4229   */
4230  splitBy(duration) {
4231    const dur = Duration.fromDurationLike(duration);
4232    if (!this.isValid || !dur.isValid || dur.as("milliseconds") === 0) {
4233      return [];
4234    }
4235    let {
4236        s
4237      } = this,
4238      idx = 1,
4239      next;
4240    const results = [];
4241    while (s < this.e) {
4242      const added = this.start.plus(dur.mapUnits(x => x * idx));
4243      next = +added > +this.e ? this.e : added;
4244      results.push(Interval.fromDateTimes(s, next));
4245      s = next;
4246      idx += 1;
4247    }
4248    return results;
4249  }
4250
4251  /**
4252   * Split this Interval into the specified number of smaller intervals.
4253   * @param {number} numberOfParts - The number of Intervals to divide the Interval into.
4254   * @return {Array}
4255   */
4256  divideEqually(numberOfParts) {
4257    if (!this.isValid) return [];
4258    return this.splitBy(this.length() / numberOfParts).slice(0, numberOfParts);
4259  }
4260
4261  /**
4262   * Return whether this Interval overlaps with the specified Interval
4263   * @param {Interval} other
4264   * @return {boolean}
4265   */
4266  overlaps(other) {
4267    return this.e > other.s && this.s < other.e;
4268  }
4269
4270  /**
4271   * Return whether this Interval's end is adjacent to the specified Interval's start.
4272   * @param {Interval} other
4273   * @return {boolean}
4274   */
4275  abutsStart(other) {
4276    if (!this.isValid) return false;
4277    return +this.e === +other.s;
4278  }
4279
4280  /**
4281   * Return whether this Interval's start is adjacent to the specified Interval's end.
4282   * @param {Interval} other
4283   * @return {boolean}
4284   */
4285  abutsEnd(other) {
4286    if (!this.isValid) return false;
4287    return +other.e === +this.s;
4288  }
4289
4290  /**
4291   * Returns true if this Interval fully contains the specified Interval, specifically if the intersect (of this Interval and the other Interval) is equal to the other Interval; false otherwise.
4292   * @param {Interval} other
4293   * @return {boolean}
4294   */
4295  engulfs(other) {
4296    if (!this.isValid) return false;
4297    return this.s <= other.s && this.e >= other.e;
4298  }
4299
4300  /**
4301   * Return whether this Interval has the same start and end as the specified Interval.
4302   * @param {Interval} other
4303   * @return {boolean}
4304   */
4305  equals(other) {
4306    if (!this.isValid || !other.isValid) {
4307      return false;
4308    }
4309    return this.s.equals(other.s) && this.e.equals(other.e);
4310  }
4311
4312  /**
4313   * Return an Interval representing the intersection of this Interval and the specified Interval.
4314   * Specifically, the resulting Interval has the maximum start time and the minimum end time of the two Intervals.
4315   * Returns null if the intersection is empty, meaning, the intervals don't intersect.
4316   * @param {Interval} other
4317   * @return {Interval}
4318   */
4319  intersection(other) {
4320    if (!this.isValid) return this;
4321    const s = this.s > other.s ? this.s : other.s,
4322      e = this.e < other.e ? this.e : other.e;
4323    if (s >= e) {
4324      return null;
4325    } else {
4326      return Interval.fromDateTimes(s, e);
4327    }
4328  }
4329
4330  /**
4331   * Return an Interval representing the union of this Interval and the specified Interval.
4332   * Specifically, the resulting Interval has the minimum start time and the maximum end time of the two Intervals.
4333   * @param {Interval} other
4334   * @return {Interval}
4335   */
4336  union(other) {
4337    if (!this.isValid) return this;
4338    const s = this.s < other.s ? this.s : other.s,
4339      e = this.e > other.e ? this.e : other.e;
4340    return Interval.fromDateTimes(s, e);
4341  }
4342
4343  /**
4344   * Merge an array of Intervals into an equivalent minimal set of Intervals.
4345   * Combines overlapping and adjacent Intervals.
4346   * The resulting array will contain the Intervals in ascending order, that is, starting with the earliest Interval
4347   * and ending with the latest.
4348   *
4349   * @param {Array} intervals
4350   * @return {Array}
4351   */
4352  static merge(intervals) {
4353    const [found, final] = intervals.sort((a, b) => a.s - b.s).reduce(([sofar, current], item) => {
4354      if (!current) {
4355        return [sofar, item];
4356      } else if (current.overlaps(item) || current.abutsStart(item)) {
4357        return [sofar, current.union(item)];
4358      } else {
4359        return [sofar.concat([current]), item];
4360      }
4361    }, [[], null]);
4362    if (final) {
4363      found.push(final);
4364    }
4365    return found;
4366  }
4367
4368  /**
4369   * Return an array of Intervals representing the spans of time that only appear in one of the specified Intervals.
4370   * @param {Array} intervals
4371   * @return {Array}
4372   */
4373  static xor(intervals) {
4374    let start = null,
4375      currentCount = 0;
4376    const results = [],
4377      ends = intervals.map(i => [{
4378        time: i.s,
4379        type: "s"
4380      }, {
4381        time: i.e,
4382        type: "e"
4383      }]),
4384      flattened = Array.prototype.concat(...ends),
4385      arr = flattened.sort((a, b) => a.time - b.time);
4386    for (const i of arr) {
4387      currentCount += i.type === "s" ? 1 : -1;
4388      if (currentCount === 1) {
4389        start = i.time;
4390      } else {
4391        if (start && +start !== +i.time) {
4392          results.push(Interval.fromDateTimes(start, i.time));
4393        }
4394        start = null;
4395      }
4396    }
4397    return Interval.merge(results);
4398  }
4399
4400  /**
4401   * Return an Interval representing the span of time in this Interval that doesn't overlap with any of the specified Intervals.
4402   * @param {...Interval} intervals
4403   * @return {Array}
4404   */
4405  difference(...intervals) {
4406    return Interval.xor([this].concat(intervals)).map(i => this.intersection(i)).filter(i => i && !i.isEmpty());
4407  }
4408
4409  /**
4410   * Returns a string representation of this Interval appropriate for debugging.
4411   * @return {string}
4412   */
4413  toString() {
4414    if (!this.isValid) return INVALID$1;
4415    return `[${this.s.toISO()} – ${this.e.toISO()})`;
4416  }
4417
4418  /**
4419   * Returns a string representation of this Interval appropriate for the REPL.
4420   * @return {string}
4421   */
4422  [Symbol.for("nodejs.util.inspect.custom")]() {
4423    if (this.isValid) {
4424      return `Interval { start: ${this.s.toISO()}, end: ${this.e.toISO()} }`;
4425    } else {
4426      return `Interval { Invalid, reason: ${this.invalidReason} }`;
4427    }
4428  }
4429
4430  /**
4431   * Returns a localized string representing this Interval. Accepts the same options as the
4432   * Intl.DateTimeFormat constructor and any presets defined by Luxon, such as
4433   * {@link DateTime.DATE_FULL} or {@link DateTime.TIME_SIMPLE}. The exact behavior of this method
4434   * is browser-specific, but in general it will return an appropriate representation of the
4435   * Interval in the assigned locale. Defaults to the system's locale if no locale has been
4436   * specified.
4437   * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
4438   * @param {Object} [formatOpts=DateTime.DATE_SHORT] - Either a DateTime preset or
4439   * Intl.DateTimeFormat constructor options.
4440   * @param {Object} opts - Options to override the configuration of the start DateTime.
4441   * @example Interval.fromISO('2022-11-07T09:00Z/2022-11-08T09:00Z').toLocaleString(); //=> 11/7/2022 – 11/8/2022
4442   * @example Interval.fromISO('2022-11-07T09:00Z/2022-11-08T09:00Z').toLocaleString(DateTime.DATE_FULL); //=> November 7 – 8, 2022
4443   * @example Interval.fromISO('2022-11-07T09:00Z/2022-11-08T09:00Z').toLocaleString(DateTime.DATE_FULL, { locale: 'fr-FR' }); //=> 7–8 novembre 2022
4444   * @example Interval.fromISO('2022-11-07T17:00Z/2022-11-07T19:00Z').toLocaleString(DateTime.TIME_SIMPLE); //=> 6:00 – 8:00 PM
4445   * @example Interval.fromISO('2022-11-07T17:00Z/2022-11-07T19:00Z').toLocaleString({ weekday: 'short', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }); //=> Mon, Nov 07, 6:00 – 8:00 p
4446   * @return {string}
4447   */
4448  toLocaleString(formatOpts = DATE_SHORT, opts = {}) {
4449    return this.isValid ? Formatter.create(this.s.loc.clone(opts), formatOpts).formatInterval(this) : INVALID$1;
4450  }
4451
4452  /**
4453   * Returns an ISO 8601-compliant string representation of this Interval.
4454   * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals
4455   * @param {Object} opts - The same options as {@link DateTime#toISO}
4456   * @return {string}
4457   */
4458  toISO(opts) {
4459    if (!this.isValid) return INVALID$1;
4460    return `${this.s.toISO(opts)}/${this.e.toISO(opts)}`;
4461  }
4462
4463  /**
4464   * Returns an ISO 8601-compliant string representation of date of this Interval.
4465   * The time components are ignored.
4466   * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals
4467   * @return {string}
4468   */
4469  toISODate() {
4470    if (!this.isValid) return INVALID$1;
4471    return `${this.s.toISODate()}/${this.e.toISODate()}`;
4472  }
4473
4474  /**
4475   * Returns an ISO 8601-compliant string representation of time of this Interval.
4476   * The date components are ignored.
4477   * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals
4478   * @param {Object} opts - The same options as {@link DateTime#toISO}
4479   * @return {string}
4480   */
4481  toISOTime(opts) {
4482    if (!this.isValid) return INVALID$1;
4483    return `${this.s.toISOTime(opts)}/${this.e.toISOTime(opts)}`;
4484  }
4485
4486  /**
4487   * Returns a string representation of this Interval formatted according to the specified format
4488   * string. **You may not want this.** See {@link Interval#toLocaleString} for a more flexible
4489   * formatting tool.
4490   * @param {string} dateFormat - The format string. This string formats the start and end time.
4491   * See {@link DateTime#toFormat} for details.
4492   * @param {Object} opts - Options.
4493   * @param {string} [opts.separator =  ' – '] - A separator to place between the start and end
4494   * representations.
4495   * @return {string}
4496   */
4497  toFormat(dateFormat, {
4498    separator = " – "
4499  } = {}) {
4500    if (!this.isValid) return INVALID$1;
4501    return `${this.s.toFormat(dateFormat)}${separator}${this.e.toFormat(dateFormat)}`;
4502  }
4503
4504  /**
4505   * Return a Duration representing the time spanned by this interval.
4506   * @param {string|string[]} [unit=['milliseconds']] - the unit or units (such as 'hours' or 'days') to include in the duration.
4507   * @param {Object} opts - options that affect the creation of the Duration
4508   * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use
4509   * @example Interval.fromDateTimes(dt1, dt2).toDuration().toObject() //=> { milliseconds: 88489257 }
4510   * @example Interval.fromDateTimes(dt1, dt2).toDuration('days').toObject() //=> { days: 1.0241812152777778 }
4511   * @example Interval.fromDateTimes(dt1, dt2).toDuration(['hours', 'minutes']).toObject() //=> { hours: 24, minutes: 34.82095 }
4512   * @example Interval.fromDateTimes(dt1, dt2).toDuration(['hours', 'minutes', 'seconds']).toObject() //=> { hours: 24, minutes: 34, seconds: 49.257 }
4513   * @example Interval.fromDateTimes(dt1, dt2).toDuration('seconds').toObject() //=> { seconds: 88489.257 }
4514   * @return {Duration}
4515   */
4516  toDuration(unit, opts) {
4517    if (!this.isValid) {
4518      return Duration.invalid(this.invalidReason);
4519    }
4520    return this.e.diff(this.s, unit, opts);
4521  }
4522
4523  /**
4524   * Run mapFn on the interval start and end, returning a new Interval from the resulting DateTimes
4525   * @param {function} mapFn
4526   * @return {Interval}
4527   * @example Interval.fromDateTimes(dt1, dt2).mapEndpoints(endpoint => endpoint.toUTC())
4528   * @example Interval.fromDateTimes(dt1, dt2).mapEndpoints(endpoint => endpoint.plus({ hours: 2 }))
4529   */
4530  mapEndpoints(mapFn) {
4531    return Interval.fromDateTimes(mapFn(this.s), mapFn(this.e));
4532  }
4533}
4534
4535/**
4536 * The Info class contains static methods for retrieving general time and date related data. For example, it has methods for finding out if a time zone has a DST, for listing the months in any supported locale, and for discovering which of Luxon features are available in the current environment.
4537 */
4538class Info {
4539  /**
4540   * Return whether the specified zone contains a DST.
4541   * @param {string|Zone} [zone='local'] - Zone to check. Defaults to the environment's local zone.
4542   * @return {boolean}
4543   */
4544  static hasDST(zone = Settings.defaultZone) {
4545    const proto = DateTime.now().setZone(zone).set({
4546      month: 12
4547    });
4548    return !zone.isUniversal && proto.offset !== proto.set({
4549      month: 6
4550    }).offset;
4551  }
4552
4553  /**
4554   * Return whether the specified zone is a valid IANA specifier.
4555   * @param {string} zone - Zone to check
4556   * @return {boolean}
4557   */
4558  static isValidIANAZone(zone) {
4559    return IANAZone.isValidZone(zone);
4560  }
4561
4562  /**
4563   * Converts the input into a {@link Zone} instance.
4564   *
4565   * * If `input` is already a Zone instance, it is returned unchanged.
4566   * * If `input` is a string containing a valid time zone name, a Zone instance
4567   *   with that name is returned.
4568   * * If `input` is a string that doesn't refer to a known time zone, a Zone
4569   *   instance with {@link Zone#isValid} == false is returned.
4570   * * If `input is a number, a Zone instance with the specified fixed offset
4571   *   in minutes is returned.
4572   * * If `input` is `null` or `undefined`, the default zone is returned.
4573   * @param {string|Zone|number} [input] - the value to be converted
4574   * @return {Zone}
4575   */
4576  static normalizeZone(input) {
4577    return normalizeZone(input, Settings.defaultZone);
4578  }
4579
4580  /**
4581   * Get the weekday on which the week starts according to the given locale.
4582   * @param {Object} opts - options
4583   * @param {string} [opts.locale] - the locale code
4584   * @param {string} [opts.locObj=null] - an existing locale object to use
4585   * @returns {number} the start of the week, 1 for Monday through 7 for Sunday
4586   */
4587  static getStartOfWeek({
4588    locale = null,
4589    locObj = null
4590  } = {}) {
4591    return (locObj || Locale.create(locale)).getStartOfWeek();
4592  }
4593
4594  /**
4595   * Get the minimum number of days necessary in a week before it is considered part of the next year according
4596   * to the given locale.
4597   * @param {Object} opts - options
4598   * @param {string} [opts.locale] - the locale code
4599   * @param {string} [opts.locObj=null] - an existing locale object to use
4600   * @returns {number}
4601   */
4602  static getMinimumDaysInFirstWeek({
4603    locale = null,
4604    locObj = null
4605  } = {}) {
4606    return (locObj || Locale.create(locale)).getMinDaysInFirstWeek();
4607  }
4608
4609  /**
4610   * Get the weekdays, which are considered the weekend according to the given locale
4611   * @param {Object} opts - options
4612   * @param {string} [opts.locale] - the locale code
4613   * @param {string} [opts.locObj=null] - an existing locale object to use
4614   * @returns {number[]} an array of weekdays, 1 for Monday through 7 for Sunday
4615   */
4616  static getWeekendWeekdays({
4617    locale = null,
4618    locObj = null
4619  } = {}) {
4620    // copy the array, because we cache it internally
4621    return (locObj || Locale.create(locale)).getWeekendDays().slice();
4622  }
4623
4624  /**
4625   * Return an array of standalone month names.
4626   * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
4627   * @param {string} [length='long'] - the length of the month representation, such as "numeric", "2-digit", "narrow", "short", "long"
4628   * @param {Object} opts - options
4629   * @param {string} [opts.locale] - the locale code
4630   * @param {string} [opts.numberingSystem=null] - the numbering system
4631   * @param {string} [opts.locObj=null] - an existing locale object to use
4632   * @param {string} [opts.outputCalendar='gregory'] - the calendar
4633   * @example Info.months()[0] //=> 'January'
4634   * @example Info.months('short')[0] //=> 'Jan'
4635   * @example Info.months('numeric')[0] //=> '1'
4636   * @example Info.months('short', { locale: 'fr-CA' } )[0] //=> 'janv.'
4637   * @example Info.months('numeric', { locale: 'ar' })[0] //=> 'Ù¡'
4638   * @example Info.months('long', { outputCalendar: 'islamic' })[0] //=> 'RabiÊ» I'
4639   * @return {Array}
4640   */
4641  static months(length = "long", {
4642    locale = null,
4643    numberingSystem = null,
4644    locObj = null,
4645    outputCalendar = "gregory"
4646  } = {}) {
4647    return (locObj || Locale.create(locale, numberingSystem, outputCalendar)).months(length);
4648  }
4649
4650  /**
4651   * Return an array of format month names.
4652   * Format months differ from standalone months in that they're meant to appear next to the day of the month. In some languages, that
4653   * changes the string.
4654   * See {@link Info#months}
4655   * @param {string} [length='long'] - the length of the month representation, such as "numeric", "2-digit", "narrow", "short", "long"
4656   * @param {Object} opts - options
4657   * @param {string} [opts.locale] - the locale code
4658   * @param {string} [opts.numberingSystem=null] - the numbering system
4659   * @param {string} [opts.locObj=null] - an existing locale object to use
4660   * @param {string} [opts.outputCalendar='gregory'] - the calendar
4661   * @return {Array}
4662   */
4663  static monthsFormat(length = "long", {
4664    locale = null,
4665    numberingSystem = null,
4666    locObj = null,
4667    outputCalendar = "gregory"
4668  } = {}) {
4669    return (locObj || Locale.create(locale, numberingSystem, outputCalendar)).months(length, true);
4670  }
4671
4672  /**
4673   * Return an array of standalone week names.
4674   * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
4675   * @param {string} [length='long'] - the length of the weekday representation, such as "narrow", "short", "long".
4676   * @param {Object} opts - options
4677   * @param {string} [opts.locale] - the locale code
4678   * @param {string} [opts.numberingSystem=null] - the numbering system
4679   * @param {string} [opts.locObj=null] - an existing locale object to use
4680   * @example Info.weekdays()[0] //=> 'Monday'
4681   * @example Info.weekdays('short')[0] //=> 'Mon'
4682   * @example Info.weekdays('short', { locale: 'fr-CA' })[0] //=> 'lun.'
4683   * @example Info.weekdays('short', { locale: 'ar' })[0] //=> 'الاثنين'
4684   * @return {Array}
4685   */
4686  static weekdays(length = "long", {
4687    locale = null,
4688    numberingSystem = null,
4689    locObj = null
4690  } = {}) {
4691    return (locObj || Locale.create(locale, numberingSystem, null)).weekdays(length);
4692  }
4693
4694  /**
4695   * Return an array of format week names.
4696   * Format weekdays differ from standalone weekdays in that they're meant to appear next to more date information. In some languages, that
4697   * changes the string.
4698   * See {@link Info#weekdays}
4699   * @param {string} [length='long'] - the length of the month representation, such as "narrow", "short", "long".
4700   * @param {Object} opts - options
4701   * @param {string} [opts.locale=null] - the locale code
4702   * @param {string} [opts.numberingSystem=null] - the numbering system
4703   * @param {string} [opts.locObj=null] - an existing locale object to use
4704   * @return {Array}
4705   */
4706  static weekdaysFormat(length = "long", {
4707    locale = null,
4708    numberingSystem = null,
4709    locObj = null
4710  } = {}) {
4711    return (locObj || Locale.create(locale, numberingSystem, null)).weekdays(length, true);
4712  }
4713
4714  /**
4715   * Return an array of meridiems.
4716   * @param {Object} opts - options
4717   * @param {string} [opts.locale] - the locale code
4718   * @example Info.meridiems() //=> [ 'AM', 'PM' ]
4719   * @example Info.meridiems({ locale: 'my' }) //=> [ 'နံနက်', 'ညနေ' ]
4720   * @return {Array}
4721   */
4722  static meridiems({
4723    locale = null
4724  } = {}) {
4725    return Locale.create(locale).meridiems();
4726  }
4727
4728  /**
4729   * Return an array of eras, such as ['BC', 'AD']. The locale can be specified, but the calendar system is always Gregorian.
4730   * @param {string} [length='short'] - the length of the era representation, such as "short" or "long".
4731   * @param {Object} opts - options
4732   * @param {string} [opts.locale] - the locale code
4733   * @example Info.eras() //=> [ 'BC', 'AD' ]
4734   * @example Info.eras('long') //=> [ 'Before Christ', 'Anno Domini' ]
4735   * @example Info.eras('long', { locale: 'fr' }) //=> [ 'avant Jésus-Christ', 'après Jésus-Christ' ]
4736   * @return {Array}
4737   */
4738  static eras(length = "short", {
4739    locale = null
4740  } = {}) {
4741    return Locale.create(locale, null, "gregory").eras(length);
4742  }
4743
4744  /**
4745   * Return the set of available features in this environment.
4746   * Some features of Luxon are not available in all environments. For example, on older browsers, relative time formatting support is not available. Use this function to figure out if that's the case.
4747   * Keys:
4748   * * `relative`: whether this environment supports relative time formatting
4749   * * `localeWeek`: whether this environment supports different weekdays for the start of the week based on the locale
4750   * @example Info.features() //=> { relative: false, localeWeek: true }
4751   * @return {Object}
4752   */
4753  static features() {
4754    return {
4755      relative: hasRelative(),
4756      localeWeek: hasLocaleWeekInfo()
4757    };
4758  }
4759}
4760
4761function dayDiff(earlier, later) {
4762  const utcDayStart = dt => dt.toUTC(0, {
4763      keepLocalTime: true
4764    }).startOf("day").valueOf(),
4765    ms = utcDayStart(later) - utcDayStart(earlier);
4766  return Math.floor(Duration.fromMillis(ms).as("days"));
4767}
4768function highOrderDiffs(cursor, later, units) {
4769  const differs = [["years", (a, b) => b.year - a.year], ["quarters", (a, b) => b.quarter - a.quarter + (b.year - a.year) * 4], ["months", (a, b) => b.month - a.month + (b.year - a.year) * 12], ["weeks", (a, b) => {
4770    const days = dayDiff(a, b);
4771    return (days - days % 7) / 7;
4772  }], ["days", dayDiff]];
4773  const results = {};
4774  const earlier = cursor;
4775  let lowestOrder, highWater;
4776
4777  /* This loop tries to diff using larger units first.
4778     If we overshoot, we backtrack and try the next smaller unit.
4779     "cursor" starts out at the earlier timestamp and moves closer and closer to "later"
4780     as we use smaller and smaller units.
4781     highWater keeps track of where we would be if we added one more of the smallest unit,
4782     this is used later to potentially convert any difference smaller than the smallest higher order unit
4783     into a fraction of that smallest higher order unit
4784  */
4785  for (const [unit, differ] of differs) {
4786    if (units.indexOf(unit) >= 0) {
4787      lowestOrder = unit;
4788      results[unit] = differ(cursor, later);
4789      highWater = earlier.plus(results);
4790      if (highWater > later) {
4791        // we overshot the end point, backtrack cursor by 1
4792        results[unit]--;
4793        cursor = earlier.plus(results);
4794
4795        // if we are still overshooting now, we need to backtrack again
4796        // this happens in certain situations when diffing times in different zones,
4797        // because this calculation ignores time zones
4798        if (cursor > later) {
4799          // keep the "overshot by 1" around as highWater
4800          highWater = cursor;
4801          // backtrack cursor by 1
4802          results[unit]--;
4803          cursor = earlier.plus(results);
4804        }
4805      } else {
4806        cursor = highWater;
4807      }
4808    }
4809  }
4810  return [cursor, results, highWater, lowestOrder];
4811}
4812function diff (earlier, later, units, opts) {
4813  let [cursor, results, highWater, lowestOrder] = highOrderDiffs(earlier, later, units);
4814  const remainingMillis = later - cursor;
4815  const lowerOrderUnits = units.filter(u => ["hours", "minutes", "seconds", "milliseconds"].indexOf(u) >= 0);
4816  if (lowerOrderUnits.length === 0) {
4817    if (highWater < later) {
4818      highWater = cursor.plus({
4819        [lowestOrder]: 1
4820      });
4821    }
4822    if (highWater !== cursor) {
4823      results[lowestOrder] = (results[lowestOrder] || 0) + remainingMillis / (highWater - cursor);
4824    }
4825  }
4826  const duration = Duration.fromObject(results, opts);
4827  if (lowerOrderUnits.length > 0) {
4828    return Duration.fromMillis(remainingMillis, opts).shiftTo(...lowerOrderUnits).plus(duration);
4829  } else {
4830    return duration;
4831  }
4832}
4833
4834const MISSING_FTP = "missing Intl.DateTimeFormat.formatToParts support";
4835function intUnit(regex, post = i => i) {
4836  return {
4837    regex,
4838    deser: ([s]) => post(parseDigits(s))
4839  };
4840}
4841const NBSP = String.fromCharCode(160);
4842const spaceOrNBSP = `[ ${NBSP}]`;
4843const spaceOrNBSPRegExp = new RegExp(spaceOrNBSP, "g");
4844function fixListRegex(s) {
4845  // make dots optional and also make them literal
4846  // make space and non breakable space characters interchangeable
4847  return s.replace(/\./g, "\\.?").replace(spaceOrNBSPRegExp, spaceOrNBSP);
4848}
4849function stripInsensitivities(s) {
4850  return s.replace(/\./g, "") // ignore dots that were made optional
4851  .replace(spaceOrNBSPRegExp, " ") // interchange space and nbsp
4852  .toLowerCase();
4853}
4854function oneOf(strings, startIndex) {
4855  if (strings === null) {
4856    return null;
4857  } else {
4858    return {
4859      regex: RegExp(strings.map(fixListRegex).join("|")),
4860      deser: ([s]) => strings.findIndex(i => stripInsensitivities(s) === stripInsensitivities(i)) + startIndex
4861    };
4862  }
4863}
4864function offset(regex, groups) {
4865  return {
4866    regex,
4867    deser: ([, h, m]) => signedOffset(h, m),
4868    groups
4869  };
4870}
4871function simple(regex) {
4872  return {
4873    regex,
4874    deser: ([s]) => s
4875  };
4876}
4877function escapeToken(value) {
4878  return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
4879}
4880
4881/**
4882 * @param token
4883 * @param {Locale} loc
4884 */
4885function unitForToken(token, loc) {
4886  const one = digitRegex(loc),
4887    two = digitRegex(loc, "{2}"),
4888    three = digitRegex(loc, "{3}"),
4889    four = digitRegex(loc, "{4}"),
4890    six = digitRegex(loc, "{6}"),
4891    oneOrTwo = digitRegex(loc, "{1,2}"),
4892    oneToThree = digitRegex(loc, "{1,3}"),
4893    oneToSix = digitRegex(loc, "{1,6}"),
4894    oneToNine = digitRegex(loc, "{1,9}"),
4895    twoToFour = digitRegex(loc, "{2,4}"),
4896    fourToSix = digitRegex(loc, "{4,6}"),
4897    literal = t => ({
4898      regex: RegExp(escapeToken(t.val)),
4899      deser: ([s]) => s,
4900      literal: true
4901    }),
4902    unitate = t => {
4903      if (token.literal) {
4904        return literal(t);
4905      }
4906      switch (t.val) {
4907        // era
4908        case "G":
4909          return oneOf(loc.eras("short"), 0);
4910        case "GG":
4911          return oneOf(loc.eras("long"), 0);
4912        // years
4913        case "y":
4914          return intUnit(oneToSix);
4915        case "yy":
4916          return intUnit(twoToFour, untruncateYear);
4917        case "yyyy":
4918          return intUnit(four);
4919        case "yyyyy":
4920          return intUnit(fourToSix);
4921        case "yyyyyy":
4922          return intUnit(six);
4923        // months
4924        case "M":
4925          return intUnit(oneOrTwo);
4926        case "MM":
4927          return intUnit(two);
4928        case "MMM":
4929          return oneOf(loc.months("short", true), 1);
4930        case "MMMM":
4931          return oneOf(loc.months("long", true), 1);
4932        case "L":
4933          return intUnit(oneOrTwo);
4934        case "LL":
4935          return intUnit(two);
4936        case "LLL":
4937          return oneOf(loc.months("short", false), 1);
4938        case "LLLL":
4939          return oneOf(loc.months("long", false), 1);
4940        // dates
4941        case "d":
4942          return intUnit(oneOrTwo);
4943        case "dd":
4944          return intUnit(two);
4945        // ordinals
4946        case "o":
4947          return intUnit(oneToThree);
4948        case "ooo":
4949          return intUnit(three);
4950        // time
4951        case "HH":
4952          return intUnit(two);
4953        case "H":
4954          return intUnit(oneOrTwo);
4955        case "hh":
4956          return intUnit(two);
4957        case "h":
4958          return intUnit(oneOrTwo);
4959        case "mm":
4960          return intUnit(two);
4961        case "m":
4962          return intUnit(oneOrTwo);
4963        case "q":
4964          return intUnit(oneOrTwo);
4965        case "qq":
4966          return intUnit(two);
4967        case "s":
4968          return intUnit(oneOrTwo);
4969        case "ss":
4970          return intUnit(two);
4971        case "S":
4972          return intUnit(oneToThree);
4973        case "SSS":
4974          return intUnit(three);
4975        case "u":
4976          return simple(oneToNine);
4977        case "uu":
4978          return simple(oneOrTwo);
4979        case "uuu":
4980          return intUnit(one);
4981        // meridiem
4982        case "a":
4983          return oneOf(loc.meridiems(), 0);
4984        // weekYear (k)
4985        case "kkkk":
4986          return intUnit(four);
4987        case "kk":
4988          return intUnit(twoToFour, untruncateYear);
4989        // weekNumber (W)
4990        case "W":
4991          return intUnit(oneOrTwo);
4992        case "WW":
4993          return intUnit(two);
4994        // weekdays
4995        case "E":
4996        case "c":
4997          return intUnit(one);
4998        case "EEE":
4999          return oneOf(loc.weekdays("short", false), 1);
5000        case "EEEE":
5001          return oneOf(loc.weekdays("long", false), 1);
5002        case "ccc":
5003          return oneOf(loc.weekdays("short", true), 1);
5004        case "cccc":
5005          return oneOf(loc.weekdays("long", true), 1);
5006        // offset/zone
5007        case "Z":
5008        case "ZZ":
5009          return offset(new RegExp(`([+-]${oneOrTwo.source})(?::(${two.source}))?`), 2);
5010        case "ZZZ":
5011          return offset(new RegExp(`([+-]${oneOrTwo.source})(${two.source})?`), 2);
5012        // we don't support ZZZZ (PST) or ZZZZZ (Pacific Standard Time) in parsing
5013        // because we don't have any way to figure out what they are
5014        case "z":
5015          return simple(/[a-z_+-/]{1,256}?/i);
5016        // this special-case "token" represents a place where a macro-token expanded into a white-space literal
5017        // in this case we accept any non-newline white-space
5018        case " ":
5019          return simple(/[^\S\n\r]/);
5020        default:
5021          return literal(t);
5022      }
5023    };
5024  const unit = unitate(token) || {
5025    invalidReason: MISSING_FTP
5026  };
5027  unit.token = token;
5028  return unit;
5029}
5030const partTypeStyleToTokenVal = {
5031  year: {
5032    "2-digit": "yy",
5033    numeric: "yyyyy"
5034  },
5035  month: {
5036    numeric: "M",
5037    "2-digit": "MM",
5038    short: "MMM",
5039    long: "MMMM"
5040  },
5041  day: {
5042    numeric: "d",
5043    "2-digit": "dd"
5044  },
5045  weekday: {
5046    short: "EEE",
5047    long: "EEEE"
5048  },
5049  dayperiod: "a",
5050  dayPeriod: "a",
5051  hour12: {
5052    numeric: "h",
5053    "2-digit": "hh"
5054  },
5055  hour24: {
5056    numeric: "H",
5057    "2-digit": "HH"
5058  },
5059  minute: {
5060    numeric: "m",
5061    "2-digit": "mm"
5062  },
5063  second: {
5064    numeric: "s",
5065    "2-digit": "ss"
5066  },
5067  timeZoneName: {
5068    long: "ZZZZZ",
5069    short: "ZZZ"
5070  }
5071};
5072function tokenForPart(part, formatOpts, resolvedOpts) {
5073  const {
5074    type,
5075    value
5076  } = part;
5077  if (type === "literal") {
5078    const isSpace = /^\s+$/.test(value);
5079    return {
5080      literal: !isSpace,
5081      val: isSpace ? " " : value
5082    };
5083  }
5084  const style = formatOpts[type];
5085
5086  // The user might have explicitly specified hour12 or hourCycle
5087  // if so, respect their decision
5088  // if not, refer back to the resolvedOpts, which are based on the locale
5089  let actualType = type;
5090  if (type === "hour") {
5091    if (formatOpts.hour12 != null) {
5092      actualType = formatOpts.hour12 ? "hour12" : "hour24";
5093    } else if (formatOpts.hourCycle != null) {
5094      if (formatOpts.hourCycle === "h11" || formatOpts.hourCycle === "h12") {
5095        actualType = "hour12";
5096      } else {
5097        actualType = "hour24";
5098      }
5099    } else {
5100      // tokens only differentiate between 24 hours or not,
5101      // so we do not need to check hourCycle here, which is less supported anyways
5102      actualType = resolvedOpts.hour12 ? "hour12" : "hour24";
5103    }
5104  }
5105  let val = partTypeStyleToTokenVal[actualType];
5106  if (typeof val === "object") {
5107    val = val[style];
5108  }
5109  if (val) {
5110    return {
5111      literal: false,
5112      val
5113    };
5114  }
5115  return undefined;
5116}
5117function buildRegex(units) {
5118  const re = units.map(u => u.regex).reduce((f, r) => `${f}(${r.source})`, "");
5119  return [`^${re}$`, units];
5120}
5121function match(input, regex, handlers) {
5122  const matches = input.match(regex);
5123  if (matches) {
5124    const all = {};
5125    let matchIndex = 1;
5126    for (const i in handlers) {
5127      if (hasOwnProperty(handlers, i)) {
5128        const h = handlers[i],
5129          groups = h.groups ? h.groups + 1 : 1;
5130        if (!h.literal && h.token) {
5131          all[h.token.val[0]] = h.deser(matches.slice(matchIndex, matchIndex + groups));
5132        }
5133        matchIndex += groups;
5134      }
5135    }
5136    return [matches, all];
5137  } else {
5138    return [matches, {}];
5139  }
5140}
5141function dateTimeFromMatches(matches) {
5142  const toField = token => {
5143    switch (token) {
5144      case "S":
5145        return "millisecond";
5146      case "s":
5147        return "second";
5148      case "m":
5149        return "minute";
5150      case "h":
5151      case "H":
5152        return "hour";
5153      case "d":
5154        return "day";
5155      case "o":
5156        return "ordinal";
5157      case "L":
5158      case "M":
5159        return "month";
5160      case "y":
5161        return "year";
5162      case "E":
5163      case "c":
5164        return "weekday";
5165      case "W":
5166        return "weekNumber";
5167      case "k":
5168        return "weekYear";
5169      case "q":
5170        return "quarter";
5171      default:
5172        return null;
5173    }
5174  };
5175  let zone = null;
5176  let specificOffset;
5177  if (!isUndefined(matches.z)) {
5178    zone = IANAZone.create(matches.z);
5179  }
5180  if (!isUndefined(matches.Z)) {
5181    if (!zone) {
5182      zone = new FixedOffsetZone(matches.Z);
5183    }
5184    specificOffset = matches.Z;
5185  }
5186  if (!isUndefined(matches.q)) {
5187    matches.M = (matches.q - 1) * 3 + 1;
5188  }
5189  if (!isUndefined(matches.h)) {
5190    if (matches.h < 12 && matches.a === 1) {
5191      matches.h += 12;
5192    } else if (matches.h === 12 && matches.a === 0) {
5193      matches.h = 0;
5194    }
5195  }
5196  if (matches.G === 0 && matches.y) {
5197    matches.y = -matches.y;
5198  }
5199  if (!isUndefined(matches.u)) {
5200    matches.S = parseMillis(matches.u);
5201  }
5202  const vals = Object.keys(matches).reduce((r, k) => {
5203    const f = toField(k);
5204    if (f) {
5205      r[f] = matches[k];
5206    }
5207    return r;
5208  }, {});
5209  return [vals, zone, specificOffset];
5210}
5211let dummyDateTimeCache = null;
5212function getDummyDateTime() {
5213  if (!dummyDateTimeCache) {
5214    dummyDateTimeCache = DateTime.fromMillis(1555555555555);
5215  }
5216  return dummyDateTimeCache;
5217}
5218function maybeExpandMacroToken(token, locale) {
5219  if (token.literal) {
5220    return token;
5221  }
5222  const formatOpts = Formatter.macroTokenToFormatOpts(token.val);
5223  const tokens = formatOptsToTokens(formatOpts, locale);
5224  if (tokens == null || tokens.includes(undefined)) {
5225    return token;
5226  }
5227  return tokens;
5228}
5229function expandMacroTokens(tokens, locale) {
5230  return Array.prototype.concat(...tokens.map(t => maybeExpandMacroToken(t, locale)));
5231}
5232
5233/**
5234 * @private
5235 */
5236
5237class TokenParser {
5238  constructor(locale, format) {
5239    this.locale = locale;
5240    this.format = format;
5241    this.tokens = expandMacroTokens(Formatter.parseFormat(format), locale);
5242    this.units = this.tokens.map(t => unitForToken(t, locale));
5243    this.disqualifyingUnit = this.units.find(t => t.invalidReason);
5244    if (!this.disqualifyingUnit) {
5245      const [regexString, handlers] = buildRegex(this.units);
5246      this.regex = RegExp(regexString, "i");
5247      this.handlers = handlers;
5248    }
5249  }
5250  explainFromTokens(input) {
5251    if (!this.isValid) {
5252      return {
5253        input,
5254        tokens: this.tokens,
5255        invalidReason: this.invalidReason
5256      };
5257    } else {
5258      const [rawMatches, matches] = match(input, this.regex, this.handlers),
5259        [result, zone, specificOffset] = matches ? dateTimeFromMatches(matches) : [null, null, undefined];
5260      if (hasOwnProperty(matches, "a") && hasOwnProperty(matches, "H")) {
5261        throw new ConflictingSpecificationError("Can't include meridiem when specifying 24-hour format");
5262      }
5263      return {
5264        input,
5265        tokens: this.tokens,
5266        regex: this.regex,
5267        rawMatches,
5268        matches,
5269        result,
5270        zone,
5271        specificOffset
5272      };
5273    }
5274  }
5275  get isValid() {
5276    return !this.disqualifyingUnit;
5277  }
5278  get invalidReason() {
5279    return this.disqualifyingUnit ? this.disqualifyingUnit.invalidReason : null;
5280  }
5281}
5282function explainFromTokens(locale, input, format) {
5283  const parser = new TokenParser(locale, format);
5284  return parser.explainFromTokens(input);
5285}
5286function parseFromTokens(locale, input, format) {
5287  const {
5288    result,
5289    zone,
5290    specificOffset,
5291    invalidReason
5292  } = explainFromTokens(locale, input, format);
5293  return [result, zone, specificOffset, invalidReason];
5294}
5295function formatOptsToTokens(formatOpts, locale) {
5296  if (!formatOpts) {
5297    return null;
5298  }
5299  const formatter = Formatter.create(locale, formatOpts);
5300  const df = formatter.dtFormatter(getDummyDateTime());
5301  const parts = df.formatToParts();
5302  const resolvedOpts = df.resolvedOptions();
5303  return parts.map(p => tokenForPart(p, formatOpts, resolvedOpts));
5304}
5305
5306const INVALID = "Invalid DateTime";
5307const MAX_DATE = 8.64e15;
5308function unsupportedZone(zone) {
5309  return new Invalid("unsupported zone", `the zone "${zone.name}" is not supported`);
5310}
5311
5312// we cache week data on the DT object and this intermediates the cache
5313/**
5314 * @param {DateTime} dt
5315 */
5316function possiblyCachedWeekData(dt) {
5317  if (dt.weekData === null) {
5318    dt.weekData = gregorianToWeek(dt.c);
5319  }
5320  return dt.weekData;
5321}
5322
5323/**
5324 * @param {DateTime} dt
5325 */
5326function possiblyCachedLocalWeekData(dt) {
5327  if (dt.localWeekData === null) {
5328    dt.localWeekData = gregorianToWeek(dt.c, dt.loc.getMinDaysInFirstWeek(), dt.loc.getStartOfWeek());
5329  }
5330  return dt.localWeekData;
5331}
5332
5333// clone really means, "make a new object with these modifications". all "setters" really use this
5334// to create a new object while only changing some of the properties
5335function clone(inst, alts) {
5336  const current = {
5337    ts: inst.ts,
5338    zone: inst.zone,
5339    c: inst.c,
5340    o: inst.o,
5341    loc: inst.loc,
5342    invalid: inst.invalid
5343  };
5344  return new DateTime({
5345    ...current,
5346    ...alts,
5347    old: current
5348  });
5349}
5350
5351// find the right offset a given local time. The o input is our guess, which determines which
5352// offset we'll pick in ambiguous cases (e.g. there are two 3 AMs b/c Fallback DST)
5353function fixOffset(localTS, o, tz) {
5354  // Our UTC time is just a guess because our offset is just a guess
5355  let utcGuess = localTS - o * 60 * 1000;
5356
5357  // Test whether the zone matches the offset for this ts
5358  const o2 = tz.offset(utcGuess);
5359
5360  // If so, offset didn't change and we're done
5361  if (o === o2) {
5362    return [utcGuess, o];
5363  }
5364
5365  // If not, change the ts by the difference in the offset
5366  utcGuess -= (o2 - o) * 60 * 1000;
5367
5368  // If that gives us the local time we want, we're done
5369  const o3 = tz.offset(utcGuess);
5370  if (o2 === o3) {
5371    return [utcGuess, o2];
5372  }
5373
5374  // If it's different, we're in a hole time. The offset has changed, but the we don't adjust the time
5375  return [localTS - Math.min(o2, o3) * 60 * 1000, Math.max(o2, o3)];
5376}
5377
5378// convert an epoch timestamp into a calendar object with the given offset
5379function tsToObj(ts, offset) {
5380  ts += offset * 60 * 1000;
5381  const d = new Date(ts);
5382  return {
5383    year: d.getUTCFullYear(),
5384    month: d.getUTCMonth() + 1,
5385    day: d.getUTCDate(),
5386    hour: d.getUTCHours(),
5387    minute: d.getUTCMinutes(),
5388    second: d.getUTCSeconds(),
5389    millisecond: d.getUTCMilliseconds()
5390  };
5391}
5392
5393// convert a calendar object to a epoch timestamp
5394function objToTS(obj, offset, zone) {
5395  return fixOffset(objToLocalTS(obj), offset, zone);
5396}
5397
5398// create a new DT instance by adding a duration, adjusting for DSTs
5399function adjustTime(inst, dur) {
5400  const oPre = inst.o,
5401    year = inst.c.year + Math.trunc(dur.years),
5402    month = inst.c.month + Math.trunc(dur.months) + Math.trunc(dur.quarters) * 3,
5403    c = {
5404      ...inst.c,
5405      year,
5406      month,
5407      day: Math.min(inst.c.day, daysInMonth(year, month)) + Math.trunc(dur.days) + Math.trunc(dur.weeks) * 7
5408    },
5409    millisToAdd = Duration.fromObject({
5410      years: dur.years - Math.trunc(dur.years),
5411      quarters: dur.quarters - Math.trunc(dur.quarters),
5412      months: dur.months - Math.trunc(dur.months),
5413      weeks: dur.weeks - Math.trunc(dur.weeks),
5414      days: dur.days - Math.trunc(dur.days),
5415      hours: dur.hours,
5416      minutes: dur.minutes,
5417      seconds: dur.seconds,
5418      milliseconds: dur.milliseconds
5419    }).as("milliseconds"),
5420    localTS = objToLocalTS(c);
5421  let [ts, o] = fixOffset(localTS, oPre, inst.zone);
5422  if (millisToAdd !== 0) {
5423    ts += millisToAdd;
5424    // that could have changed the offset by going over a DST, but we want to keep the ts the same
5425    o = inst.zone.offset(ts);
5426  }
5427  return {
5428    ts,
5429    o
5430  };
5431}
5432
5433// helper useful in turning the results of parsing into real dates
5434// by handling the zone options
5435function parseDataToDateTime(parsed, parsedZone, opts, format, text, specificOffset) {
5436  const {
5437    setZone,
5438    zone
5439  } = opts;
5440  if (parsed && Object.keys(parsed).length !== 0 || parsedZone) {
5441    const interpretationZone = parsedZone || zone,
5442      inst = DateTime.fromObject(parsed, {
5443        ...opts,
5444        zone: interpretationZone,
5445        specificOffset
5446      });
5447    return setZone ? inst : inst.setZone(zone);
5448  } else {
5449    return DateTime.invalid(new Invalid("unparsable", `the input "${text}" can't be parsed as ${format}`));
5450  }
5451}
5452
5453// if you want to output a technical format (e.g. RFC 2822), this helper
5454// helps handle the details
5455function toTechFormat(dt, format, allowZ = true) {
5456  return dt.isValid ? Formatter.create(Locale.create("en-US"), {
5457    allowZ,
5458    forceSimple: true
5459  }).formatDateTimeFromString(dt, format) : null;
5460}
5461function toISODate(o, extended, precision) {
5462  const longFormat = o.c.year > 9999 || o.c.year < 0;
5463  let c = "";
5464  if (longFormat && o.c.year >= 0) c += "+";
5465  c += padStart(o.c.year, longFormat ? 6 : 4);
5466  if (precision === "year") return c;
5467  if (extended) {
5468    c += "-";
5469    c += padStart(o.c.month);
5470    if (precision === "month") return c;
5471    c += "-";
5472  } else {
5473    c += padStart(o.c.month);
5474    if (precision === "month") return c;
5475  }
5476  c += padStart(o.c.day);
5477  return c;
5478}
5479function toISOTime(o, extended, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision) {
5480  let showSeconds = !suppressSeconds || o.c.millisecond !== 0 || o.c.second !== 0,
5481    c = "";
5482  switch (precision) {
5483    case "day":
5484    case "month":
5485    case "year":
5486      break;
5487    default:
5488      c += padStart(o.c.hour);
5489      if (precision === "hour") break;
5490      if (extended) {
5491        c += ":";
5492        c += padStart(o.c.minute);
5493        if (precision === "minute") break;
5494        if (showSeconds) {
5495          c += ":";
5496          c += padStart(o.c.second);
5497        }
5498      } else {
5499        c += padStart(o.c.minute);
5500        if (precision === "minute") break;
5501        if (showSeconds) {
5502          c += padStart(o.c.second);
5503        }
5504      }
5505      if (precision === "second") break;
5506      if (showSeconds && (!suppressMilliseconds || o.c.millisecond !== 0)) {
5507        c += ".";
5508        c += padStart(o.c.millisecond, 3);
5509      }
5510  }
5511  if (includeOffset) {
5512    if (o.isOffsetFixed && o.offset === 0 && !extendedZone) {
5513      c += "Z";
5514    } else if (o.o < 0) {
5515      c += "-";
5516      c += padStart(Math.trunc(-o.o / 60));
5517      c += ":";
5518      c += padStart(Math.trunc(-o.o % 60));
5519    } else {
5520      c += "+";
5521      c += padStart(Math.trunc(o.o / 60));
5522      c += ":";
5523      c += padStart(Math.trunc(o.o % 60));
5524    }
5525  }
5526  if (extendedZone) {
5527    c += "[" + o.zone.ianaName + "]";
5528  }
5529  return c;
5530}
5531
5532// defaults for unspecified units in the supported calendars
5533const defaultUnitValues = {
5534    month: 1,
5535    day: 1,
5536    hour: 0,
5537    minute: 0,
5538    second: 0,
5539    millisecond: 0
5540  },
5541  defaultWeekUnitValues = {
5542    weekNumber: 1,
5543    weekday: 1,
5544    hour: 0,
5545    minute: 0,
5546    second: 0,
5547    millisecond: 0
5548  },
5549  defaultOrdinalUnitValues = {
5550    ordinal: 1,
5551    hour: 0,
5552    minute: 0,
5553    second: 0,
5554    millisecond: 0
5555  };
5556
5557// Units in the supported calendars, sorted by bigness
5558const orderedUnits = ["year", "month", "day", "hour", "minute", "second", "millisecond"],
5559  orderedWeekUnits = ["weekYear", "weekNumber", "weekday", "hour", "minute", "second", "millisecond"],
5560  orderedOrdinalUnits = ["year", "ordinal", "hour", "minute", "second", "millisecond"];
5561
5562// standardize case and plurality in units
5563function normalizeUnit(unit) {
5564  const normalized = {
5565    year: "year",
5566    years: "year",
5567    month: "month",
5568    months: "month",
5569    day: "day",
5570    days: "day",
5571    hour: "hour",
5572    hours: "hour",
5573    minute: "minute",
5574    minutes: "minute",
5575    quarter: "quarter",
5576    quarters: "quarter",
5577    second: "second",
5578    seconds: "second",
5579    millisecond: "millisecond",
5580    milliseconds: "millisecond",
5581    weekday: "weekday",
5582    weekdays: "weekday",
5583    weeknumber: "weekNumber",
5584    weeksnumber: "weekNumber",
5585    weeknumbers: "weekNumber",
5586    weekyear: "weekYear",
5587    weekyears: "weekYear",
5588    ordinal: "ordinal"
5589  }[unit.toLowerCase()];
5590  if (!normalized) throw new InvalidUnitError(unit);
5591  return normalized;
5592}
5593function normalizeUnitWithLocalWeeks(unit) {
5594  switch (unit.toLowerCase()) {
5595    case "localweekday":
5596    case "localweekdays":
5597      return "localWeekday";
5598    case "localweeknumber":
5599    case "localweeknumbers":
5600      return "localWeekNumber";
5601    case "localweekyear":
5602    case "localweekyears":
5603      return "localWeekYear";
5604    default:
5605      return normalizeUnit(unit);
5606  }
5607}
5608
5609// cache offsets for zones based on the current timestamp when this function is
5610// first called. When we are handling a datetime from components like (year,
5611// month, day, hour) in a time zone, we need a guess about what the timezone
5612// offset is so that we can convert into a UTC timestamp. One way is to find the
5613// offset of now in the zone. The actual date may have a different offset (for
5614// example, if we handle a date in June while we're in December in a zone that
5615// observes DST), but we can check and adjust that.
5616//
5617// When handling many dates, calculating the offset for now every time is
5618// expensive. It's just a guess, so we can cache the offset to use even if we
5619// are right on a time change boundary (we'll just correct in the other
5620// direction). Using a timestamp from first read is a slight optimization for
5621// handling dates close to the current date, since those dates will usually be
5622// in the same offset (we could set the timestamp statically, instead). We use a
5623// single timestamp for all zones to make things a bit more predictable.
5624//
5625// This is safe for quickDT (used by local() and utc()) because we don't fill in
5626// higher-order units from tsNow (as we do in fromObject, this requires that
5627// offset is calculated from tsNow).
5628/**
5629 * @param {Zone} zone
5630 * @return {number}
5631 */
5632function guessOffsetForZone(zone) {
5633  if (zoneOffsetTs === undefined) {
5634    zoneOffsetTs = Settings.now();
5635  }
5636
5637  // Do not cache anything but IANA zones, because it is not safe to do so.
5638  // Guessing an offset which is not present in the zone can cause wrong results from fixOffset
5639  if (zone.type !== "iana") {
5640    return zone.offset(zoneOffsetTs);
5641  }
5642  const zoneName = zone.name;
5643  let offsetGuess = zoneOffsetGuessCache.get(zoneName);
5644  if (offsetGuess === undefined) {
5645    offsetGuess = zone.offset(zoneOffsetTs);
5646    zoneOffsetGuessCache.set(zoneName, offsetGuess);
5647  }
5648  return offsetGuess;
5649}
5650
5651// this is a dumbed down version of fromObject() that runs about 60% faster
5652// but doesn't do any validation, makes a bunch of assumptions about what units
5653// are present, and so on.
5654function quickDT(obj, opts) {
5655  const zone = normalizeZone(opts.zone, Settings.defaultZone);
5656  if (!zone.isValid) {
5657    return DateTime.invalid(unsupportedZone(zone));
5658  }
5659  const loc = Locale.fromObject(opts);
5660  let ts, o;
5661
5662  // assume we have the higher-order units
5663  if (!isUndefined(obj.year)) {
5664    for (const u of orderedUnits) {
5665      if (isUndefined(obj[u])) {
5666        obj[u] = defaultUnitValues[u];
5667      }
5668    }
5669    const invalid = hasInvalidGregorianData(obj) || hasInvalidTimeData(obj);
5670    if (invalid) {
5671      return DateTime.invalid(invalid);
5672    }
5673    const offsetProvis = guessOffsetForZone(zone);
5674    [ts, o] = objToTS(obj, offsetProvis, zone);
5675  } else {
5676    ts = Settings.now();
5677  }
5678  return new DateTime({
5679    ts,
5680    zone,
5681    loc,
5682    o
5683  });
5684}
5685function diffRelative(start, end, opts) {
5686  const round = isUndefined(opts.round) ? true : opts.round,
5687    rounding = isUndefined(opts.rounding) ? "trunc" : opts.rounding,
5688    format = (c, unit) => {
5689      c = roundTo(c, round || opts.calendary ? 0 : 2, opts.calendary ? "round" : rounding);
5690      const formatter = end.loc.clone(opts).relFormatter(opts);
5691      return formatter.format(c, unit);
5692    },
5693    differ = unit => {
5694      if (opts.calendary) {
5695        if (!end.hasSame(start, unit)) {
5696          return end.startOf(unit).diff(start.startOf(unit), unit).get(unit);
5697        } else return 0;
5698      } else {
5699        return end.diff(start, unit).get(unit);
5700      }
5701    };
5702  if (opts.unit) {
5703    return format(differ(opts.unit), opts.unit);
5704  }
5705  for (const unit of opts.units) {
5706    const count = differ(unit);
5707    if (Math.abs(count) >= 1) {
5708      return format(count, unit);
5709    }
5710  }
5711  return format(start > end ? -0 : 0, opts.units[opts.units.length - 1]);
5712}
5713function lastOpts(argList) {
5714  let opts = {},
5715    args;
5716  if (argList.length > 0 && typeof argList[argList.length - 1] === "object") {
5717    opts = argList[argList.length - 1];
5718    args = Array.from(argList).slice(0, argList.length - 1);
5719  } else {
5720    args = Array.from(argList);
5721  }
5722  return [opts, args];
5723}
5724
5725/**
5726 * Timestamp to use for cached zone offset guesses (exposed for test)
5727 */
5728let zoneOffsetTs;
5729/**
5730 * Cache for zone offset guesses (exposed for test).
5731 *
5732 * This optimizes quickDT via guessOffsetForZone to avoid repeated calls of
5733 * zone.offset().
5734 */
5735const zoneOffsetGuessCache = new Map();
5736
5737/**
5738 * A DateTime is an immutable data structure representing a specific date and time and accompanying methods. It contains class and instance methods for creating, parsing, interrogating, transforming, and formatting them.
5739 *
5740 * A DateTime comprises of:
5741 * * A timestamp. Each DateTime instance refers to a specific millisecond of the Unix epoch.
5742 * * A time zone. Each instance is considered in the context of a specific zone (by default the local system's zone).
5743 * * Configuration properties that effect how output strings are formatted, such as `locale`, `numberingSystem`, and `outputCalendar`.
5744 *
5745 * Here is a brief overview of the most commonly used functionality it provides:
5746 *
5747 * * **Creation**: To create a DateTime from its components, use one of its factory class methods: {@link DateTime.local}, {@link DateTime.utc}, and (most flexibly) {@link DateTime.fromObject}. To create one from a standard string format, use {@link DateTime.fromISO}, {@link DateTime.fromHTTP}, and {@link DateTime.fromRFC2822}. To create one from a custom string format, use {@link DateTime.fromFormat}. To create one from a native JS date, use {@link DateTime.fromJSDate}.
5748 * * **Gregorian calendar and time**: To examine the Gregorian properties of a DateTime individually (i.e as opposed to collectively through {@link DateTime#toObject}), use the {@link DateTime#year}, {@link DateTime#month},
5749 * {@link DateTime#day}, {@link DateTime#hour}, {@link DateTime#minute}, {@link DateTime#second}, {@link DateTime#millisecond} accessors.
5750 * * **Week calendar**: For ISO week calendar attributes, see the {@link DateTime#weekYear}, {@link DateTime#weekNumber}, and {@link DateTime#weekday} accessors.
5751 * * **Configuration** See the {@link DateTime#locale} and {@link DateTime#numberingSystem} accessors.
5752 * * **Transformation**: To transform the DateTime into other DateTimes, use {@link DateTime#set}, {@link DateTime#reconfigure}, {@link DateTime#setZone}, {@link DateTime#setLocale}, {@link DateTime.plus}, {@link DateTime#minus}, {@link DateTime#endOf}, {@link DateTime#startOf}, {@link DateTime#toUTC}, and {@link DateTime#toLocal}.
5753 * * **Output**: To convert the DateTime to other representations, use the {@link DateTime#toRelative}, {@link DateTime#toRelativeCalendar}, {@link DateTime#toJSON}, {@link DateTime#toISO}, {@link DateTime#toHTTP}, {@link DateTime#toObject}, {@link DateTime#toRFC2822}, {@link DateTime#toString}, {@link DateTime#toLocaleString}, {@link DateTime#toFormat}, {@link DateTime#toMillis} and {@link DateTime#toJSDate}.
5754 *
5755 * There's plenty others documented below. In addition, for more information on subtler topics like internationalization, time zones, alternative calendars, validity, and so on, see the external documentation.
5756 */
5757class DateTime {
5758  /**
5759   * @access private
5760   */
5761  constructor(config) {
5762    const zone = config.zone || Settings.defaultZone;
5763    let invalid = config.invalid || (Number.isNaN(config.ts) ? new Invalid("invalid input") : null) || (!zone.isValid ? unsupportedZone(zone) : null);
5764    /**
5765     * @access private
5766     */
5767    this.ts = isUndefined(config.ts) ? Settings.now() : config.ts;
5768    let c = null,
5769      o = null;
5770    if (!invalid) {
5771      const unchanged = config.old && config.old.ts === this.ts && config.old.zone.equals(zone);
5772      if (unchanged) {
5773        [c, o] = [config.old.c, config.old.o];
5774      } else {
5775        // If an offset has been passed and we have not been called from
5776        // clone(), we can trust it and avoid the offset calculation.
5777        const ot = isNumber(config.o) && !config.old ? config.o : zone.offset(this.ts);
5778        c = tsToObj(this.ts, ot);
5779        invalid = Number.isNaN(c.year) ? new Invalid("invalid input") : null;
5780        c = invalid ? null : c;
5781        o = invalid ? null : ot;
5782      }
5783    }
5784
5785    /**
5786     * @access private
5787     */
5788    this._zone = zone;
5789    /**
5790     * @access private
5791     */
5792    this.loc = config.loc || Locale.create();
5793    /**
5794     * @access private
5795     */
5796    this.invalid = invalid;
5797    /**
5798     * @access private
5799     */
5800    this.weekData = null;
5801    /**
5802     * @access private
5803     */
5804    this.localWeekData = null;
5805    /**
5806     * @access private
5807     */
5808    this.c = c;
5809    /**
5810     * @access private
5811     */
5812    this.o = o;
5813    /**
5814     * @access private
5815     */
5816    this.isLuxonDateTime = true;
5817  }
5818
5819  // CONSTRUCT
5820
5821  /**
5822   * Create a DateTime for the current instant, in the system's time zone.
5823   *
5824   * Use Settings to override these default values if needed.
5825   * @example DateTime.now().toISO() //~> now in the ISO format
5826   * @return {DateTime}
5827   */
5828  static now() {
5829    return new DateTime({});
5830  }
5831
5832  /**
5833   * Create a local DateTime
5834   * @param {number} [year] - The calendar year. If omitted (as in, call `local()` with no arguments), the current time will be used
5835   * @param {number} [month=1] - The month, 1-indexed
5836   * @param {number} [day=1] - The day of the month, 1-indexed
5837   * @param {number} [hour=0] - The hour of the day, in 24-hour time
5838   * @param {number} [minute=0] - The minute of the hour, meaning a number between 0 and 59
5839   * @param {number} [second=0] - The second of the minute, meaning a number between 0 and 59
5840   * @param {number} [millisecond=0] - The millisecond of the second, meaning a number between 0 and 999
5841   * @example DateTime.local()                                  //~> now
5842   * @example DateTime.local({ zone: "America/New_York" })      //~> now, in US east coast time
5843   * @example DateTime.local(2017)                              //~> 2017-01-01T00:00:00
5844   * @example DateTime.local(2017, 3)                           //~> 2017-03-01T00:00:00
5845   * @example DateTime.local(2017, 3, 12, { locale: "fr" })     //~> 2017-03-12T00:00:00, with a French locale
5846   * @example DateTime.local(2017, 3, 12, 5)                    //~> 2017-03-12T05:00:00
5847   * @example DateTime.local(2017, 3, 12, 5, { zone: "utc" })   //~> 2017-03-12T05:00:00, in UTC
5848   * @example DateTime.local(2017, 3, 12, 5, 45)                //~> 2017-03-12T05:45:00
5849   * @example DateTime.local(2017, 3, 12, 5, 45, 10)            //~> 2017-03-12T05:45:10
5850   * @example DateTime.local(2017, 3, 12, 5, 45, 10, 765)       //~> 2017-03-12T05:45:10.765
5851   * @return {DateTime}
5852   */
5853  static local() {
5854    const [opts, args] = lastOpts(arguments),
5855      [year, month, day, hour, minute, second, millisecond] = args;
5856    return quickDT({
5857      year,
5858      month,
5859      day,
5860      hour,
5861      minute,
5862      second,
5863      millisecond
5864    }, opts);
5865  }
5866
5867  /**
5868   * Create a DateTime in UTC
5869   * @param {number} [year] - The calendar year. If omitted (as in, call `utc()` with no arguments), the current time will be used
5870   * @param {number} [month=1] - The month, 1-indexed
5871   * @param {number} [day=1] - The day of the month
5872   * @param {number} [hour=0] - The hour of the day, in 24-hour time
5873   * @param {number} [minute=0] - The minute of the hour, meaning a number between 0 and 59
5874   * @param {number} [second=0] - The second of the minute, meaning a number between 0 and 59
5875   * @param {number} [millisecond=0] - The millisecond of the second, meaning a number between 0 and 999
5876   * @param {Object} options - configuration options for the DateTime
5877   * @param {string} [options.locale] - a locale to set on the resulting DateTime instance
5878   * @param {string} [options.outputCalendar] - the output calendar to set on the resulting DateTime instance
5879   * @param {string} [options.numberingSystem] - the numbering system to set on the resulting DateTime instance
5880   * @param {string} [options.weekSettings] - the week settings to set on the resulting DateTime instance
5881   * @example DateTime.utc()                                              //~> now
5882   * @example DateTime.utc(2017)                                          //~> 2017-01-01T00:00:00Z
5883   * @example DateTime.utc(2017, 3)                                       //~> 2017-03-01T00:00:00Z
5884   * @example DateTime.utc(2017, 3, 12)                                   //~> 2017-03-12T00:00:00Z
5885   * @example DateTime.utc(2017, 3, 12, 5)                                //~> 2017-03-12T05:00:00Z
5886   * @example DateTime.utc(2017, 3, 12, 5, 45)                            //~> 2017-03-12T05:45:00Z
5887   * @example DateTime.utc(2017, 3, 12, 5, 45, { locale: "fr" })          //~> 2017-03-12T05:45:00Z with a French locale
5888   * @example DateTime.utc(2017, 3, 12, 5, 45, 10)                        //~> 2017-03-12T05:45:10Z
5889   * @example DateTime.utc(2017, 3, 12, 5, 45, 10, 765, { locale: "fr" }) //~> 2017-03-12T05:45:10.765Z with a French locale
5890   * @return {DateTime}
5891   */
5892  static utc() {
5893    const [opts, args] = lastOpts(arguments),
5894      [year, month, day, hour, minute, second, millisecond] = args;
5895    opts.zone = FixedOffsetZone.utcInstance;
5896    return quickDT({
5897      year,
5898      month,
5899      day,
5900      hour,
5901      minute,
5902      second,
5903      millisecond
5904    }, opts);
5905  }
5906
5907  /**
5908   * Create a DateTime from a JavaScript Date object. Uses the default zone.
5909   * @param {Date} date - a JavaScript Date object
5910   * @param {Object} options - configuration options for the DateTime
5911   * @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into
5912   * @return {DateTime}
5913   */
5914  static fromJSDate(date, options = {}) {
5915    const ts = isDate(date) ? date.valueOf() : NaN;
5916    if (Number.isNaN(ts)) {
5917      return DateTime.invalid("invalid input");
5918    }
5919    const zoneToUse = normalizeZone(options.zone, Settings.defaultZone);
5920    if (!zoneToUse.isValid) {
5921      return DateTime.invalid(unsupportedZone(zoneToUse));
5922    }
5923    return new DateTime({
5924      ts: ts,
5925      zone: zoneToUse,
5926      loc: Locale.fromObject(options)
5927    });
5928  }
5929
5930  /**
5931   * Create a DateTime from a number of milliseconds since the epoch (meaning since 1 January 1970 00:00:00 UTC). Uses the default zone.
5932   * @param {number} milliseconds - a number of milliseconds since 1970 UTC
5933   * @param {Object} options - configuration options for the DateTime
5934   * @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into
5935   * @param {string} [options.locale] - a locale to set on the resulting DateTime instance
5936   * @param {string} options.outputCalendar - the output calendar to set on the resulting DateTime instance
5937   * @param {string} options.numberingSystem - the numbering system to set on the resulting DateTime instance
5938   * @param {string} options.weekSettings - the week settings to set on the resulting DateTime instance
5939   * @return {DateTime}
5940   */
5941  static fromMillis(milliseconds, options = {}) {
5942    if (!isNumber(milliseconds)) {
5943      throw new InvalidArgumentError(`fromMillis requires a numerical input, but received a ${typeof milliseconds} with value ${milliseconds}`);
5944    } else if (milliseconds < -MAX_DATE || milliseconds > MAX_DATE) {
5945      // this isn't perfect because we can still end up out of range because of additional shifting, but it's a start
5946      return DateTime.invalid("Timestamp out of range");
5947    } else {
5948      return new DateTime({
5949        ts: milliseconds,
5950        zone: normalizeZone(options.zone, Settings.defaultZone),
5951        loc: Locale.fromObject(options)
5952      });
5953    }
5954  }
5955
5956  /**
5957   * Create a DateTime from a number of seconds since the epoch (meaning since 1 January 1970 00:00:00 UTC). Uses the default zone.
5958   * @param {number} seconds - a number of seconds since 1970 UTC
5959   * @param {Object} options - configuration options for the DateTime
5960   * @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into
5961   * @param {string} [options.locale] - a locale to set on the resulting DateTime instance
5962   * @param {string} options.outputCalendar - the output calendar to set on the resulting DateTime instance
5963   * @param {string} options.numberingSystem - the numbering system to set on the resulting DateTime instance
5964   * @param {string} options.weekSettings - the week settings to set on the resulting DateTime instance
5965   * @return {DateTime}
5966   */
5967  static fromSeconds(seconds, options = {}) {
5968    if (!isNumber(seconds)) {
5969      throw new InvalidArgumentError("fromSeconds requires a numerical input");
5970    } else {
5971      return new DateTime({
5972        ts: seconds * 1000,
5973        zone: normalizeZone(options.zone, Settings.defaultZone),
5974        loc: Locale.fromObject(options)
5975      });
5976    }
5977  }
5978
5979  /**
5980   * Create a DateTime from a JavaScript object with keys like 'year' and 'hour' with reasonable defaults.
5981   * @param {Object} obj - the object to create the DateTime from
5982   * @param {number} obj.year - a year, such as 1987
5983   * @param {number} obj.month - a month, 1-12
5984   * @param {number} obj.day - a day of the month, 1-31, depending on the month
5985   * @param {number} obj.ordinal - day of the year, 1-365 or 366
5986   * @param {number} obj.weekYear - an ISO week year
5987   * @param {number} obj.weekNumber - an ISO week number, between 1 and 52 or 53, depending on the year
5988   * @param {number} obj.weekday - an ISO weekday, 1-7, where 1 is Monday and 7 is Sunday
5989   * @param {number} obj.localWeekYear - a week year, according to the locale
5990   * @param {number} obj.localWeekNumber - a week number, between 1 and 52 or 53, depending on the year, according to the locale
5991   * @param {number} obj.localWeekday - a weekday, 1-7, where 1 is the first and 7 is the last day of the week, according to the locale
5992   * @param {number} obj.hour - hour of the day, 0-23
5993   * @param {number} obj.minute - minute of the hour, 0-59
5994   * @param {number} obj.second - second of the minute, 0-59
5995   * @param {number} obj.millisecond - millisecond of the second, 0-999
5996   * @param {Object} opts - options for creating this DateTime
5997   * @param {string|Zone} [opts.zone='local'] - interpret the numbers in the context of a particular zone. Can take any value taken as the first argument to setZone()
5998   * @param {string} [opts.locale='system\'s locale'] - a locale to set on the resulting DateTime instance
5999   * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance
6000   * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance
6001   * @param {string} opts.weekSettings - the week settings to set on the resulting DateTime instance
6002   * @example DateTime.fromObject({ year: 1982, month: 5, day: 25}).toISODate() //=> '1982-05-25'
6003   * @example DateTime.fromObject({ year: 1982 }).toISODate() //=> '1982-01-01'
6004   * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }) //~> today at 10:26:06
6005   * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'utc' }),
6006   * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'local' })
6007   * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'America/New_York' })
6008   * @example DateTime.fromObject({ weekYear: 2016, weekNumber: 2, weekday: 3 }).toISODate() //=> '2016-01-13'
6009   * @example DateTime.fromObject({ localWeekYear: 2022, localWeekNumber: 1, localWeekday: 1 }, { locale: "en-US" }).toISODate() //=> '2021-12-26'
6010   * @return {DateTime}
6011   */
6012  static fromObject(obj, opts = {}) {
6013    obj = obj || {};
6014    const zoneToUse = normalizeZone(opts.zone, Settings.defaultZone);
6015    if (!zoneToUse.isValid) {
6016      return DateTime.invalid(unsupportedZone(zoneToUse));
6017    }
6018    const loc = Locale.fromObject(opts);
6019    const normalized = normalizeObject(obj, normalizeUnitWithLocalWeeks);
6020    const {
6021      minDaysInFirstWeek,
6022      startOfWeek
6023    } = usesLocalWeekValues(normalized, loc);
6024    const tsNow = Settings.now(),
6025      offsetProvis = !isUndefined(opts.specificOffset) ? opts.specificOffset : zoneToUse.offset(tsNow),
6026      containsOrdinal = !isUndefined(normalized.ordinal),
6027      containsGregorYear = !isUndefined(normalized.year),
6028      containsGregorMD = !isUndefined(normalized.month) || !isUndefined(normalized.day),
6029      containsGregor = containsGregorYear || containsGregorMD,
6030      definiteWeekDef = normalized.weekYear || normalized.weekNumber;
6031
6032    // cases:
6033    // just a weekday -> this week's instance of that weekday, no worries
6034    // (gregorian data or ordinal) + (weekYear or weekNumber) -> error
6035    // (gregorian month or day) + ordinal -> error
6036    // otherwise just use weeks or ordinals or gregorian, depending on what's specified
6037
6038    if ((containsGregor || containsOrdinal) && definiteWeekDef) {
6039      throw new ConflictingSpecificationError("Can't mix weekYear/weekNumber units with year/month/day or ordinals");
6040    }
6041    if (containsGregorMD && containsOrdinal) {
6042      throw new ConflictingSpecificationError("Can't mix ordinal dates with month/day");
6043    }
6044    const useWeekData = definiteWeekDef || normalized.weekday && !containsGregor;
6045
6046    // configure ourselves to deal with gregorian dates or week stuff
6047    let units,
6048      defaultValues,
6049      objNow = tsToObj(tsNow, offsetProvis);
6050    if (useWeekData) {
6051      units = orderedWeekUnits;
6052      defaultValues = defaultWeekUnitValues;
6053      objNow = gregorianToWeek(objNow, minDaysInFirstWeek, startOfWeek);
6054    } else if (containsOrdinal) {
6055      units = orderedOrdinalUnits;
6056      defaultValues = defaultOrdinalUnitValues;
6057      objNow = gregorianToOrdinal(objNow);
6058    } else {
6059      units = orderedUnits;
6060      defaultValues = defaultUnitValues;
6061    }
6062
6063    // set default values for missing stuff
6064    let foundFirst = false;
6065    for (const u of units) {
6066      const v = normalized[u];
6067      if (!isUndefined(v)) {
6068        foundFirst = true;
6069      } else if (foundFirst) {
6070        normalized[u] = defaultValues[u];
6071      } else {
6072        normalized[u] = objNow[u];
6073      }
6074    }
6075
6076    // make sure the values we have are in range
6077    const higherOrderInvalid = useWeekData ? hasInvalidWeekData(normalized, minDaysInFirstWeek, startOfWeek) : containsOrdinal ? hasInvalidOrdinalData(normalized) : hasInvalidGregorianData(normalized),
6078      invalid = higherOrderInvalid || hasInvalidTimeData(normalized);
6079    if (invalid) {
6080      return DateTime.invalid(invalid);
6081    }
6082
6083    // compute the actual time
6084    const gregorian = useWeekData ? weekToGregorian(normalized, minDaysInFirstWeek, startOfWeek) : containsOrdinal ? ordinalToGregorian(normalized) : normalized,
6085      [tsFinal, offsetFinal] = objToTS(gregorian, offsetProvis, zoneToUse),
6086      inst = new DateTime({
6087        ts: tsFinal,
6088        zone: zoneToUse,
6089        o: offsetFinal,
6090        loc
6091      });
6092
6093    // gregorian data + weekday serves only to validate
6094    if (normalized.weekday && containsGregor && obj.weekday !== inst.weekday) {
6095      return DateTime.invalid("mismatched weekday", `you can't specify both a weekday of ${normalized.weekday} and a date of ${inst.toISO()}`);
6096    }
6097    if (!inst.isValid) {
6098      return DateTime.invalid(inst.invalid);
6099    }
6100    return inst;
6101  }
6102
6103  /**
6104   * Create a DateTime from an ISO 8601 string
6105   * @param {string} text - the ISO string
6106   * @param {Object} opts - options to affect the creation
6107   * @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the time to this zone
6108   * @param {boolean} [opts.setZone=false] - override the zone with a fixed-offset zone specified in the string itself, if it specifies one
6109   * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance
6110   * @param {string} [opts.outputCalendar] - the output calendar to set on the resulting DateTime instance
6111   * @param {string} [opts.numberingSystem] - the numbering system to set on the resulting DateTime instance
6112   * @param {string} [opts.weekSettings] - the week settings to set on the resulting DateTime instance
6113   * @example DateTime.fromISO('2016-05-25T09:08:34.123')
6114   * @example DateTime.fromISO('2016-05-25T09:08:34.123+06:00')
6115   * @example DateTime.fromISO('2016-05-25T09:08:34.123+06:00', {setZone: true})
6116   * @example DateTime.fromISO('2016-05-25T09:08:34.123', {zone: 'utc'})
6117   * @example DateTime.fromISO('2016-W05-4')
6118   * @return {DateTime}
6119   */
6120  static fromISO(text, opts = {}) {
6121    const [vals, parsedZone] = parseISODate(text);
6122    return parseDataToDateTime(vals, parsedZone, opts, "ISO 8601", text);
6123  }
6124
6125  /**
6126   * Create a DateTime from an RFC 2822 string
6127   * @param {string} text - the RFC 2822 string
6128   * @param {Object} opts - options to affect the creation
6129   * @param {string|Zone} [opts.zone='local'] - convert the time to this zone. Since the offset is always specified in the string itself, this has no effect on the interpretation of string, merely the zone the resulting DateTime is expressed in.
6130   * @param {boolean} [opts.setZone=false] - override the zone with a fixed-offset zone specified in the string itself, if it specifies one
6131   * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance
6132   * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance
6133   * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance
6134   * @param {string} opts.weekSettings - the week settings to set on the resulting DateTime instance
6135   * @example DateTime.fromRFC2822('25 Nov 2016 13:23:12 GMT')
6136   * @example DateTime.fromRFC2822('Fri, 25 Nov 2016 13:23:12 +0600')
6137   * @example DateTime.fromRFC2822('25 Nov 2016 13:23 Z')
6138   * @return {DateTime}
6139   */
6140  static fromRFC2822(text, opts = {}) {
6141    const [vals, parsedZone] = parseRFC2822Date(text);
6142    return parseDataToDateTime(vals, parsedZone, opts, "RFC 2822", text);
6143  }
6144
6145  /**
6146   * Create a DateTime from an HTTP header date
6147   * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1
6148   * @param {string} text - the HTTP header date
6149   * @param {Object} opts - options to affect the creation
6150   * @param {string|Zone} [opts.zone='local'] - convert the time to this zone. Since HTTP dates are always in UTC, this has no effect on the interpretation of string, merely the zone the resulting DateTime is expressed in.
6151   * @param {boolean} [opts.setZone=false] - override the zone with the fixed-offset zone specified in the string. For HTTP dates, this is always UTC, so this option is equivalent to setting the `zone` option to 'utc', but this option is included for consistency with similar methods.
6152   * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance
6153   * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance
6154   * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance
6155   * @param {string} opts.weekSettings - the week settings to set on the resulting DateTime instance
6156   * @example DateTime.fromHTTP('Sun, 06 Nov 1994 08:49:37 GMT')
6157   * @example DateTime.fromHTTP('Sunday, 06-Nov-94 08:49:37 GMT')
6158   * @example DateTime.fromHTTP('Sun Nov  6 08:49:37 1994')
6159   * @return {DateTime}
6160   */
6161  static fromHTTP(text, opts = {}) {
6162    const [vals, parsedZone] = parseHTTPDate(text);
6163    return parseDataToDateTime(vals, parsedZone, opts, "HTTP", opts);
6164  }
6165
6166  /**
6167   * Create a DateTime from an input string and format string.
6168   * Defaults to en-US if no locale has been specified, regardless of the system's locale. For a table of tokens and their interpretations, see [here](https://moment.github.io/luxon/#/parsing?id=table-of-tokens).
6169   * @param {string} text - the string to parse
6170   * @param {string} fmt - the format the string is expected to be in (see the link below for the formats)
6171   * @param {Object} opts - options to affect the creation
6172   * @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the DateTime to this zone
6173   * @param {boolean} [opts.setZone=false] - override the zone with a zone specified in the string itself, if it specifies one
6174   * @param {string} [opts.locale='en-US'] - a locale string to use when parsing. Will also set the DateTime to this locale
6175   * @param {string} opts.numberingSystem - the numbering system to use when parsing. Will also set the resulting DateTime to this numbering system
6176   * @param {string} opts.weekSettings - the week settings to set on the resulting DateTime instance
6177   * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance
6178   * @return {DateTime}
6179   */
6180  static fromFormat(text, fmt, opts = {}) {
6181    if (isUndefined(text) || isUndefined(fmt)) {
6182      throw new InvalidArgumentError("fromFormat requires an input string and a format");
6183    }
6184    const {
6185        locale = null,
6186        numberingSystem = null
6187      } = opts,
6188      localeToUse = Locale.fromOpts({
6189        locale,
6190        numberingSystem,
6191        defaultToEN: true
6192      }),
6193      [vals, parsedZone, specificOffset, invalid] = parseFromTokens(localeToUse, text, fmt);
6194    if (invalid) {
6195      return DateTime.invalid(invalid);
6196    } else {
6197      return parseDataToDateTime(vals, parsedZone, opts, `format ${fmt}`, text, specificOffset);
6198    }
6199  }
6200
6201  /**
6202   * @deprecated use fromFormat instead
6203   */
6204  static fromString(text, fmt, opts = {}) {
6205    return DateTime.fromFormat(text, fmt, opts);
6206  }
6207
6208  /**
6209   * Create a DateTime from a SQL date, time, or datetime
6210   * Defaults to en-US if no locale has been specified, regardless of the system's locale
6211   * @param {string} text - the string to parse
6212   * @param {Object} opts - options to affect the creation
6213   * @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the DateTime to this zone
6214   * @param {boolean} [opts.setZone=false] - override the zone with a zone specified in the string itself, if it specifies one
6215   * @param {string} [opts.locale='en-US'] - a locale string to use when parsing. Will also set the DateTime to this locale
6216   * @param {string} opts.numberingSystem - the numbering system to use when parsing. Will also set the resulting DateTime to this numbering system
6217   * @param {string} opts.weekSettings - the week settings to set on the resulting DateTime instance
6218   * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance
6219   * @example DateTime.fromSQL('2017-05-15')
6220   * @example DateTime.fromSQL('2017-05-15 09:12:34')
6221   * @example DateTime.fromSQL('2017-05-15 09:12:34.342')
6222   * @example DateTime.fromSQL('2017-05-15 09:12:34.342+06:00')
6223   * @example DateTime.fromSQL('2017-05-15 09:12:34.342 America/Los_Angeles')
6224   * @example DateTime.fromSQL('2017-05-15 09:12:34.342 America/Los_Angeles', { setZone: true })
6225   * @example DateTime.fromSQL('2017-05-15 09:12:34.342', { zone: 'America/Los_Angeles' })
6226   * @example DateTime.fromSQL('09:12:34.342')
6227   * @return {DateTime}
6228   */
6229  static fromSQL(text, opts = {}) {
6230    const [vals, parsedZone] = parseSQL(text);
6231    return parseDataToDateTime(vals, parsedZone, opts, "SQL", text);
6232  }
6233
6234  /**
6235   * Create an invalid DateTime.
6236   * @param {string} reason - simple string of why this DateTime is invalid. Should not contain parameters or anything else data-dependent.
6237   * @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information
6238   * @return {DateTime}
6239   */
6240  static invalid(reason, explanation = null) {
6241    if (!reason) {
6242      throw new InvalidArgumentError("need to specify a reason the DateTime is invalid");
6243    }
6244    const invalid = reason instanceof Invalid ? reason : new Invalid(reason, explanation);
6245    if (Settings.throwOnInvalid) {
6246      throw new InvalidDateTimeError(invalid);
6247    } else {
6248      return new DateTime({
6249        invalid
6250      });
6251    }
6252  }
6253
6254  /**
6255   * Check if an object is an instance of DateTime. Works across context boundaries
6256   * @param {object} o
6257   * @return {boolean}
6258   */
6259  static isDateTime(o) {
6260    return o && o.isLuxonDateTime || false;
6261  }
6262
6263  /**
6264   * Produce the format string for a set of options
6265   * @param formatOpts
6266   * @param localeOpts
6267   * @returns {string}
6268   */
6269  static parseFormatForOpts(formatOpts, localeOpts = {}) {
6270    const tokenList = formatOptsToTokens(formatOpts, Locale.fromObject(localeOpts));
6271    return !tokenList ? null : tokenList.map(t => t ? t.val : null).join("");
6272  }
6273
6274  /**
6275   * Produce the the fully expanded format token for the locale
6276   * Does NOT quote characters, so quoted tokens will not round trip correctly
6277   * @param fmt
6278   * @param localeOpts
6279   * @returns {string}
6280   */
6281  static expandFormat(fmt, localeOpts = {}) {
6282    const expanded = expandMacroTokens(Formatter.parseFormat(fmt), Locale.fromObject(localeOpts));
6283    return expanded.map(t => t.val).join("");
6284  }
6285  static resetCache() {
6286    zoneOffsetTs = undefined;
6287    zoneOffsetGuessCache.clear();
6288  }
6289
6290  // INFO
6291
6292  /**
6293   * Get the value of unit.
6294   * @param {string} unit - a unit such as 'minute' or 'day'
6295   * @example DateTime.local(2017, 7, 4).get('month'); //=> 7
6296   * @example DateTime.local(2017, 7, 4).get('day'); //=> 4
6297   * @return {number}
6298   */
6299  get(unit) {
6300    return this[unit];
6301  }
6302
6303  /**
6304   * Returns whether the DateTime is valid. Invalid DateTimes occur when:
6305   * * The DateTime was created from invalid calendar information, such as the 13th month or February 30
6306   * * The DateTime was created by an operation on another invalid date
6307   * @type {boolean}
6308   */
6309  get isValid() {
6310    return this.invalid === null;
6311  }
6312
6313  /**
6314   * Returns an error code if this DateTime is invalid, or null if the DateTime is valid
6315   * @type {string}
6316   */
6317  get invalidReason() {
6318    return this.invalid ? this.invalid.reason : null;
6319  }
6320
6321  /**
6322   * Returns an explanation of why this DateTime became invalid, or null if the DateTime is valid
6323   * @type {string}
6324   */
6325  get invalidExplanation() {
6326    return this.invalid ? this.invalid.explanation : null;
6327  }
6328
6329  /**
6330   * Get the locale of a DateTime, such 'en-GB'. The locale is used when formatting the DateTime
6331   *
6332   * @type {string}
6333   */
6334  get locale() {
6335    return this.isValid ? this.loc.locale : null;
6336  }
6337
6338  /**
6339   * Get the numbering system of a DateTime, such 'beng'. The numbering system is used when formatting the DateTime
6340   *
6341   * @type {string}
6342   */
6343  get numberingSystem() {
6344    return this.isValid ? this.loc.numberingSystem : null;
6345  }
6346
6347  /**
6348   * Get the output calendar of a DateTime, such 'islamic'. The output calendar is used when formatting the DateTime
6349   *
6350   * @type {string}
6351   */
6352  get outputCalendar() {
6353    return this.isValid ? this.loc.outputCalendar : null;
6354  }
6355
6356  /**
6357   * Get the time zone associated with this DateTime.
6358   * @type {Zone}
6359   */
6360  get zone() {
6361    return this._zone;
6362  }
6363
6364  /**
6365   * Get the name of the time zone.
6366   * @type {string}
6367   */
6368  get zoneName() {
6369    return this.isValid ? this.zone.name : null;
6370  }
6371
6372  /**
6373   * Get the year
6374   * @example DateTime.local(2017, 5, 25).year //=> 2017
6375   * @type {number}
6376   */
6377  get year() {
6378    return this.isValid ? this.c.year : NaN;
6379  }
6380
6381  /**
6382   * Get the quarter
6383   * @example DateTime.local(2017, 5, 25).quarter //=> 2
6384   * @type {number}
6385   */
6386  get quarter() {
6387    return this.isValid ? Math.ceil(this.c.month / 3) : NaN;
6388  }
6389
6390  /**
6391   * Get the month (1-12).
6392   * @example DateTime.local(2017, 5, 25).month //=> 5
6393   * @type {number}
6394   */
6395  get month() {
6396    return this.isValid ? this.c.month : NaN;
6397  }
6398
6399  /**
6400   * Get the day of the month (1-30ish).
6401   * @example DateTime.local(2017, 5, 25).day //=> 25
6402   * @type {number}
6403   */
6404  get day() {
6405    return this.isValid ? this.c.day : NaN;
6406  }
6407
6408  /**
6409   * Get the hour of the day (0-23).
6410   * @example DateTime.local(2017, 5, 25, 9).hour //=> 9
6411   * @type {number}
6412   */
6413  get hour() {
6414    return this.isValid ? this.c.hour : NaN;
6415  }
6416
6417  /**
6418   * Get the minute of the hour (0-59).
6419   * @example DateTime.local(2017, 5, 25, 9, 30).minute //=> 30
6420   * @type {number}
6421   */
6422  get minute() {
6423    return this.isValid ? this.c.minute : NaN;
6424  }
6425
6426  /**
6427   * Get the second of the minute (0-59).
6428   * @example DateTime.local(2017, 5, 25, 9, 30, 52).second //=> 52
6429   * @type {number}
6430   */
6431  get second() {
6432    return this.isValid ? this.c.second : NaN;
6433  }
6434
6435  /**
6436   * Get the millisecond of the second (0-999).
6437   * @example DateTime.local(2017, 5, 25, 9, 30, 52, 654).millisecond //=> 654
6438   * @type {number}
6439   */
6440  get millisecond() {
6441    return this.isValid ? this.c.millisecond : NaN;
6442  }
6443
6444  /**
6445   * Get the week year
6446   * @see https://en.wikipedia.org/wiki/ISO_week_date
6447   * @example DateTime.local(2014, 12, 31).weekYear //=> 2015
6448   * @type {number}
6449   */
6450  get weekYear() {
6451    return this.isValid ? possiblyCachedWeekData(this).weekYear : NaN;
6452  }
6453
6454  /**
6455   * Get the week number of the week year (1-52ish).
6456   * @see https://en.wikipedia.org/wiki/ISO_week_date
6457   * @example DateTime.local(2017, 5, 25).weekNumber //=> 21
6458   * @type {number}
6459   */
6460  get weekNumber() {
6461    return this.isValid ? possiblyCachedWeekData(this).weekNumber : NaN;
6462  }
6463
6464  /**
6465   * Get the day of the week.
6466   * 1 is Monday and 7 is Sunday
6467   * @see https://en.wikipedia.org/wiki/ISO_week_date
6468   * @example DateTime.local(2014, 11, 31).weekday //=> 4
6469   * @type {number}
6470   */
6471  get weekday() {
6472    return this.isValid ? possiblyCachedWeekData(this).weekday : NaN;
6473  }
6474
6475  /**
6476   * Returns true if this date is on a weekend according to the locale, false otherwise
6477   * @returns {boolean}
6478   */
6479  get isWeekend() {
6480    return this.isValid && this.loc.getWeekendDays().includes(this.weekday);
6481  }
6482
6483  /**
6484   * Get the day of the week according to the locale.
6485   * 1 is the first day of the week and 7 is the last day of the week.
6486   * If the locale assigns Sunday as the first day of the week, then a date which is a Sunday will return 1,
6487   * @returns {number}
6488   */
6489  get localWeekday() {
6490    return this.isValid ? possiblyCachedLocalWeekData(this).weekday : NaN;
6491  }
6492
6493  /**
6494   * Get the week number of the week year according to the locale. Different locales assign week numbers differently,
6495   * because the week can start on different days of the week (see localWeekday) and because a different number of days
6496   * is required for a week to count as the first week of a year.
6497   * @returns {number}
6498   */
6499  get localWeekNumber() {
6500    return this.isValid ? possiblyCachedLocalWeekData(this).weekNumber : NaN;
6501  }
6502
6503  /**
6504   * Get the week year according to the locale. Different locales assign week numbers (and therefor week years)
6505   * differently, see localWeekNumber.
6506   * @returns {number}
6507   */
6508  get localWeekYear() {
6509    return this.isValid ? possiblyCachedLocalWeekData(this).weekYear : NaN;
6510  }
6511
6512  /**
6513   * Get the ordinal (meaning the day of the year)
6514   * @example DateTime.local(2017, 5, 25).ordinal //=> 145
6515   * @type {number|DateTime}
6516   */
6517  get ordinal() {
6518    return this.isValid ? gregorianToOrdinal(this.c).ordinal : NaN;
6519  }
6520
6521  /**
6522   * Get the human readable short month name, such as 'Oct'.
6523   * Defaults to the system's locale if no locale has been specified
6524   * @example DateTime.local(2017, 10, 30).monthShort //=> Oct
6525   * @type {string}
6526   */
6527  get monthShort() {
6528    return this.isValid ? Info.months("short", {
6529      locObj: this.loc
6530    })[this.month - 1] : null;
6531  }
6532
6533  /**
6534   * Get the human readable long month name, such as 'October'.
6535   * Defaults to the system's locale if no locale has been specified
6536   * @example DateTime.local(2017, 10, 30).monthLong //=> October
6537   * @type {string}
6538   */
6539  get monthLong() {
6540    return this.isValid ? Info.months("long", {
6541      locObj: this.loc
6542    })[this.month - 1] : null;
6543  }
6544
6545  /**
6546   * Get the human readable short weekday, such as 'Mon'.
6547   * Defaults to the system's locale if no locale has been specified
6548   * @example DateTime.local(2017, 10, 30).weekdayShort //=> Mon
6549   * @type {string}
6550   */
6551  get weekdayShort() {
6552    return this.isValid ? Info.weekdays("short", {
6553      locObj: this.loc
6554    })[this.weekday - 1] : null;
6555  }
6556
6557  /**
6558   * Get the human readable long weekday, such as 'Monday'.
6559   * Defaults to the system's locale if no locale has been specified
6560   * @example DateTime.local(2017, 10, 30).weekdayLong //=> Monday
6561   * @type {string}
6562   */
6563  get weekdayLong() {
6564    return this.isValid ? Info.weekdays("long", {
6565      locObj: this.loc
6566    })[this.weekday - 1] : null;
6567  }
6568
6569  /**
6570   * Get the UTC offset of this DateTime in minutes
6571   * @example DateTime.now().offset //=> -240
6572   * @example DateTime.utc().offset //=> 0
6573   * @type {number}
6574   */
6575  get offset() {
6576    return this.isValid ? +this.o : NaN;
6577  }
6578
6579  /**
6580   * Get the short human name for the zone's current offset, for example "EST" or "EDT".
6581   * Defaults to the system's locale if no locale has been specified
6582   * @type {string}
6583   */
6584  get offsetNameShort() {
6585    if (this.isValid) {
6586      return this.zone.offsetName(this.ts, {
6587        format: "short",
6588        locale: this.locale
6589      });
6590    } else {
6591      return null;
6592    }
6593  }
6594
6595  /**
6596   * Get the long human name for the zone's current offset, for example "Eastern Standard Time" or "Eastern Daylight Time".
6597   * Defaults to the system's locale if no locale has been specified
6598   * @type {string}
6599   */
6600  get offsetNameLong() {
6601    if (this.isValid) {
6602      return this.zone.offsetName(this.ts, {
6603        format: "long",
6604        locale: this.locale
6605      });
6606    } else {
6607      return null;
6608    }
6609  }
6610
6611  /**
6612   * Get whether this zone's offset ever changes, as in a DST.
6613   * @type {boolean}
6614   */
6615  get isOffsetFixed() {
6616    return this.isValid ? this.zone.isUniversal : null;
6617  }
6618
6619  /**
6620   * Get whether the DateTime is in a DST.
6621   * @type {boolean}
6622   */
6623  get isInDST() {
6624    if (this.isOffsetFixed) {
6625      return false;
6626    } else {
6627      return this.offset > this.set({
6628        month: 1,
6629        day: 1
6630      }).offset || this.offset > this.set({
6631        month: 5
6632      }).offset;
6633    }
6634  }
6635
6636  /**
6637   * Get those DateTimes which have the same local time as this DateTime, but a different offset from UTC
6638   * in this DateTime's zone. During DST changes local time can be ambiguous, for example
6639   * `2023-10-29T02:30:00` in `Europe/Berlin` can have offset `+01:00` or `+02:00`.
6640   * This method will return both possible DateTimes if this DateTime's local time is ambiguous.
6641   * @returns {DateTime[]}
6642   */
6643  getPossibleOffsets() {
6644    if (!this.isValid || this.isOffsetFixed) {
6645      return [this];
6646    }
6647    const dayMs = 86400000;
6648    const minuteMs = 60000;
6649    const localTS = objToLocalTS(this.c);
6650    const oEarlier = this.zone.offset(localTS - dayMs);
6651    const oLater = this.zone.offset(localTS + dayMs);
6652    const o1 = this.zone.offset(localTS - oEarlier * minuteMs);
6653    const o2 = this.zone.offset(localTS - oLater * minuteMs);
6654    if (o1 === o2) {
6655      return [this];
6656    }
6657    const ts1 = localTS - o1 * minuteMs;
6658    const ts2 = localTS - o2 * minuteMs;
6659    const c1 = tsToObj(ts1, o1);
6660    const c2 = tsToObj(ts2, o2);
6661    if (c1.hour === c2.hour && c1.minute === c2.minute && c1.second === c2.second && c1.millisecond === c2.millisecond) {
6662      return [clone(this, {
6663        ts: ts1
6664      }), clone(this, {
6665        ts: ts2
6666      })];
6667    }
6668    return [this];
6669  }
6670
6671  /**
6672   * Returns true if this DateTime is in a leap year, false otherwise
6673   * @example DateTime.local(2016).isInLeapYear //=> true
6674   * @example DateTime.local(2013).isInLeapYear //=> false
6675   * @type {boolean}
6676   */
6677  get isInLeapYear() {
6678    return isLeapYear(this.year);
6679  }
6680
6681  /**
6682   * Returns the number of days in this DateTime's month
6683   * @example DateTime.local(2016, 2).daysInMonth //=> 29
6684   * @example DateTime.local(2016, 3).daysInMonth //=> 31
6685   * @type {number}
6686   */
6687  get daysInMonth() {
6688    return daysInMonth(this.year, this.month);
6689  }
6690
6691  /**
6692   * Returns the number of days in this DateTime's year
6693   * @example DateTime.local(2016).daysInYear //=> 366
6694   * @example DateTime.local(2013).daysInYear //=> 365
6695   * @type {number}
6696   */
6697  get daysInYear() {
6698    return this.isValid ? daysInYear(this.year) : NaN;
6699  }
6700
6701  /**
6702   * Returns the number of weeks in this DateTime's year
6703   * @see https://en.wikipedia.org/wiki/ISO_week_date
6704   * @example DateTime.local(2004).weeksInWeekYear //=> 53
6705   * @example DateTime.local(2013).weeksInWeekYear //=> 52
6706   * @type {number}
6707   */
6708  get weeksInWeekYear() {
6709    return this.isValid ? weeksInWeekYear(this.weekYear) : NaN;
6710  }
6711
6712  /**
6713   * Returns the number of weeks in this DateTime's local week year
6714   * @example DateTime.local(2020, 6, {locale: 'en-US'}).weeksInLocalWeekYear //=> 52
6715   * @example DateTime.local(2020, 6, {locale: 'de-DE'}).weeksInLocalWeekYear //=> 53
6716   * @type {number}
6717   */
6718  get weeksInLocalWeekYear() {
6719    return this.isValid ? weeksInWeekYear(this.localWeekYear, this.loc.getMinDaysInFirstWeek(), this.loc.getStartOfWeek()) : NaN;
6720  }
6721
6722  /**
6723   * Returns the resolved Intl options for this DateTime.
6724   * This is useful in understanding the behavior of formatting methods
6725   * @param {Object} opts - the same options as toLocaleString
6726   * @return {Object}
6727   */
6728  resolvedLocaleOptions(opts = {}) {
6729    const {
6730      locale,
6731      numberingSystem,
6732      calendar
6733    } = Formatter.create(this.loc.clone(opts), opts).resolvedOptions(this);
6734    return {
6735      locale,
6736      numberingSystem,
6737      outputCalendar: calendar
6738    };
6739  }
6740
6741  // TRANSFORM
6742
6743  /**
6744   * "Set" the DateTime's zone to UTC. Returns a newly-constructed DateTime.
6745   *
6746   * Equivalent to {@link DateTime#setZone}('utc')
6747   * @param {number} [offset=0] - optionally, an offset from UTC in minutes
6748   * @param {Object} [opts={}] - options to pass to `setZone()`
6749   * @return {DateTime}
6750   */
6751  toUTC(offset = 0, opts = {}) {
6752    return this.setZone(FixedOffsetZone.instance(offset), opts);
6753  }
6754
6755  /**
6756   * "Set" the DateTime's zone to the host's local zone. Returns a newly-constructed DateTime.
6757   *
6758   * Equivalent to `setZone('local')`
6759   * @return {DateTime}
6760   */
6761  toLocal() {
6762    return this.setZone(Settings.defaultZone);
6763  }
6764
6765  /**
6766   * "Set" the DateTime's zone to specified zone. Returns a newly-constructed DateTime.
6767   *
6768   * By default, the setter keeps the underlying time the same (as in, the same timestamp), but the new instance will report different local times and consider DSTs when making computations, as with {@link DateTime#plus}. You may wish to use {@link DateTime#toLocal} and {@link DateTime#toUTC} which provide simple convenience wrappers for commonly used zones.
6769   * @param {string|Zone} [zone='local'] - a zone identifier. As a string, that can be any IANA zone supported by the host environment, or a fixed-offset name of the form 'UTC+3', or the strings 'local' or 'utc'. You may also supply an instance of a {@link DateTime#Zone} class.
6770   * @param {Object} opts - options
6771   * @param {boolean} [opts.keepLocalTime=false] - If true, adjust the underlying time so that the local time stays the same, but in the target zone. You should rarely need this.
6772   * @return {DateTime}
6773   */
6774  setZone(zone, {
6775    keepLocalTime = false,
6776    keepCalendarTime = false
6777  } = {}) {
6778    zone = normalizeZone(zone, Settings.defaultZone);
6779    if (zone.equals(this.zone)) {
6780      return this;
6781    } else if (!zone.isValid) {
6782      return DateTime.invalid(unsupportedZone(zone));
6783    } else {
6784      let newTS = this.ts;
6785      if (keepLocalTime || keepCalendarTime) {
6786        const offsetGuess = zone.offset(this.ts);
6787        const asObj = this.toObject();
6788        [newTS] = objToTS(asObj, offsetGuess, zone);
6789      }
6790      return clone(this, {
6791        ts: newTS,
6792        zone
6793      });
6794    }
6795  }
6796
6797  /**
6798   * "Set" the locale, numberingSystem, or outputCalendar. Returns a newly-constructed DateTime.
6799   * @param {Object} properties - the properties to set
6800   * @example DateTime.local(2017, 5, 25).reconfigure({ locale: 'en-GB' })
6801   * @return {DateTime}
6802   */
6803  reconfigure({
6804    locale,
6805    numberingSystem,
6806    outputCalendar
6807  } = {}) {
6808    const loc = this.loc.clone({
6809      locale,
6810      numberingSystem,
6811      outputCalendar
6812    });
6813    return clone(this, {
6814      loc
6815    });
6816  }
6817
6818  /**
6819   * "Set" the locale. Returns a newly-constructed DateTime.
6820   * Just a convenient alias for reconfigure({ locale })
6821   * @example DateTime.local(2017, 5, 25).setLocale('en-GB')
6822   * @return {DateTime}
6823   */
6824  setLocale(locale) {
6825    return this.reconfigure({
6826      locale
6827    });
6828  }
6829
6830  /**
6831   * "Set" the values of specified units. Returns a newly-constructed DateTime.
6832   * You can only set units with this method; for "setting" metadata, see {@link DateTime#reconfigure} and {@link DateTime#setZone}.
6833   *
6834   * This method also supports setting locale-based week units, i.e. `localWeekday`, `localWeekNumber` and `localWeekYear`.
6835   * They cannot be mixed with ISO-week units like `weekday`.
6836   * @param {Object} values - a mapping of units to numbers
6837   * @example dt.set({ year: 2017 })
6838   * @example dt.set({ hour: 8, minute: 30 })
6839   * @example dt.set({ weekday: 5 })
6840   * @example dt.set({ year: 2005, ordinal: 234 })
6841   * @return {DateTime}
6842   */
6843  set(values) {
6844    if (!this.isValid) return this;
6845    const normalized = normalizeObject(values, normalizeUnitWithLocalWeeks);
6846    const {
6847      minDaysInFirstWeek,
6848      startOfWeek
6849    } = usesLocalWeekValues(normalized, this.loc);
6850    const settingWeekStuff = !isUndefined(normalized.weekYear) || !isUndefined(normalized.weekNumber) || !isUndefined(normalized.weekday),
6851      containsOrdinal = !isUndefined(normalized.ordinal),
6852      containsGregorYear = !isUndefined(normalized.year),
6853      containsGregorMD = !isUndefined(normalized.month) || !isUndefined(normalized.day),
6854      containsGregor = containsGregorYear || containsGregorMD,
6855      definiteWeekDef = normalized.weekYear || normalized.weekNumber;
6856    if ((containsGregor || containsOrdinal) && definiteWeekDef) {
6857      throw new ConflictingSpecificationError("Can't mix weekYear/weekNumber units with year/month/day or ordinals");
6858    }
6859    if (containsGregorMD && containsOrdinal) {
6860      throw new ConflictingSpecificationError("Can't mix ordinal dates with month/day");
6861    }
6862    let mixed;
6863    if (settingWeekStuff) {
6864      mixed = weekToGregorian({
6865        ...gregorianToWeek(this.c, minDaysInFirstWeek, startOfWeek),
6866        ...normalized
6867      }, minDaysInFirstWeek, startOfWeek);
6868    } else if (!isUndefined(normalized.ordinal)) {
6869      mixed = ordinalToGregorian({
6870        ...gregorianToOrdinal(this.c),
6871        ...normalized
6872      });
6873    } else {
6874      mixed = {
6875        ...this.toObject(),
6876        ...normalized
6877      };
6878
6879      // if we didn't set the day but we ended up on an overflow date,
6880      // use the last day of the right month
6881      if (isUndefined(normalized.day)) {
6882        mixed.day = Math.min(daysInMonth(mixed.year, mixed.month), mixed.day);
6883      }
6884    }
6885    const [ts, o] = objToTS(mixed, this.o, this.zone);
6886    return clone(this, {
6887      ts,
6888      o
6889    });
6890  }
6891
6892  /**
6893   * Add a period of time to this DateTime and return the resulting DateTime
6894   *
6895   * Adding hours, minutes, seconds, or milliseconds increases the timestamp by the right number of milliseconds. Adding days, months, or years shifts the calendar, accounting for DSTs and leap years along the way. Thus, `dt.plus({ hours: 24 })` may result in a different time than `dt.plus({ days: 1 })` if there's a DST shift in between.
6896   * @param {Duration|Object|number} duration - The amount to add. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject()
6897   * @example DateTime.now().plus(123) //~> in 123 milliseconds
6898   * @example DateTime.now().plus({ minutes: 15 }) //~> in 15 minutes
6899   * @example DateTime.now().plus({ days: 1 }) //~> this time tomorrow
6900   * @example DateTime.now().plus({ days: -1 }) //~> this time yesterday
6901   * @example DateTime.now().plus({ hours: 3, minutes: 13 }) //~> in 3 hr, 13 min
6902   * @example DateTime.now().plus(Duration.fromObject({ hours: 3, minutes: 13 })) //~> in 3 hr, 13 min
6903   * @return {DateTime}
6904   */
6905  plus(duration) {
6906    if (!this.isValid) return this;
6907    const dur = Duration.fromDurationLike(duration);
6908    return clone(this, adjustTime(this, dur));
6909  }
6910
6911  /**
6912   * Subtract a period of time to this DateTime and return the resulting DateTime
6913   * See {@link DateTime#plus}
6914   * @param {Duration|Object|number} duration - The amount to subtract. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject()
6915   @return {DateTime}
6916   */
6917  minus(duration) {
6918    if (!this.isValid) return this;
6919    const dur = Duration.fromDurationLike(duration).negate();
6920    return clone(this, adjustTime(this, dur));
6921  }
6922
6923  /**
6924   * "Set" this DateTime to the beginning of a unit of time.
6925   * @param {string} unit - The unit to go to the beginning of. Can be 'year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', or 'millisecond'.
6926   * @param {Object} opts - options
6927   * @param {boolean} [opts.useLocaleWeeks=false] - If true, use weeks based on the locale, i.e. use the locale-dependent start of the week
6928   * @example DateTime.local(2014, 3, 3).startOf('month').toISODate(); //=> '2014-03-01'
6929   * @example DateTime.local(2014, 3, 3).startOf('year').toISODate(); //=> '2014-01-01'
6930   * @example DateTime.local(2014, 3, 3).startOf('week').toISODate(); //=> '2014-03-03', weeks always start on Mondays
6931   * @example DateTime.local(2014, 3, 3, 5, 30).startOf('day').toISOTime(); //=> '00:00.000-05:00'
6932   * @example DateTime.local(2014, 3, 3, 5, 30).startOf('hour').toISOTime(); //=> '05:00:00.000-05:00'
6933   * @return {DateTime}
6934   */
6935  startOf(unit, {
6936    useLocaleWeeks = false
6937  } = {}) {
6938    if (!this.isValid) return this;
6939    const o = {},
6940      normalizedUnit = Duration.normalizeUnit(unit);
6941    switch (normalizedUnit) {
6942      case "years":
6943        o.month = 1;
6944      // falls through
6945      case "quarters":
6946      case "months":
6947        o.day = 1;
6948      // falls through
6949      case "weeks":
6950      case "days":
6951        o.hour = 0;
6952      // falls through
6953      case "hours":
6954        o.minute = 0;
6955      // falls through
6956      case "minutes":
6957        o.second = 0;
6958      // falls through
6959      case "seconds":
6960        o.millisecond = 0;
6961        break;
6962      // no default, invalid units throw in normalizeUnit()
6963    }
6964
6965    if (normalizedUnit === "weeks") {
6966      if (useLocaleWeeks) {
6967        const startOfWeek = this.loc.getStartOfWeek();
6968        const {
6969          weekday
6970        } = this;
6971        if (weekday < startOfWeek) {
6972          o.weekNumber = this.weekNumber - 1;
6973        }
6974        o.weekday = startOfWeek;
6975      } else {
6976        o.weekday = 1;
6977      }
6978    }
6979    if (normalizedUnit === "quarters") {
6980      const q = Math.ceil(this.month / 3);
6981      o.month = (q - 1) * 3 + 1;
6982    }
6983    return this.set(o);
6984  }
6985
6986  /**
6987   * "Set" this DateTime to the end (meaning the last millisecond) of a unit of time
6988   * @param {string} unit - The unit to go to the end of. Can be 'year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', or 'millisecond'.
6989   * @param {Object} opts - options
6990   * @param {boolean} [opts.useLocaleWeeks=false] - If true, use weeks based on the locale, i.e. use the locale-dependent start of the week
6991   * @example DateTime.local(2014, 3, 3).endOf('month').toISO(); //=> '2014-03-31T23:59:59.999-05:00'
6992   * @example DateTime.local(2014, 3, 3).endOf('year').toISO(); //=> '2014-12-31T23:59:59.999-05:00'
6993   * @example DateTime.local(2014, 3, 3).endOf('week').toISO(); // => '2014-03-09T23:59:59.999-05:00', weeks start on Mondays
6994   * @example DateTime.local(2014, 3, 3, 5, 30).endOf('day').toISO(); //=> '2014-03-03T23:59:59.999-05:00'
6995   * @example DateTime.local(2014, 3, 3, 5, 30).endOf('hour').toISO(); //=> '2014-03-03T05:59:59.999-05:00'
6996   * @return {DateTime}
6997   */
6998  endOf(unit, opts) {
6999    return this.isValid ? this.plus({
7000      [unit]: 1
7001    }).startOf(unit, opts).minus(1) : this;
7002  }
7003
7004  // OUTPUT
7005
7006  /**
7007   * Returns a string representation of this DateTime formatted according to the specified format string.
7008   * **You may not want this.** See {@link DateTime#toLocaleString} for a more flexible formatting tool. For a table of tokens and their interpretations, see [here](https://moment.github.io/luxon/#/formatting?id=table-of-tokens).
7009   * Defaults to en-US if no locale has been specified, regardless of the system's locale.
7010   * @param {string} fmt - the format string
7011   * @param {Object} opts - opts to override the configuration options on this DateTime
7012   * @example DateTime.now().toFormat('yyyy LLL dd') //=> '2017 Apr 22'
7013   * @example DateTime.now().setLocale('fr').toFormat('yyyy LLL dd') //=> '2017 avr. 22'
7014   * @example DateTime.now().toFormat('yyyy LLL dd', { locale: "fr" }) //=> '2017 avr. 22'
7015   * @example DateTime.now().toFormat("HH 'hours and' mm 'minutes'") //=> '20 hours and 55 minutes'
7016   * @return {string}
7017   */
7018  toFormat(fmt, opts = {}) {
7019    return this.isValid ? Formatter.create(this.loc.redefaultToEN(opts)).formatDateTimeFromString(this, fmt) : INVALID;
7020  }
7021
7022  /**
7023   * Returns a localized string representing this date. Accepts the same options as the Intl.DateTimeFormat constructor and any presets defined by Luxon, such as `DateTime.DATE_FULL` or `DateTime.TIME_SIMPLE`.
7024   * The exact behavior of this method is browser-specific, but in general it will return an appropriate representation
7025   * of the DateTime in the assigned locale.
7026   * Defaults to the system's locale if no locale has been specified
7027   * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
7028   * @param formatOpts {Object} - Intl.DateTimeFormat constructor options and configuration options
7029   * @param {Object} opts - opts to override the configuration options on this DateTime
7030   * @example DateTime.now().toLocaleString(); //=> 4/20/2017
7031   * @example DateTime.now().setLocale('en-gb').toLocaleString(); //=> '20/04/2017'
7032   * @example DateTime.now().toLocaleString(DateTime.DATE_FULL); //=> 'April 20, 2017'
7033   * @example DateTime.now().toLocaleString(DateTime.DATE_FULL, { locale: 'fr' }); //=> '28 août 2022'
7034   * @example DateTime.now().toLocaleString(DateTime.TIME_SIMPLE); //=> '11:32 AM'
7035   * @example DateTime.now().toLocaleString(DateTime.DATETIME_SHORT); //=> '4/20/2017, 11:32 AM'
7036   * @example DateTime.now().toLocaleString({ weekday: 'long', month: 'long', day: '2-digit' }); //=> 'Thursday, April 20'
7037   * @example DateTime.now().toLocaleString({ weekday: 'short', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }); //=> 'Thu, Apr 20, 11:27 AM'
7038   * @example DateTime.now().toLocaleString({ hour: '2-digit', minute: '2-digit', hourCycle: 'h23' }); //=> '11:32'
7039   * @return {string}
7040   */
7041  toLocaleString(formatOpts = DATE_SHORT, opts = {}) {
7042    return this.isValid ? Formatter.create(this.loc.clone(opts), formatOpts).formatDateTime(this) : INVALID;
7043  }
7044
7045  /**
7046   * Returns an array of format "parts", meaning individual tokens along with metadata. This is allows callers to post-process individual sections of the formatted output.
7047   * Defaults to the system's locale if no locale has been specified
7048   * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/formatToParts
7049   * @param opts {Object} - Intl.DateTimeFormat constructor options, same as `toLocaleString`.
7050   * @example DateTime.now().toLocaleParts(); //=> [
7051   *                                   //=>   { type: 'day', value: '25' },
7052   *                                   //=>   { type: 'literal', value: '/' },
7053   *                                   //=>   { type: 'month', value: '05' },
7054   *                                   //=>   { type: 'literal', value: '/' },
7055   *                                   //=>   { type: 'year', value: '1982' }
7056   *                                   //=> ]
7057   */
7058  toLocaleParts(opts = {}) {
7059    return this.isValid ? Formatter.create(this.loc.clone(opts), opts).formatDateTimeParts(this) : [];
7060  }
7061
7062  /**
7063   * Returns an ISO 8601-compliant string representation of this DateTime
7064   * @param {Object} opts - options
7065   * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0
7066   * @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0
7067   * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00'
7068   * @param {boolean} [opts.extendedZone=false] - add the time zone format extension
7069   * @param {string} [opts.format='extended'] - choose between the basic and extended format
7070   * @param {string} [opts.precision='milliseconds'] - truncate output to desired presicion: 'years', 'months', 'days', 'hours', 'minutes', 'seconds' or 'milliseconds'. When precision and suppressSeconds or suppressMilliseconds are used together, precision sets the maximum unit shown in the output, however seconds or milliseconds will still be suppressed if they are 0.
7071   * @example DateTime.utc(1983, 5, 25).toISO() //=> '1982-05-25T00:00:00.000Z'
7072   * @example DateTime.now().toISO() //=> '2017-04-22T20:47:05.335-04:00'
7073   * @example DateTime.now().toISO({ includeOffset: false }) //=> '2017-04-22T20:47:05.335'
7074   * @example DateTime.now().toISO({ format: 'basic' }) //=> '20170422T204705.335-0400'
7075   * @example DateTime.now().toISO({ precision: 'day' }) //=> '2017-04-22Z'
7076   * @example DateTime.now().toISO({ precision: 'minute' }) //=> '2017-04-22T20:47Z'
7077   * @return {string|null}
7078   */
7079  toISO({
7080    format = "extended",
7081    suppressSeconds = false,
7082    suppressMilliseconds = false,
7083    includeOffset = true,
7084    extendedZone = false,
7085    precision = "milliseconds"
7086  } = {}) {
7087    if (!this.isValid) {
7088      return null;
7089    }
7090    precision = normalizeUnit(precision);
7091    const ext = format === "extended";
7092    let c = toISODate(this, ext, precision);
7093    if (orderedUnits.indexOf(precision) >= 3) c += "T";
7094    c += toISOTime(this, ext, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision);
7095    return c;
7096  }
7097
7098  /**
7099   * Returns an ISO 8601-compliant string representation of this DateTime's date component
7100   * @param {Object} opts - options
7101   * @param {string} [opts.format='extended'] - choose between the basic and extended format
7102   * @param {string} [opts.precision='day'] - truncate output to desired precision: 'years', 'months', or 'days'.
7103   * @example DateTime.utc(1982, 5, 25).toISODate() //=> '1982-05-25'
7104   * @example DateTime.utc(1982, 5, 25).toISODate({ format: 'basic' }) //=> '19820525'
7105   * @example DateTime.utc(1982, 5, 25).toISODate({ precision: 'month' }) //=> '1982-05'
7106   * @return {string|null}
7107   */
7108  toISODate({
7109    format = "extended",
7110    precision = "day"
7111  } = {}) {
7112    if (!this.isValid) {
7113      return null;
7114    }
7115    return toISODate(this, format === "extended", normalizeUnit(precision));
7116  }
7117
7118  /**
7119   * Returns an ISO 8601-compliant string representation of this DateTime's week date
7120   * @example DateTime.utc(1982, 5, 25).toISOWeekDate() //=> '1982-W21-2'
7121   * @return {string}
7122   */
7123  toISOWeekDate() {
7124    return toTechFormat(this, "kkkk-'W'WW-c");
7125  }
7126
7127  /**
7128   * Returns an ISO 8601-compliant string representation of this DateTime's time component
7129   * @param {Object} opts - options
7130   * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0
7131   * @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0
7132   * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00'
7133   * @param {boolean} [opts.extendedZone=true] - add the time zone format extension
7134   * @param {boolean} [opts.includePrefix=false] - include the `T` prefix
7135   * @param {string} [opts.format='extended'] - choose between the basic and extended format
7136   * @param {string} [opts.precision='milliseconds'] - truncate output to desired presicion: 'hours', 'minutes', 'seconds' or 'milliseconds'. When precision and suppressSeconds or suppressMilliseconds are used together, precision sets the maximum unit shown in the output, however seconds or milliseconds will still be suppressed if they are 0.
7137   * @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime() //=> '07:34:19.361Z'
7138   * @example DateTime.utc().set({ hour: 7, minute: 34, seconds: 0, milliseconds: 0 }).toISOTime({ suppressSeconds: true }) //=> '07:34Z'
7139   * @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ format: 'basic' }) //=> '073419.361Z'
7140   * @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ includePrefix: true }) //=> 'T07:34:19.361Z'
7141   * @example DateTime.utc().set({ hour: 7, minute: 34, second: 56 }).toISOTime({ precision: 'minute' }) //=> '07:34Z'
7142   * @return {string}
7143   */
7144  toISOTime({
7145    suppressMilliseconds = false,
7146    suppressSeconds = false,
7147    includeOffset = true,
7148    includePrefix = false,
7149    extendedZone = false,
7150    format = "extended",
7151    precision = "milliseconds"
7152  } = {}) {
7153    if (!this.isValid) {
7154      return null;
7155    }
7156    precision = normalizeUnit(precision);
7157    let c = includePrefix && orderedUnits.indexOf(precision) >= 3 ? "T" : "";
7158    return c + toISOTime(this, format === "extended", suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision);
7159  }
7160
7161  /**
7162   * Returns an RFC 2822-compatible string representation of this DateTime
7163   * @example DateTime.utc(2014, 7, 13).toRFC2822() //=> 'Sun, 13 Jul 2014 00:00:00 +0000'
7164   * @example DateTime.local(2014, 7, 13).toRFC2822() //=> 'Sun, 13 Jul 2014 00:00:00 -0400'
7165   * @return {string}
7166   */
7167  toRFC2822() {
7168    return toTechFormat(this, "EEE, dd LLL yyyy HH:mm:ss ZZZ", false);
7169  }
7170
7171  /**
7172   * Returns a string representation of this DateTime appropriate for use in HTTP headers. The output is always expressed in GMT.
7173   * Specifically, the string conforms to RFC 1123.
7174   * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1
7175   * @example DateTime.utc(2014, 7, 13).toHTTP() //=> 'Sun, 13 Jul 2014 00:00:00 GMT'
7176   * @example DateTime.utc(2014, 7, 13, 19).toHTTP() //=> 'Sun, 13 Jul 2014 19:00:00 GMT'
7177   * @return {string}
7178   */
7179  toHTTP() {
7180    return toTechFormat(this.toUTC(), "EEE, dd LLL yyyy HH:mm:ss 'GMT'");
7181  }
7182
7183  /**
7184   * Returns a string representation of this DateTime appropriate for use in SQL Date
7185   * @example DateTime.utc(2014, 7, 13).toSQLDate() //=> '2014-07-13'
7186   * @return {string|null}
7187   */
7188  toSQLDate() {
7189    if (!this.isValid) {
7190      return null;
7191    }
7192    return toISODate(this, true);
7193  }
7194
7195  /**
7196   * Returns a string representation of this DateTime appropriate for use in SQL Time
7197   * @param {Object} opts - options
7198   * @param {boolean} [opts.includeZone=false] - include the zone, such as 'America/New_York'. Overrides includeOffset.
7199   * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00'
7200   * @param {boolean} [opts.includeOffsetSpace=true] - include the space between the time and the offset, such as '05:15:16.345 -04:00'
7201   * @example DateTime.utc().toSQL() //=> '05:15:16.345'
7202   * @example DateTime.now().toSQL() //=> '05:15:16.345 -04:00'
7203   * @example DateTime.now().toSQL({ includeOffset: false }) //=> '05:15:16.345'
7204   * @example DateTime.now().toSQL({ includeZone: false }) //=> '05:15:16.345 America/New_York'
7205   * @return {string}
7206   */
7207  toSQLTime({
7208    includeOffset = true,
7209    includeZone = false,
7210    includeOffsetSpace = true
7211  } = {}) {
7212    let fmt = "HH:mm:ss.SSS";
7213    if (includeZone || includeOffset) {
7214      if (includeOffsetSpace) {
7215        fmt += " ";
7216      }
7217      if (includeZone) {
7218        fmt += "z";
7219      } else if (includeOffset) {
7220        fmt += "ZZ";
7221      }
7222    }
7223    return toTechFormat(this, fmt, true);
7224  }
7225
7226  /**
7227   * Returns a string representation of this DateTime appropriate for use in SQL DateTime
7228   * @param {Object} opts - options
7229   * @param {boolean} [opts.includeZone=false] - include the zone, such as 'America/New_York'. Overrides includeOffset.
7230   * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00'
7231   * @param {boolean} [opts.includeOffsetSpace=true] - include the space between the time and the offset, such as '05:15:16.345 -04:00'
7232   * @example DateTime.utc(2014, 7, 13).toSQL() //=> '2014-07-13 00:00:00.000 Z'
7233   * @example DateTime.local(2014, 7, 13).toSQL() //=> '2014-07-13 00:00:00.000 -04:00'
7234   * @example DateTime.local(2014, 7, 13).toSQL({ includeOffset: false }) //=> '2014-07-13 00:00:00.000'
7235   * @example DateTime.local(2014, 7, 13).toSQL({ includeZone: true }) //=> '2014-07-13 00:00:00.000 America/New_York'
7236   * @return {string}
7237   */
7238  toSQL(opts = {}) {
7239    if (!this.isValid) {
7240      return null;
7241    }
7242    return `${this.toSQLDate()} ${this.toSQLTime(opts)}`;
7243  }
7244
7245  /**
7246   * Returns a string representation of this DateTime appropriate for debugging
7247   * @return {string}
7248   */
7249  toString() {
7250    return this.isValid ? this.toISO() : INVALID;
7251  }
7252
7253  /**
7254   * Returns a string representation of this DateTime appropriate for the REPL.
7255   * @return {string}
7256   */
7257  [Symbol.for("nodejs.util.inspect.custom")]() {
7258    if (this.isValid) {
7259      return `DateTime { ts: ${this.toISO()}, zone: ${this.zone.name}, locale: ${this.locale} }`;
7260    } else {
7261      return `DateTime { Invalid, reason: ${this.invalidReason} }`;
7262    }
7263  }
7264
7265  /**
7266   * Returns the epoch milliseconds of this DateTime. Alias of {@link DateTime#toMillis}
7267   * @return {number}
7268   */
7269  valueOf() {
7270    return this.toMillis();
7271  }
7272
7273  /**
7274   * Returns the epoch milliseconds of this DateTime.
7275   * @return {number}
7276   */
7277  toMillis() {
7278    return this.isValid ? this.ts : NaN;
7279  }
7280
7281  /**
7282   * Returns the epoch seconds (including milliseconds in the fractional part) of this DateTime.
7283   * @return {number}
7284   */
7285  toSeconds() {
7286    return this.isValid ? this.ts / 1000 : NaN;
7287  }
7288
7289  /**
7290   * Returns the epoch seconds (as a whole number) of this DateTime.
7291   * @return {number}
7292   */
7293  toUnixInteger() {
7294    return this.isValid ? Math.floor(this.ts / 1000) : NaN;
7295  }
7296
7297  /**
7298   * Returns an ISO 8601 representation of this DateTime appropriate for use in JSON.
7299   * @return {string}
7300   */
7301  toJSON() {
7302    return this.toISO();
7303  }
7304
7305  /**
7306   * Returns a BSON serializable equivalent to this DateTime.
7307   * @return {Date}
7308   */
7309  toBSON() {
7310    return this.toJSDate();
7311  }
7312
7313  /**
7314   * Returns a JavaScript object with this DateTime's year, month, day, and so on.
7315   * @param opts - options for generating the object
7316   * @param {boolean} [opts.includeConfig=false] - include configuration attributes in the output
7317   * @example DateTime.now().toObject() //=> { year: 2017, month: 4, day: 22, hour: 20, minute: 49, second: 42, millisecond: 268 }
7318   * @return {Object}
7319   */
7320  toObject(opts = {}) {
7321    if (!this.isValid) return {};
7322    const base = {
7323      ...this.c
7324    };
7325    if (opts.includeConfig) {
7326      base.outputCalendar = this.outputCalendar;
7327      base.numberingSystem = this.loc.numberingSystem;
7328      base.locale = this.loc.locale;
7329    }
7330    return base;
7331  }
7332
7333  /**
7334   * Returns a JavaScript Date equivalent to this DateTime.
7335   * @return {Date}
7336   */
7337  toJSDate() {
7338    return new Date(this.isValid ? this.ts : NaN);
7339  }
7340
7341  // COMPARE
7342
7343  /**
7344   * Return the difference between two DateTimes as a Duration.
7345   * @param {DateTime} otherDateTime - the DateTime to compare this one to
7346   * @param {string|string[]} [unit=['milliseconds']] - the unit or array of units (such as 'hours' or 'days') to include in the duration.
7347   * @param {Object} opts - options that affect the creation of the Duration
7348   * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use
7349   * @example
7350   * var i1 = DateTime.fromISO('1982-05-25T09:45'),
7351   *     i2 = DateTime.fromISO('1983-10-14T10:30');
7352   * i2.diff(i1).toObject() //=> { milliseconds: 43807500000 }
7353   * i2.diff(i1, 'hours').toObject() //=> { hours: 12168.75 }
7354   * i2.diff(i1, ['months', 'days']).toObject() //=> { months: 16, days: 19.03125 }
7355   * i2.diff(i1, ['months', 'days', 'hours']).toObject() //=> { months: 16, days: 19, hours: 0.75 }
7356   * @return {Duration}
7357   */
7358  diff(otherDateTime, unit = "milliseconds", opts = {}) {
7359    if (!this.isValid || !otherDateTime.isValid) {
7360      return Duration.invalid("created by diffing an invalid DateTime");
7361    }
7362    const durOpts = {
7363      locale: this.locale,
7364      numberingSystem: this.numberingSystem,
7365      ...opts
7366    };
7367    const units = maybeArray(unit).map(Duration.normalizeUnit),
7368      otherIsLater = otherDateTime.valueOf() > this.valueOf(),
7369      earlier = otherIsLater ? this : otherDateTime,
7370      later = otherIsLater ? otherDateTime : this,
7371      diffed = diff(earlier, later, units, durOpts);
7372    return otherIsLater ? diffed.negate() : diffed;
7373  }
7374
7375  /**
7376   * Return the difference between this DateTime and right now.
7377   * See {@link DateTime#diff}
7378   * @param {string|string[]} [unit=['milliseconds']] - the unit or units units (such as 'hours' or 'days') to include in the duration
7379   * @param {Object} opts - options that affect the creation of the Duration
7380   * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use
7381   * @return {Duration}
7382   */
7383  diffNow(unit = "milliseconds", opts = {}) {
7384    return this.diff(DateTime.now(), unit, opts);
7385  }
7386
7387  /**
7388   * Return an Interval spanning between this DateTime and another DateTime
7389   * @param {DateTime} otherDateTime - the other end point of the Interval
7390   * @return {Interval|DateTime}
7391   */
7392  until(otherDateTime) {
7393    return this.isValid ? Interval.fromDateTimes(this, otherDateTime) : this;
7394  }
7395
7396  /**
7397   * Return whether this DateTime is in the same unit of time as another DateTime.
7398   * Higher-order units must also be identical for this function to return `true`.
7399   * Note that time zones are **ignored** in this comparison, which compares the **local** calendar time. Use {@link DateTime#setZone} to convert one of the dates if needed.
7400   * @param {DateTime} otherDateTime - the other DateTime
7401   * @param {string} unit - the unit of time to check sameness on
7402   * @param {Object} opts - options
7403   * @param {boolean} [opts.useLocaleWeeks=false] - If true, use weeks based on the locale, i.e. use the locale-dependent start of the week; only the locale of this DateTime is used
7404   * @example DateTime.now().hasSame(otherDT, 'day'); //~> true if otherDT is in the same current calendar day
7405   * @return {boolean}
7406   */
7407  hasSame(otherDateTime, unit, opts) {
7408    if (!this.isValid) return false;
7409    const inputMs = otherDateTime.valueOf();
7410    const adjustedToZone = this.setZone(otherDateTime.zone, {
7411      keepLocalTime: true
7412    });
7413    return adjustedToZone.startOf(unit, opts) <= inputMs && inputMs <= adjustedToZone.endOf(unit, opts);
7414  }
7415
7416  /**
7417   * Equality check
7418   * Two DateTimes are equal if and only if they represent the same millisecond, have the same zone and location, and are both valid.
7419   * To compare just the millisecond values, use `+dt1 === +dt2`.
7420   * @param {DateTime} other - the other DateTime
7421   * @return {boolean}
7422   */
7423  equals(other) {
7424    return this.isValid && other.isValid && this.valueOf() === other.valueOf() && this.zone.equals(other.zone) && this.loc.equals(other.loc);
7425  }
7426
7427  /**
7428   * Returns a string representation of a this time relative to now, such as "in two days". Can only internationalize if your
7429   * platform supports Intl.RelativeTimeFormat. Rounds towards zero by default.
7430   * @param {Object} options - options that affect the output
7431   * @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now.
7432   * @param {string} [options.style="long"] - the style of units, must be "long", "short", or "narrow"
7433   * @param {string|string[]} options.unit - use a specific unit or array of units; if omitted, or an array, the method will pick the best unit. Use an array or one of "years", "quarters", "months", "weeks", "days", "hours", "minutes", or "seconds"
7434   * @param {boolean} [options.round=true] - whether to round the numbers in the output.
7435   * @param {string} [options.rounding="trunc"] - rounding method to use when rounding the numbers in the output. Can be "trunc" (toward zero), "expand" (away from zero), "round", "floor", or "ceil".
7436   * @param {number} [options.padding=0] - padding in milliseconds. This allows you to round up the result if it fits inside the threshold. Don't use in combination with {round: false} because the decimal output will include the padding.
7437   * @param {string} options.locale - override the locale of this DateTime
7438   * @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this
7439   * @example DateTime.now().plus({ days: 1 }).toRelative() //=> "in 1 day"
7440   * @example DateTime.now().setLocale("es").toRelative({ days: 1 }) //=> "dentro de 1 día"
7441   * @example DateTime.now().plus({ days: 1 }).toRelative({ locale: "fr" }) //=> "dans 23 heures"
7442   * @example DateTime.now().minus({ days: 2 }).toRelative() //=> "2 days ago"
7443   * @example DateTime.now().minus({ days: 2 }).toRelative({ unit: "hours" }) //=> "48 hours ago"
7444   * @example DateTime.now().minus({ hours: 36 }).toRelative({ round: false }) //=> "1.5 days ago"
7445   */
7446  toRelative(options = {}) {
7447    if (!this.isValid) return null;
7448    const base = options.base || DateTime.fromObject({}, {
7449        zone: this.zone
7450      }),
7451      padding = options.padding ? this < base ? -options.padding : options.padding : 0;
7452    let units = ["years", "months", "days", "hours", "minutes", "seconds"];
7453    let unit = options.unit;
7454    if (Array.isArray(options.unit)) {
7455      units = options.unit;
7456      unit = undefined;
7457    }
7458    return diffRelative(base, this.plus(padding), {
7459      ...options,
7460      numeric: "always",
7461      units,
7462      unit
7463    });
7464  }
7465
7466  /**
7467   * Returns a string representation of this date relative to today, such as "yesterday" or "next month".
7468   * Only internationalizes on platforms that supports Intl.RelativeTimeFormat.
7469   * @param {Object} options - options that affect the output
7470   * @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now.
7471   * @param {string} options.locale - override the locale of this DateTime
7472   * @param {string} options.unit - use a specific unit; if omitted, the method will pick the unit. Use one of "years", "quarters", "months", "weeks", or "days"
7473   * @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this
7474   * @example DateTime.now().plus({ days: 1 }).toRelativeCalendar() //=> "tomorrow"
7475   * @example DateTime.now().setLocale("es").plus({ days: 1 }).toRelative() //=> ""mañana"
7476   * @example DateTime.now().plus({ days: 1 }).toRelativeCalendar({ locale: "fr" }) //=> "demain"
7477   * @example DateTime.now().minus({ days: 2 }).toRelativeCalendar() //=> "2 days ago"
7478   */
7479  toRelativeCalendar(options = {}) {
7480    if (!this.isValid) return null;
7481    return diffRelative(options.base || DateTime.fromObject({}, {
7482      zone: this.zone
7483    }), this, {
7484      ...options,
7485      numeric: "auto",
7486      units: ["years", "months", "days"],
7487      calendary: true
7488    });
7489  }
7490
7491  /**
7492   * Return the min of several date times
7493   * @param {...DateTime} dateTimes - the DateTimes from which to choose the minimum
7494   * @return {DateTime} the min DateTime, or undefined if called with no argument
7495   */
7496  static min(...dateTimes) {
7497    if (!dateTimes.every(DateTime.isDateTime)) {
7498      throw new InvalidArgumentError("min requires all arguments be DateTimes");
7499    }
7500    return bestBy(dateTimes, i => i.valueOf(), Math.min);
7501  }
7502
7503  /**
7504   * Return the max of several date times
7505   * @param {...DateTime} dateTimes - the DateTimes from which to choose the maximum
7506   * @return {DateTime} the max DateTime, or undefined if called with no argument
7507   */
7508  static max(...dateTimes) {
7509    if (!dateTimes.every(DateTime.isDateTime)) {
7510      throw new InvalidArgumentError("max requires all arguments be DateTimes");
7511    }
7512    return bestBy(dateTimes, i => i.valueOf(), Math.max);
7513  }
7514
7515  // MISC
7516
7517  /**
7518   * Explain how a string would be parsed by fromFormat()
7519   * @param {string} text - the string to parse
7520   * @param {string} fmt - the format the string is expected to be in (see description)
7521   * @param {Object} options - options taken by fromFormat()
7522   * @return {Object}
7523   */
7524  static fromFormatExplain(text, fmt, options = {}) {
7525    const {
7526        locale = null,
7527        numberingSystem = null
7528      } = options,
7529      localeToUse = Locale.fromOpts({
7530        locale,
7531        numberingSystem,
7532        defaultToEN: true
7533      });
7534    return explainFromTokens(localeToUse, text, fmt);
7535  }
7536
7537  /**
7538   * @deprecated use fromFormatExplain instead
7539   */
7540  static fromStringExplain(text, fmt, options = {}) {
7541    return DateTime.fromFormatExplain(text, fmt, options);
7542  }
7543
7544  /**
7545   * Build a parser for `fmt` using the given locale. This parser can be passed
7546   * to {@link DateTime.fromFormatParser} to a parse a date in this format. This
7547   * can be used to optimize cases where many dates need to be parsed in a
7548   * specific format.
7549   *
7550   * @param {String} fmt - the format the string is expected to be in (see
7551   * description)
7552   * @param {Object} options - options used to set locale and numberingSystem
7553   * for parser
7554   * @returns {TokenParser} - opaque object to be used
7555   */
7556  static buildFormatParser(fmt, options = {}) {
7557    const {
7558        locale = null,
7559        numberingSystem = null
7560      } = options,
7561      localeToUse = Locale.fromOpts({
7562        locale,
7563        numberingSystem,
7564        defaultToEN: true
7565      });
7566    return new TokenParser(localeToUse, fmt);
7567  }
7568
7569  /**
7570   * Create a DateTime from an input string and format parser.
7571   *
7572   * The format parser must have been created with the same locale as this call.
7573   *
7574   * @param {String} text - the string to parse
7575   * @param {TokenParser} formatParser - parser from {@link DateTime.buildFormatParser}
7576   * @param {Object} opts - options taken by fromFormat()
7577   * @returns {DateTime}
7578   */
7579  static fromFormatParser(text, formatParser, opts = {}) {
7580    if (isUndefined(text) || isUndefined(formatParser)) {
7581      throw new InvalidArgumentError("fromFormatParser requires an input string and a format parser");
7582    }
7583    const {
7584        locale = null,
7585        numberingSystem = null
7586      } = opts,
7587      localeToUse = Locale.fromOpts({
7588        locale,
7589        numberingSystem,
7590        defaultToEN: true
7591      });
7592    if (!localeToUse.equals(formatParser.locale)) {
7593      throw new InvalidArgumentError(`fromFormatParser called with a locale of ${localeToUse}, ` + `but the format parser was created for ${formatParser.locale}`);
7594    }
7595    const {
7596      result,
7597      zone,
7598      specificOffset,
7599      invalidReason
7600    } = formatParser.explainFromTokens(text);
7601    if (invalidReason) {
7602      return DateTime.invalid(invalidReason);
7603    } else {
7604      return parseDataToDateTime(result, zone, opts, `format ${formatParser.format}`, text, specificOffset);
7605    }
7606  }
7607
7608  // FORMAT PRESETS
7609
7610  /**
7611   * {@link DateTime#toLocaleString} format like 10/14/1983
7612   * @type {Object}
7613   */
7614  static get DATE_SHORT() {
7615    return DATE_SHORT;
7616  }
7617
7618  /**
7619   * {@link DateTime#toLocaleString} format like 'Oct 14, 1983'
7620   * @type {Object}
7621   */
7622  static get DATE_MED() {
7623    return DATE_MED;
7624  }
7625
7626  /**
7627   * {@link DateTime#toLocaleString} format like 'Fri, Oct 14, 1983'
7628   * @type {Object}
7629   */
7630  static get DATE_MED_WITH_WEEKDAY() {
7631    return DATE_MED_WITH_WEEKDAY;
7632  }
7633
7634  /**
7635   * {@link DateTime#toLocaleString} format like 'October 14, 1983'
7636   * @type {Object}
7637   */
7638  static get DATE_FULL() {
7639    return DATE_FULL;
7640  }
7641
7642  /**
7643   * {@link DateTime#toLocaleString} format like 'Tuesday, October 14, 1983'
7644   * @type {Object}
7645   */
7646  static get DATE_HUGE() {
7647    return DATE_HUGE;
7648  }
7649
7650  /**
7651   * {@link DateTime#toLocaleString} format like '09:30 AM'. Only 12-hour if the locale is.
7652   * @type {Object}
7653   */
7654  static get TIME_SIMPLE() {
7655    return TIME_SIMPLE;
7656  }
7657
7658  /**
7659   * {@link DateTime#toLocaleString} format like '09:30:23 AM'. Only 12-hour if the locale is.
7660   * @type {Object}
7661   */
7662  static get TIME_WITH_SECONDS() {
7663    return TIME_WITH_SECONDS;
7664  }
7665
7666  /**
7667   * {@link DateTime#toLocaleString} format like '09:30:23 AM EDT'. Only 12-hour if the locale is.
7668   * @type {Object}
7669   */
7670  static get TIME_WITH_SHORT_OFFSET() {
7671    return TIME_WITH_SHORT_OFFSET;
7672  }
7673
7674  /**
7675   * {@link DateTime#toLocaleString} format like '09:30:23 AM Eastern Daylight Time'. Only 12-hour if the locale is.
7676   * @type {Object}
7677   */
7678  static get TIME_WITH_LONG_OFFSET() {
7679    return TIME_WITH_LONG_OFFSET;
7680  }
7681
7682  /**
7683   * {@link DateTime#toLocaleString} format like '09:30', always 24-hour.
7684   * @type {Object}
7685   */
7686  static get TIME_24_SIMPLE() {
7687    return TIME_24_SIMPLE;
7688  }
7689
7690  /**
7691   * {@link DateTime#toLocaleString} format like '09:30:23', always 24-hour.
7692   * @type {Object}
7693   */
7694  static get TIME_24_WITH_SECONDS() {
7695    return TIME_24_WITH_SECONDS;
7696  }
7697
7698  /**
7699   * {@link DateTime#toLocaleString} format like '09:30:23 EDT', always 24-hour.
7700   * @type {Object}
7701   */
7702  static get TIME_24_WITH_SHORT_OFFSET() {
7703    return TIME_24_WITH_SHORT_OFFSET;
7704  }
7705
7706  /**
7707   * {@link DateTime#toLocaleString} format like '09:30:23 Eastern Daylight Time', always 24-hour.
7708   * @type {Object}
7709   */
7710  static get TIME_24_WITH_LONG_OFFSET() {
7711    return TIME_24_WITH_LONG_OFFSET;
7712  }
7713
7714  /**
7715   * {@link DateTime#toLocaleString} format like '10/14/1983, 9:30 AM'. Only 12-hour if the locale is.
7716   * @type {Object}
7717   */
7718  static get DATETIME_SHORT() {
7719    return DATETIME_SHORT;
7720  }
7721
7722  /**
7723   * {@link DateTime#toLocaleString} format like '10/14/1983, 9:30:33 AM'. Only 12-hour if the locale is.
7724   * @type {Object}
7725   */
7726  static get DATETIME_SHORT_WITH_SECONDS() {
7727    return DATETIME_SHORT_WITH_SECONDS;
7728  }
7729
7730  /**
7731   * {@link DateTime#toLocaleString} format like 'Oct 14, 1983, 9:30 AM'. Only 12-hour if the locale is.
7732   * @type {Object}
7733   */
7734  static get DATETIME_MED() {
7735    return DATETIME_MED;
7736  }
7737
7738  /**
7739   * {@link DateTime#toLocaleString} format like 'Oct 14, 1983, 9:30:33 AM'. Only 12-hour if the locale is.
7740   * @type {Object}
7741   */
7742  static get DATETIME_MED_WITH_SECONDS() {
7743    return DATETIME_MED_WITH_SECONDS;
7744  }
7745
7746  /**
7747   * {@link DateTime#toLocaleString} format like 'Fri, 14 Oct 1983, 9:30 AM'. Only 12-hour if the locale is.
7748   * @type {Object}
7749   */
7750  static get DATETIME_MED_WITH_WEEKDAY() {
7751    return DATETIME_MED_WITH_WEEKDAY;
7752  }
7753
7754  /**
7755   * {@link DateTime#toLocaleString} format like 'October 14, 1983, 9:30 AM EDT'. Only 12-hour if the locale is.
7756   * @type {Object}
7757   */
7758  static get DATETIME_FULL() {
7759    return DATETIME_FULL;
7760  }
7761
7762  /**
7763   * {@link DateTime#toLocaleString} format like 'October 14, 1983, 9:30:33 AM EDT'. Only 12-hour if the locale is.
7764   * @type {Object}
7765   */
7766  static get DATETIME_FULL_WITH_SECONDS() {
7767    return DATETIME_FULL_WITH_SECONDS;
7768  }
7769
7770  /**
7771   * {@link DateTime#toLocaleString} format like 'Friday, October 14, 1983, 9:30 AM Eastern Daylight Time'. Only 12-hour if the locale is.
7772   * @type {Object}
7773   */
7774  static get DATETIME_HUGE() {
7775    return DATETIME_HUGE;
7776  }
7777
7778  /**
7779   * {@link DateTime#toLocaleString} format like 'Friday, October 14, 1983, 9:30:33 AM Eastern Daylight Time'. Only 12-hour if the locale is.
7780   * @type {Object}
7781   */
7782  static get DATETIME_HUGE_WITH_SECONDS() {
7783    return DATETIME_HUGE_WITH_SECONDS;
7784  }
7785}
7786
7787/**
7788 * @private
7789 */
7790function friendlyDateTime(dateTimeish) {
7791  if (DateTime.isDateTime(dateTimeish)) {
7792    return dateTimeish;
7793  } else if (dateTimeish && dateTimeish.valueOf && isNumber(dateTimeish.valueOf())) {
7794    return DateTime.fromJSDate(dateTimeish);
7795  } else if (dateTimeish && typeof dateTimeish === "object") {
7796    return DateTime.fromObject(dateTimeish);
7797  } else {
7798    throw new InvalidArgumentError(`Unknown datetime argument: ${dateTimeish}, of type ${typeof dateTimeish}`);
7799  }
7800}
7801
7802const VERSION = "3.7.2";
7803
7804exports.DateTime = DateTime;
7805exports.Duration = Duration;
7806exports.FixedOffsetZone = FixedOffsetZone;
7807exports.IANAZone = IANAZone;
7808exports.Info = Info;
7809exports.Interval = Interval;
7810exports.InvalidZone = InvalidZone;
7811exports.Settings = Settings;
7812exports.SystemZone = SystemZone;
7813exports.VERSION = VERSION;
7814exports.Zone = Zone;
7815//# sourceMappingURL=luxon.js.map
7816
7817
7818/***/ }
7819
7820}]);
7821//# sourceMappingURL=vendors-node_modules_luxon_build_node_luxon_js.95927b80.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.