@energycap/components 0.46.8 → 0.46.9-esm-luxon.20260514-2148

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,8 +16,8 @@ import { TranslateModule, TranslateService } from '@ngx-translate/core';
16
16
  import { ClipboardService } from 'ngx-clipboard';
17
17
  import { Subject, of, lastValueFrom, forkJoin, merge, fromEvent, EMPTY, timer, interval, race, ReplaySubject } from 'rxjs';
18
18
  import { takeUntil, switchMap, delay, distinctUntilChanged, filter, take, debounceTime, skipUntil, tap, pluck, map, catchError, skipWhile } from 'rxjs/operators';
19
- import moment from 'moment';
20
- import { range, cloneDeep, isEqual, uniqueId, sortBy, orderBy, get, upperFirst } from 'lodash';
19
+ import { DateTime, Info } from 'luxon';
20
+ import { range, cloneDeep, isEqual, uniqueId, sortBy, orderBy, get, upperFirst } from 'lodash-es';
21
21
  import { ComponentPortal, TemplatePortal } from '@angular/cdk/portal';
22
22
  import Popper from 'popper.js';
23
23
 
@@ -480,7 +480,7 @@ class DateTimeHelper {
480
480
  /** 3000-01-01 */
481
481
  static { this.endOfTime = new Date(3000, 0, 1); }
482
482
  /** 3000-01-01 UTC */
483
- static { this.endOfTimeUTC = moment.utc('3000-01-01').toDate(); }
483
+ static { this.endOfTimeUTC = DateTime.fromISO('3000-01-01', { zone: 'utc' }).toJSDate(); }
484
484
  /** Default effective date for new AccountMeter relationships: 2010-01-01 */
485
485
  static { this.defaultAccountMeterEffectiveDate = new Date(2010, 0, 1); }
486
486
  /** The default date that a newly created account becomes effective: 2010-01-01 */
@@ -522,20 +522,19 @@ class DateTimeHelper {
522
522
  "yyyyMMdd"
523
523
  ]; }
524
524
  /**
525
- * User input formats that we will parse into a date
526
- * when the users date format preference has month before day.
527
- * To be used with moment.js. Moment ignores non-alphanumeric characters
528
- * so dates like 2020/09/10 will be parsed the same as 2020-09-10
529
- */
530
- static { this.momentMonthFirstParseFormats = [
531
- 'M-D',
532
- 'MM-DD',
533
- 'M-D-YY',
534
- 'MM-DD-YY',
535
- 'MMDDYYYY',
536
- 'YYYYMMDD',
537
- 'YYYY-MM-DD',
538
- 'MM-DD-YYYY'
525
+ * Luxon parse formats for the month-first preference. Separator characters
526
+ * in the input are normalized to a hyphen before matching (see {@link parseWithFormats}),
527
+ * so the formats below intentionally use a single separator.
528
+ */
529
+ static { this.luxonMonthFirstParseFormats = [
530
+ 'M-d',
531
+ 'MM-dd',
532
+ 'M-d-yy',
533
+ 'MM-dd-yy',
534
+ 'MMddyyyy',
535
+ 'yyyyMMdd',
536
+ 'yyyy-MM-dd',
537
+ 'MM-dd-yyyy'
539
538
  ]; }
540
539
  /**
541
540
  * User input formats that we will parse into a date
@@ -559,44 +558,48 @@ class DateTimeHelper {
559
558
  "yyyyDDmm"
560
559
  ]; }
561
560
  /**
562
- * User input formats that we will parse into a date
563
- * when the users date format preference has day before month.
564
- * To be used with moment.js. Moment ignores non-alphanumeric characters
565
- * so dates like 2020/09/10 will be parsed the same as 2020-09-10
566
- */
567
- static { this.momentDateFirstParseFormats = [
568
- 'D-M',
569
- 'DD-MM',
570
- 'D-M-YY',
571
- 'DD-MM-YY',
572
- 'DDMMYYYY',
573
- 'YYYYMMDD',
574
- 'YYYY-MM-DD',
575
- 'DD-MM-YYYY'
561
+ * Luxon parse formats for the day-first preference. Separator characters
562
+ * in the input are normalized to a hyphen before matching (see {@link parseWithFormats}).
563
+ */
564
+ static { this.luxonDateFirstParseFormats = [
565
+ 'd-M',
566
+ 'dd-MM',
567
+ 'd-M-yy',
568
+ 'dd-MM-yy',
569
+ 'ddMMyyyy',
570
+ 'yyyyMMdd',
571
+ 'yyyy-MM-dd',
572
+ 'dd-MM-yyyy'
576
573
  ]; }
577
574
  /**
578
- * Formats used to parse dates that are in the medium or long format by moment js.
579
- * These are shared by date-first and month-first date formats. The date can't be
580
- * parsed differently based on the date preference since the month is not numeric.
581
- * This is not an exhaustive list of formats, but it should cover most common formats.
582
- */
583
- static { this.momentMedAndLongDateFormats = [
584
- 'DD MMM',
585
- 'MMM DD',
586
- 'DD MMM YY',
587
- 'DD MMM YYYY',
588
- 'DD MMMM YYYY',
589
- 'MMM D, YY',
590
- 'MMM D, YYYY',
591
- 'MMM DD, YYYY',
592
- 'MMMM D, YYYY',
593
- 'MMMM DD, YYYY',
594
- 'MMM YY',
595
- 'MMM YYYY',
596
- 'MMMM YYYY',
597
- 'MMM, YY',
598
- 'MMM, YYYY',
599
- 'MMMM, YYYY',
575
+ * Luxon parse formats for medium/long date strings (e.g. "Jan 5, 2024").
576
+ * Shared by date-first and month-first preferences because the month is
577
+ * not numeric, so the order is unambiguous.
578
+ */
579
+ static { this.luxonMedAndLongDateFormats = [
580
+ // Moment was forgiving with leading zeros (`DD` matched both `9` and `09`);
581
+ // Luxon's `dd` is strict, so single-digit `d` variants are listed explicitly.
582
+ 'd MMM',
583
+ 'dd MMM',
584
+ 'MMM d',
585
+ 'MMM dd',
586
+ 'd MMM yy',
587
+ 'dd MMM yy',
588
+ 'd MMM yyyy',
589
+ 'dd MMM yyyy',
590
+ 'd MMMM yyyy',
591
+ 'dd MMMM yyyy',
592
+ 'MMM d, yy',
593
+ 'MMM d, yyyy',
594
+ 'MMM dd, yyyy',
595
+ 'MMMM d, yyyy',
596
+ 'MMMM dd, yyyy',
597
+ 'MMM yy',
598
+ 'MMM yyyy',
599
+ 'MMMM yyyy',
600
+ 'MMM, yy',
601
+ 'MMM, yyyy',
602
+ 'MMMM, yyyy',
600
603
  ]; }
601
604
  /**
602
605
  * Format to display the time portion of a datetime
@@ -605,6 +608,99 @@ class DateTimeHelper {
605
608
  ///////////////////////////////////////////////////////
606
609
  // METHODS
607
610
  ///////////////////////////////////////////////////////
611
+ /**
612
+ * Convert any date-like value into a Luxon {@link DateTime}. Strings are parsed
613
+ * as ISO 8601; numbers are treated as epoch milliseconds. Returns an invalid
614
+ * DateTime when the input is null/undefined.
615
+ */
616
+ static toDateTime(value) {
617
+ if (value === null || value === undefined) {
618
+ return DateTime.invalid('null or undefined');
619
+ }
620
+ if (DateTime.isDateTime(value)) {
621
+ return value;
622
+ }
623
+ if (value instanceof Date) {
624
+ return DateTime.fromJSDate(value);
625
+ }
626
+ if (typeof value === 'number') {
627
+ return DateTime.fromMillis(value);
628
+ }
629
+ return DateTime.fromISO(value);
630
+ }
631
+ /**
632
+ * Translate a moment-style format string (e.g. `MM/DD/YYYY HH:mm:ss A`) into
633
+ * the Luxon equivalent (`MM/dd/yyyy HH:mm:ss a`). Use this when format strings
634
+ * originate from external sources (such as user preferences) that still use
635
+ * moment tokens.
636
+ *
637
+ * Only the tokens currently in use across this library are translated:
638
+ * `Y`→`y`, `D`→`d`, `A`→`a`. `M`, `H`, `h`, `m`, `s` are identical between
639
+ * the two libraries.
640
+ */
641
+ static momentToLuxonFormat(format) {
642
+ return format
643
+ .replace(/Y/g, 'y')
644
+ .replace(/D/g, 'd')
645
+ .replace(/A/g, 'a');
646
+ }
647
+ /**
648
+ * Format a date-like value using a moment-style format string. The format
649
+ * string is automatically translated to Luxon tokens, so callers can keep
650
+ * passing the same preference strings (e.g. `MM/DD/YYYY HH:mm:ss`).
651
+ *
652
+ * When `displayInUTC` is true, string inputs without zone info are parsed
653
+ * as UTC (matching `moment.utc(str)`), and all other inputs are shifted to
654
+ * the UTC zone for display. Returns an empty string for invalid input.
655
+ *
656
+ * Moment's lowercase `a` token produces lowercase `am`/`pm`, but Luxon's
657
+ * `a` is locale-aware and emits uppercase `AM`/`PM` in en-US. When the
658
+ * incoming format uses lowercase `a` (and not uppercase `A`), the meridiem
659
+ * in the output is lowercased to preserve the moment contract for user
660
+ * preferences like `h:mm:ss a` that are stored externally.
661
+ */
662
+ static formatDate(date, momentFormat, displayInUTC = false) {
663
+ let dt;
664
+ if (displayInUTC && typeof date === 'string') {
665
+ dt = DateTime.fromISO(date, { zone: 'utc' });
666
+ }
667
+ else {
668
+ dt = this.toDateTime(date);
669
+ if (displayInUTC) {
670
+ dt = dt.setZone('utc');
671
+ }
672
+ }
673
+ if (!dt.isValid)
674
+ return '';
675
+ let result = dt.toFormat(this.momentToLuxonFormat(momentFormat));
676
+ if (momentFormat.includes('a') && !momentFormat.includes('A')) {
677
+ result = result.replace(/AM|PM/g, m => m.toLowerCase());
678
+ }
679
+ return result;
680
+ }
681
+ /**
682
+ * Parse a string against a list of format patterns. Returns the first
683
+ * successful parse as a {@link DateTime} (which may be invalid if none match).
684
+ *
685
+ * Format strings may use either Luxon or moment tokens — each pattern is
686
+ * run through {@link momentToLuxonFormat} before matching, so callers can
687
+ * keep passing arrays like `['M/D/YYYY']` from previously moment-based code.
688
+ *
689
+ * Mirrors moment's behavior of ignoring separator characters by normalizing
690
+ * `/`, `.` and `-` in both input and patterns before matching.
691
+ */
692
+ static parseWithFormats(value, formats) {
693
+ const normalize = (s) => s.replace(/[\/.\-]/g, '-');
694
+ const normalizedValue = normalize(value);
695
+ for (const format of formats) {
696
+ const luxonFormat = this.momentToLuxonFormat(format);
697
+ const dt = DateTime.fromFormat(normalizedValue, normalize(luxonFormat));
698
+ if (dt.isValid) {
699
+ return dt;
700
+ }
701
+ }
702
+ return DateTime.invalid('no matching format');
703
+ }
608
704
  /**
609
705
  * Return true if @see date is equal to the @see endOfTime
610
706
  */
@@ -616,7 +712,7 @@ class DateTimeHelper {
616
712
  * Compare two dates and return true if they represent the same year, month, and day (time is ignored).
617
713
  */
618
714
  static isSameDay(date1, date2) {
619
- return moment(date1).isSame(moment(date2), 'day');
715
+ return this.toDateTime(date1).hasSame(this.toDateTime(date2), 'day');
620
716
  }
621
717
  /**
622
718
  * Get the parse formats based on the given date format. If no date format is
@@ -635,19 +731,19 @@ class DateTimeHelper {
635
731
  return dateFormat ? map[dateFormat] : this.monthFirstParseFormats;
636
732
  }
637
733
  /**
638
- * Get the moment parse formats based on the given date format. If no date format is
734
+ * Get the Luxon parse formats based on the given date format. If no date format is
639
735
  * given, or we don't recognize the format, return the month first parse formats.
640
736
  */
641
- static getMomentParseFormats(dateFormat) {
737
+ static getLuxonParseFormats(dateFormat) {
642
738
  let map = {
643
- 'MM/DD/YYYY': [...this.momentMonthFirstParseFormats, ...this.momentMedAndLongDateFormats],
644
- 'MM-DD-YYYY': [...this.momentMonthFirstParseFormats, ...this.momentMedAndLongDateFormats],
645
- 'DD/MM/YYYY': [...this.momentDateFirstParseFormats, ...this.momentMedAndLongDateFormats],
646
- 'DD-MM-YYYY': [...this.momentDateFirstParseFormats, ...this.momentMedAndLongDateFormats],
647
- 'YYYY/MM/DD': [...this.momentMonthFirstParseFormats, ...this.momentMedAndLongDateFormats],
648
- 'YYYY-MM-DD': [...this.momentMonthFirstParseFormats, ...this.momentMedAndLongDateFormats]
739
+ 'MM/DD/YYYY': [...this.luxonMonthFirstParseFormats, ...this.luxonMedAndLongDateFormats],
740
+ 'MM-DD-YYYY': [...this.luxonMonthFirstParseFormats, ...this.luxonMedAndLongDateFormats],
741
+ 'DD/MM/YYYY': [...this.luxonDateFirstParseFormats, ...this.luxonMedAndLongDateFormats],
742
+ 'DD-MM-YYYY': [...this.luxonDateFirstParseFormats, ...this.luxonMedAndLongDateFormats],
743
+ 'YYYY/MM/DD': [...this.luxonMonthFirstParseFormats, ...this.luxonMedAndLongDateFormats],
744
+ 'YYYY-MM-DD': [...this.luxonMonthFirstParseFormats, ...this.luxonMedAndLongDateFormats]
649
745
  };
650
- return dateFormat ? map[dateFormat] : this.momentMonthFirstParseFormats;
746
+ return dateFormat ? map[dateFormat] : this.luxonMonthFirstParseFormats;
651
747
  }
652
748
  /**
653
749
  * Get relationship start date (favoring date in partialFormState if exists)
@@ -670,28 +766,23 @@ class DateTimeHelper {
670
766
  return null;
671
767
  }
672
768
  static isDateBetween(date, startDate, endDate, includeStart, includeEnd) {
673
- let inclusivity = '()';
674
- if (includeStart && includeEnd) {
675
- inclusivity = '[]';
676
- }
677
- else if (includeStart) {
678
- inclusivity = '[)';
679
- }
680
- else if (includeEnd) {
681
- inclusivity = '(]';
682
- }
683
769
  // If a start date is not provide, we'll use our beginning of time instead
684
770
  startDate = startDate || this.beginningOfTime;
685
771
  // If an end date is not provided, we'll use our end of time instead
686
772
  endDate = endDate || this.endOfTime;
687
- return moment(date).isBetween(startDate, endDate, 'day', inclusivity);
773
+ const d = this.toDateTime(date).startOf('day');
774
+ const s = this.toDateTime(startDate).startOf('day');
775
+ const e = this.toDateTime(endDate).startOf('day');
776
+ const afterStart = includeStart ? d >= s : d > s;
777
+ const beforeEnd = includeEnd ? d <= e : d < e;
778
+ return afterStart && beforeEnd;
688
779
  }
689
780
  static stringToDate(dateString) {
690
781
  if (dateString === null || dateString === undefined) {
691
782
  return dateString;
692
783
  }
693
784
  else {
694
- return moment(dateString).toDate();
785
+ return DateTime.fromISO(dateString).toJSDate();
695
786
  }
696
787
  }
697
788
  }
@@ -705,15 +796,15 @@ class DateInputSelectionStrategyBase {
705
796
  if (!value) {
706
797
  return null;
707
798
  }
708
- const date = moment(value, parseFormats);
709
- if (date.isValid()) {
799
+ let date = DateTimeHelper.parseWithFormats(value, parseFormats);
800
+ if (date.isValid) {
710
801
  // If we're in a temporary state (when the user is typing in a textbox), we need to set the year to the current year if it's before the min year
711
802
  // This prevents the calendars from showing unhelpful dates that are in the distant past before the user finishes typing in the date.
712
803
  // We don't do this modification when the real selection happens on textbox blur.
713
- if (opts?.shiftToCurrentYearIfBelow && date.isBefore(opts.shiftToCurrentYearIfBelow)) {
714
- date.set('year', moment().year());
804
+ if (opts?.shiftToCurrentYearIfBelow && date < DateTime.fromJSDate(opts.shiftToCurrentYearIfBelow)) {
805
+ date = date.set({ year: DateTime.now().year });
715
806
  }
716
- return date.toDate();
807
+ return date.toJSDate();
717
808
  }
718
809
  return null;
719
810
  }
@@ -795,7 +886,7 @@ class DaySelectionStrategy extends DateInputSelectionStrategyBase {
795
886
  getNextSelection(selection) {
796
887
  // Add a single day to the selection
797
888
  if (DateInput.isSelectionSingleDate(selection)) {
798
- return moment(selection).add(1, 'day').toDate();
889
+ return DateTime.fromJSDate(selection).plus({ days: 1 }).toJSDate();
799
890
  }
800
891
  // This shouldn't happen based on current date input flows, but if it does just return the selection as-is.
801
892
  return selection;
@@ -803,7 +894,7 @@ class DaySelectionStrategy extends DateInputSelectionStrategyBase {
803
894
  getPreviousSelection(selection) {
804
895
  // Subtract a single day from the selection
805
896
  if (DateInput.isSelectionSingleDate(selection)) {
806
- return moment(selection).subtract(1, 'day').toDate();
897
+ return DateTime.fromJSDate(selection).minus({ days: 1 }).toJSDate();
807
898
  }
808
899
  // This shouldn't happen based on current date input flows, but if it does just return the selection as-is.
809
900
  return selection;
@@ -834,19 +925,19 @@ class Last28DaysSelectionStrategy extends DateInputSelectionStrategyBase {
834
925
  // Update the start and end dates to match a 28-day range, keying off the end date if parseFromEnd is true
835
926
  // parseFromEnd is true when a date is being entered from the end date textbox
836
927
  if (opts?.parseFromEnd) {
837
- start = moment(end).subtract(27, 'days').toDate();
928
+ start = DateTime.fromJSDate(end).minus({ days: 27 }).toJSDate();
838
929
  }
839
930
  else {
840
- end = moment(start).add(27, 'days').toDate();
931
+ end = DateTime.fromJSDate(start).plus({ days: 27 }).toJSDate();
841
932
  }
842
933
  }
843
934
  // If the start date is not provided, we'll use the end date to calculate the start date
844
935
  if (!start && end && !opts?.preventAutoComplete) {
845
- start = moment(end).subtract(27, 'days').toDate();
936
+ start = DateTime.fromJSDate(end).minus({ days: 27 }).toJSDate();
846
937
  }
847
938
  // If the end date is not provided, we'll use the start date to calculate the end date
848
939
  if (!end && start && !opts?.preventAutoComplete) {
849
- end = moment(start).add(27, 'days').toDate();
940
+ end = DateTime.fromJSDate(start).plus({ days: 27 }).toJSDate();
850
941
  }
851
942
  if (!start && !end) {
852
943
  return null;
@@ -857,7 +948,7 @@ class Last28DaysSelectionStrategy extends DateInputSelectionStrategyBase {
857
948
  }
858
949
  getSelectionFromDate(date) {
859
950
  return {
860
- start: moment(date).subtract(27, 'days').toDate(),
951
+ start: DateTime.fromJSDate(date).minus({ days: 27 }).toJSDate(),
861
952
  end: date
862
953
  };
863
954
  }
@@ -867,7 +958,7 @@ class Last28DaysSelectionStrategy extends DateInputSelectionStrategyBase {
867
958
  if (!previousSelection.end && previousSelection.start) {
868
959
  return {
869
960
  start: previousSelection.start,
870
- end: moment(previousSelection.start).add(27, 'days').toDate()
961
+ end: DateTime.fromJSDate(previousSelection.start).plus({ days: 27 }).toJSDate()
871
962
  };
872
963
  // If the range only has an end date, make the 28-day range end on that date
873
964
  }
@@ -884,9 +975,10 @@ class Last28DaysSelectionStrategy extends DateInputSelectionStrategyBase {
884
975
  getNextSelection(selection) {
885
976
  // Move the selection to the next 28 days
886
977
  if (DateInput.isSelectionRange(selection) && selection.end) {
978
+ const end = DateTime.fromJSDate(selection.end);
887
979
  return {
888
- start: moment(selection.end).add(1, 'day').toDate(),
889
- end: moment(selection.end).add(28, 'days').toDate()
980
+ start: end.plus({ days: 1 }).toJSDate(),
981
+ end: end.plus({ days: 28 }).toJSDate()
890
982
  };
891
983
  }
892
984
  // This shouldn't happen since the next stepper is disabled if the selection only has one date.
@@ -896,9 +988,10 @@ class Last28DaysSelectionStrategy extends DateInputSelectionStrategyBase {
896
988
  getPreviousSelection(selection) {
897
989
  // Move the selection to the previous 28 days
898
990
  if (DateInput.isSelectionRange(selection) && selection.start) {
991
+ const start = DateTime.fromJSDate(selection.start);
899
992
  return {
900
- start: moment(selection.start).subtract(28, 'days').toDate(),
901
- end: moment(selection.start).subtract(1, 'day').toDate()
993
+ start: start.minus({ days: 28 }).toJSDate(),
994
+ end: start.minus({ days: 1 }).toJSDate()
902
995
  };
903
996
  }
904
997
  // This shouldn't happen since the previous stepper is disabled if the selection only has one date.
@@ -931,19 +1024,19 @@ class Last7DaysSelectionStrategy extends DateInputSelectionStrategyBase {
931
1024
  // Update the start and end dates to match a 7-day range, keying off the end date if parseFromEnd is true
932
1025
  // parseFromEnd is true when a date is being entered from the end date textbox
933
1026
  if (opts?.parseFromEnd) {
934
- start = moment(end).subtract(6, 'days').toDate();
1027
+ start = DateTime.fromJSDate(end).minus({ days: 6 }).toJSDate();
935
1028
  }
936
1029
  else {
937
- end = moment(start).add(6, 'days').toDate();
1030
+ end = DateTime.fromJSDate(start).plus({ days: 6 }).toJSDate();
938
1031
  }
939
1032
  }
940
1033
  // If the start date is not provided, we'll use the end date to calculate the start date
941
1034
  if (!start && end && !opts?.preventAutoComplete) {
942
- start = moment(end).subtract(6, 'days').toDate();
1035
+ start = DateTime.fromJSDate(end).minus({ days: 6 }).toJSDate();
943
1036
  }
944
1037
  // If the end date is not provided, we'll use the start date to calculate the end date
945
1038
  if (!end && start && !opts?.preventAutoComplete) {
946
- end = moment(start).add(6, 'days').toDate();
1039
+ end = DateTime.fromJSDate(start).plus({ days: 6 }).toJSDate();
947
1040
  }
948
1041
  if (!start && !end) {
949
1042
  return null;
@@ -955,7 +1048,7 @@ class Last7DaysSelectionStrategy extends DateInputSelectionStrategyBase {
955
1048
  getSelectionFromDate(date) {
956
1049
  // Base the selection on the given date, moving back 6 days
957
1050
  return {
958
- start: moment(date).subtract(6, 'days').toDate(),
1051
+ start: DateTime.fromJSDate(date).minus({ days: 6 }).toJSDate(),
959
1052
  end: date
960
1053
  };
961
1054
  }
@@ -965,7 +1058,7 @@ class Last7DaysSelectionStrategy extends DateInputSelectionStrategyBase {
965
1058
  if (!previousSelection.end && previousSelection.start) {
966
1059
  return {
967
1060
  start: previousSelection.start,
968
- end: moment(previousSelection.start).add(6, 'days').toDate()
1061
+ end: DateTime.fromJSDate(previousSelection.start).plus({ days: 6 }).toJSDate()
969
1062
  };
970
1063
  // Otherwise, create the new selection based on the end date backwards
971
1064
  }
@@ -982,9 +1075,10 @@ class Last7DaysSelectionStrategy extends DateInputSelectionStrategyBase {
982
1075
  getNextSelection(selection) {
983
1076
  // Shift the range forward by 7 days
984
1077
  if (DateInput.isSelectionRange(selection) && selection.end) {
1078
+ const end = DateTime.fromJSDate(selection.end);
985
1079
  return {
986
- start: moment(selection.end).add(1, 'day').toDate(),
987
- end: moment(selection.end).add(7, 'days').toDate()
1080
+ start: end.plus({ days: 1 }).toJSDate(),
1081
+ end: end.plus({ days: 7 }).toJSDate()
988
1082
  };
989
1083
  }
990
1084
  // This shouldn't happen since the next stepper is disabled if the selection only has one date.
@@ -994,9 +1088,10 @@ class Last7DaysSelectionStrategy extends DateInputSelectionStrategyBase {
994
1088
  getPreviousSelection(selection) {
995
1089
  // Shift the range back 7 days
996
1090
  if (DateInput.isSelectionRange(selection) && selection.start) {
1091
+ const start = DateTime.fromJSDate(selection.start);
997
1092
  return {
998
- start: moment(selection.start).subtract(7, 'days').toDate(),
999
- end: moment(selection.start).subtract(1, 'day').toDate()
1093
+ start: start.minus({ days: 7 }).toJSDate(),
1094
+ end: start.minus({ days: 1 }).toJSDate()
1000
1095
  };
1001
1096
  }
1002
1097
  // This shouldn't happen since the previous stepper is disabled if the selection only has one date.
@@ -1024,7 +1119,7 @@ class MonthSelectionStrategy extends DateInputSelectionStrategyBase {
1024
1119
  // A single date selection shouldn't happen in this mode but it's simple enough to handle
1025
1120
  const date = DateInput.isSelectionRange(selection) ? selection.start : selection;
1026
1121
  return {
1027
- textbox: moment(date).format('MMM, YYYY'),
1122
+ textbox: date ? DateTime.fromJSDate(date).toFormat('MMM, yyyy') : null,
1028
1123
  textbox2: null
1029
1124
  };
1030
1125
  }
@@ -1037,9 +1132,10 @@ class MonthSelectionStrategy extends DateInputSelectionStrategyBase {
1037
1132
  return this.getSelectionFromDate(date);
1038
1133
  }
1039
1134
  getSelectionFromDate(date) {
1135
+ const dt = DateTime.fromJSDate(date);
1040
1136
  return {
1041
- start: moment(date).startOf('month').toDate(),
1042
- end: moment(date).endOf('month').toDate()
1137
+ start: dt.startOf('month').toJSDate(),
1138
+ end: dt.endOf('month').toJSDate()
1043
1139
  };
1044
1140
  }
1045
1141
  getNewSelectionFromExisting(previousSelection) {
@@ -1059,8 +1155,8 @@ class MonthSelectionStrategy extends DateInputSelectionStrategyBase {
1059
1155
  getNextSelection(selection) {
1060
1156
  // Move the selection to the next month
1061
1157
  if (DateInput.isSelectionRange(selection) && selection.start) {
1062
- const date = moment(selection.start).add(1, 'month');
1063
- return this.getSelectionFromDate(date.toDate());
1158
+ const date = DateTime.fromJSDate(selection.start).plus({ months: 1 });
1159
+ return this.getSelectionFromDate(date.toJSDate());
1064
1160
  }
1065
1161
  // This shouldn't happen since the next stepper is disabled if the selection only has one date.
1066
1162
  // If it does, just return the selection as-is.
@@ -1069,8 +1165,8 @@ class MonthSelectionStrategy extends DateInputSelectionStrategyBase {
1069
1165
  getPreviousSelection(selection) {
1070
1166
  // Move the selection to the previous month
1071
1167
  if (DateInput.isSelectionRange(selection) && selection.start) {
1072
- const date = moment(selection.start).subtract(1, 'month');
1073
- return this.getSelectionFromDate(date.toDate());
1168
+ const date = DateTime.fromJSDate(selection.start).minus({ months: 1 });
1169
+ return this.getSelectionFromDate(date.toJSDate());
1074
1170
  }
1075
1171
  // This shouldn't happen since the previous stepper is disabled if the selection only has one date.
1076
1172
  // If it does, just return the selection as-is.
@@ -1093,9 +1189,9 @@ class QuarterSelectionStrategy extends DateInputSelectionStrategyBase {
1093
1189
  // Format the the quarter range as "MMM–MMM, YYYY"
1094
1190
  // We only have one textbox in this mode
1095
1191
  if (DateInput.isSelectionRange(selection)) {
1096
- const start = moment(selection.start).format('MMM');
1097
- const end = moment(selection.end).format('MMM');
1098
- const year = moment(selection.end).format('YYYY');
1192
+ const start = selection.start ? DateTime.fromJSDate(selection.start).toFormat('MMM') : '';
1193
+ const end = selection.end ? DateTime.fromJSDate(selection.end).toFormat('MMM') : '';
1194
+ const year = selection.end ? DateTime.fromJSDate(selection.end).toFormat('yyyy') : '';
1099
1195
  return {
1100
1196
  textbox: `${start}–${end}, ${year}`,
1101
1197
  textbox2: null
@@ -1113,9 +1209,10 @@ class QuarterSelectionStrategy extends DateInputSelectionStrategyBase {
1113
1209
  return this.getSelectionFromDate(date);
1114
1210
  }
1115
1211
  getSelectionFromDate(date) {
1212
+ const dt = DateTime.fromJSDate(date);
1116
1213
  return {
1117
- start: moment(date).startOf('quarter').toDate(),
1118
- end: moment(date).endOf('quarter').toDate()
1214
+ start: dt.startOf('quarter').toJSDate(),
1215
+ end: dt.endOf('quarter').toJSDate()
1119
1216
  };
1120
1217
  }
1121
1218
  getNewSelectionFromExisting(previousSelection) {
@@ -1135,8 +1232,8 @@ class QuarterSelectionStrategy extends DateInputSelectionStrategyBase {
1135
1232
  getNextSelection(selection) {
1136
1233
  // Move the selection to the next quarter
1137
1234
  if (DateInput.isSelectionRange(selection) && selection.start) {
1138
- const date = moment(selection.start).add(1, 'quarter');
1139
- return this.getSelectionFromDate(date.toDate());
1235
+ const date = DateTime.fromJSDate(selection.start).plus({ quarters: 1 });
1236
+ return this.getSelectionFromDate(date.toJSDate());
1140
1237
  }
1141
1238
  // This shouldn't happen since the next stepper is disabled if the selection only has one date.
1142
1239
  // If it does, just return the selection as-is.
@@ -1145,8 +1242,8 @@ class QuarterSelectionStrategy extends DateInputSelectionStrategyBase {
1145
1242
  getPreviousSelection(selection) {
1146
1243
  // Move the selection to the previous quarter
1147
1244
  if (DateInput.isSelectionRange(selection) && selection.start) {
1148
- const date = moment(selection.start).subtract(1, 'quarter');
1149
- return this.getSelectionFromDate(date.toDate());
1245
+ const date = DateTime.fromJSDate(selection.start).minus({ quarters: 1 });
1246
+ return this.getSelectionFromDate(date.toJSDate());
1150
1247
  }
1151
1248
  // This shouldn't happen since the previous stepper is disabled if the selection only has one date.
1152
1249
  // If it does, just return the selection as-is.
@@ -1169,13 +1266,13 @@ class RangeSelectionStrategy extends DateInputSelectionStrategyBase {
1169
1266
  if (!selection) {
1170
1267
  return { textbox: null, textbox2: null };
1171
1268
  }
1172
- // We use the 'll' moment medium format here to make sure the formatted date is formatted according to the user's locale
1269
+ // We use Luxon's DATE_MED preset here (equivalent to moment's 'll') so the formatted date follows the user's locale
1173
1270
  if (DateInput.isSelectionSingleDate(selection)) {
1174
- return { textbox: moment(selection).format('ll'), textbox2: null };
1271
+ return { textbox: DateTime.fromJSDate(selection).toLocaleString(DateTime.DATE_MED), textbox2: null };
1175
1272
  }
1176
1273
  else {
1177
- const start = selection.start ? moment(selection.start).format('ll') : null;
1178
- const end = selection.end ? moment(selection.end).format('ll') : null;
1274
+ const start = selection.start ? DateTime.fromJSDate(selection.start).toLocaleString(DateTime.DATE_MED) : null;
1275
+ const end = selection.end ? DateTime.fromJSDate(selection.end).toLocaleString(DateTime.DATE_MED) : null;
1179
1276
  return { textbox: start, textbox2: end };
1180
1277
  }
1181
1278
  }
@@ -1186,7 +1283,7 @@ class RangeSelectionStrategy extends DateInputSelectionStrategyBase {
1186
1283
  // because we don't have a fixed range to automatically adjust the dates to. If the user is changing the begin date or end date and ends
1187
1284
  // up crossing the other date, we should clear out the date that's not being changed so that the user can enter a valid range using the
1188
1285
  // begin/end date they just entered.
1189
- if (start && end && moment(start).isAfter(end)) {
1286
+ if (start && end && DateTime.fromJSDate(start) > DateTime.fromJSDate(end)) {
1190
1287
  if (opts?.parseFromEnd) {
1191
1288
  start = null;
1192
1289
  }
@@ -1204,18 +1301,19 @@ class RangeSelectionStrategy extends DateInputSelectionStrategyBase {
1204
1301
  getSelectionFromDate(date, existingSelection) {
1205
1302
  if (DateInput.isSelectionRange(existingSelection)) {
1206
1303
  const { start, end } = existingSelection;
1304
+ const dDt = DateTime.fromJSDate(date);
1207
1305
  if (start && !end) {
1208
1306
  // If the selected date is before the existing start date, set it as the new start date and use the existing start date as the end date
1209
- return moment(date).isBefore(start) ? { start: date, end: start } : { start, end: date };
1307
+ return dDt < DateTime.fromJSDate(start) ? { start: date, end: start } : { start, end: date };
1210
1308
  }
1211
1309
  if (end && !start) {
1212
1310
  // If the selected date is after the existing end date, set it as the new end date and use the existing end date as the start date
1213
- return moment(date).isBefore(end) ? { start: date, end } : { start: end, end: date };
1311
+ return dDt < DateTime.fromJSDate(end) ? { start: date, end } : { start: end, end: date };
1214
1312
  }
1215
1313
  }
1216
1314
  else if (DateInput.isSelectionSingleDate(existingSelection)) {
1217
1315
  // If the selected date is before the existing date, set it as the new start date and use the existing date as the end date
1218
- return moment(date).isBefore(existingSelection) ? { start: date, end: existingSelection } : { start: existingSelection, end: date };
1316
+ return DateTime.fromJSDate(date) < DateTime.fromJSDate(existingSelection) ? { start: date, end: existingSelection } : { start: existingSelection, end: date };
1219
1317
  }
1220
1318
  // If no selection exists or we already have a complete selection, start a new one with the selected date as the start date.
1221
1319
  return { start: date, end: null };
@@ -1236,9 +1334,9 @@ class RangeSelectionStrategy extends DateInputSelectionStrategyBase {
1236
1334
  // If we have a valid range, we'll shift the range to the date provided, using it as the end date
1237
1335
  // The new selection will have the same length as the previous.
1238
1336
  if (DateInput.isSelectionRange(existingSelection) && existingSelection.start && existingSelection.end) {
1239
- const length = moment(existingSelection.end).diff(existingSelection.start, 'days');
1337
+ const length = Math.floor(DateTime.fromJSDate(existingSelection.end).diff(DateTime.fromJSDate(existingSelection.start), 'days').days);
1240
1338
  return {
1241
- start: moment(date).subtract(length, 'days').toDate(),
1339
+ start: DateTime.fromJSDate(date).minus({ days: length }).toJSDate(),
1242
1340
  end: date
1243
1341
  };
1244
1342
  }
@@ -1250,10 +1348,11 @@ class RangeSelectionStrategy extends DateInputSelectionStrategyBase {
1250
1348
  // We can only determine the next selection if we have a valid range
1251
1349
  if (DateInput.isSelectionRange(selection) && selection.start && selection.end) {
1252
1350
  // Shift the range forward by the number of days between the start and end dates
1253
- const length = moment(selection.end).diff(selection.start, 'days');
1351
+ const end = DateTime.fromJSDate(selection.end);
1352
+ const length = Math.floor(end.diff(DateTime.fromJSDate(selection.start), 'days').days);
1254
1353
  return {
1255
- start: moment(selection.end).add(1, 'days').toDate(),
1256
- end: moment(selection.end).add(1 + length, 'days').toDate()
1354
+ start: end.plus({ days: 1 }).toJSDate(),
1355
+ end: end.plus({ days: 1 + length }).toJSDate()
1257
1356
  };
1258
1357
  }
1259
1358
  // This shouldn't happen since the next stepper is disabled if the selection only has one date.
@@ -1264,10 +1363,11 @@ class RangeSelectionStrategy extends DateInputSelectionStrategyBase {
1264
1363
  // We can only determine the previous selection if we have a valid range
1265
1364
  if (DateInput.isSelectionRange(selection) && selection.start && selection.end) {
1266
1365
  // Shift the range back by the number of days between the start and end dates
1267
- const length = moment(selection.end).diff(selection.start, 'days');
1366
+ const start = DateTime.fromJSDate(selection.start);
1367
+ const length = Math.floor(DateTime.fromJSDate(selection.end).diff(start, 'days').days);
1268
1368
  return {
1269
- start: moment(selection.start).subtract(1 + length, 'days').toDate(),
1270
- end: moment(selection.start).subtract(1, 'days').toDate()
1369
+ start: start.minus({ days: 1 + length }).toJSDate(),
1370
+ end: start.minus({ days: 1 }).toJSDate()
1271
1371
  };
1272
1372
  }
1273
1373
  // This shouldn't happen since the previous stepper is disabled if the selection only has one date.
@@ -1277,31 +1377,33 @@ class RangeSelectionStrategy extends DateInputSelectionStrategyBase {
1277
1377
  getPrimaryCalendarView(selection, minDate, maxDate, currentView) {
1278
1378
  let viewDate;
1279
1379
  if (DateInput.isSelectionRange(selection)) {
1280
- let start = selection.start ? moment(selection.start) : null;
1281
- let end = selection.end ? moment(selection.end) : null;
1380
+ const start = selection.start ? DateTime.fromJSDate(selection.start) : null;
1381
+ const end = selection.end ? DateTime.fromJSDate(selection.end) : null;
1382
+ const minDt = DateTime.fromJSDate(minDate);
1383
+ const maxDt = DateTime.fromJSDate(maxDate);
1282
1384
  // Since we're in range mode, the primary calendar is mostly concerned with the start date
1283
1385
  if (start) {
1284
1386
  // If we have a start date in the selection and it's before the min date, shift the view to the min date.
1285
- if (start.isBefore(minDate, 'month')) {
1387
+ if (start.startOf('month') < minDt.startOf('month')) {
1286
1388
  viewDate = minDate;
1287
1389
  // If the start is after the max date, shift the view to the max date.
1288
1390
  }
1289
- else if (start.isSameOrAfter(maxDate, 'month')) {
1391
+ else if (start.startOf('month') >= maxDt.startOf('month')) {
1290
1392
  // the secondary calendar will show the max date month.
1291
1393
  // The primary calendar will show the month before the max date.
1292
- viewDate = moment(maxDate).subtract(1, 'month').toDate();
1394
+ viewDate = maxDt.minus({ months: 1 }).toJSDate();
1293
1395
  }
1294
1396
  else {
1295
- viewDate = start.toDate();
1397
+ viewDate = start.toJSDate();
1296
1398
  }
1297
1399
  }
1298
- else if (end && end.isSameOrBefore(minDate, 'month')) {
1400
+ else if (end && end.startOf('month') <= minDt.startOf('month')) {
1299
1401
  // If we don't have a start date, and the end date is the same month or before the min date, shift the view to the min date.
1300
1402
  viewDate = minDate;
1301
1403
  }
1302
- else if (end && end.isSameOrBefore(new Date(), 'month')) {
1404
+ else if (end && end.startOf('month') <= DateTime.now().startOf('month')) {
1303
1405
  // If we don't have a start date, and the end date is the same month or before the current month, shift the view to the month before the end
1304
- viewDate = moment(end).subtract(1, 'month').toDate();
1406
+ viewDate = end.minus({ months: 1 }).toJSDate();
1305
1407
  }
1306
1408
  else {
1307
1409
  // Otherwise, show the current month.
@@ -1319,32 +1421,34 @@ class RangeSelectionStrategy extends DateInputSelectionStrategyBase {
1319
1421
  getSecondaryCalendarView(selection, minDate, maxDate, currentView) {
1320
1422
  let viewDate;
1321
1423
  if (DateInput.isSelectionRange(selection)) {
1322
- let start = selection.start ? moment(selection.start) : null;
1323
- let end = selection.end ? moment(selection.end) : null;
1424
+ const start = selection.start ? DateTime.fromJSDate(selection.start) : null;
1425
+ const end = selection.end ? DateTime.fromJSDate(selection.end) : null;
1426
+ const minDt = DateTime.fromJSDate(minDate);
1427
+ const maxDt = DateTime.fromJSDate(maxDate);
1324
1428
  // The secondary calendar is primarily concerned with the end date in the selection.
1325
1429
  if (end) {
1326
- if (end.isAfter(maxDate, 'month')) {
1430
+ if (end.startOf('month') > maxDt.startOf('month')) {
1327
1431
  // If the end date is after the max date, shift the view to the max date.
1328
1432
  viewDate = maxDate;
1329
1433
  }
1330
- else if (end.isSameOrBefore(minDate, 'month')) {
1434
+ else if (end.startOf('month') <= minDt.startOf('month')) {
1331
1435
  // If the end date is the same month or before the min date, shift the view to show
1332
1436
  // the month after the min date. The primary calendar will show the min date month.
1333
- viewDate = moment(minDate).add(1, 'month').toDate();
1437
+ viewDate = minDt.plus({ months: 1 }).toJSDate();
1334
1438
  }
1335
1439
  else {
1336
1440
  // Otherwise, show the end date month.
1337
- viewDate = end.toDate();
1441
+ viewDate = end.toJSDate();
1338
1442
  }
1339
1443
  }
1340
- else if (start && start.isSameOrAfter(maxDate, 'month')) {
1444
+ else if (start && start.startOf('month') >= maxDt.startOf('month')) {
1341
1445
  // If we don't have an end date, and the start date is after the max date, show the max date month
1342
1446
  viewDate = maxDate;
1343
1447
  }
1344
- else if (start && start.isSameOrAfter(new Date(), 'month')) {
1448
+ else if (start && start.startOf('month') >= DateTime.now().startOf('month')) {
1345
1449
  // If we don't have an end date, and the start date is on or after the current month,
1346
1450
  // show the month after the start date.
1347
- viewDate = moment(start).add(1, 'month').toDate();
1451
+ viewDate = start.plus({ months: 1 }).toJSDate();
1348
1452
  }
1349
1453
  else {
1350
1454
  // Otherwise, show the current month.
@@ -1379,12 +1483,12 @@ class YearSelectionStrategy extends DateInputSelectionStrategyBase {
1379
1483
  // Only one date is needed for formatting since the ranges span a single year.
1380
1484
  // There shouldn't be any case where there's only a single date but it's covered anyway.
1381
1485
  const date = DateInput.isSelectionRange(selection) ? selection.start : selection;
1382
- return { textbox: moment(date).format('YYYY'), textbox2: null };
1486
+ return { textbox: date ? DateTime.fromJSDate(date).toFormat('yyyy') : null, textbox2: null };
1383
1487
  }
1384
1488
  parseString(value, parseFormats, opts) {
1385
- // Including 'YY' and 'YYYY' as valid formats for year input. These aren't included in the default parse
1489
+ // Including 'yy' and 'yyyy' as valid formats for year input. These aren't included in the default parse
1386
1490
  // formats because they cause issues with the default date parsing.
1387
- return super.parseString(value, ['YY', 'YYYY', ...parseFormats], opts);
1491
+ return super.parseString(value, ['yy', 'yyyy', ...parseFormats], opts);
1388
1492
  }
1389
1493
  parseTextboxValues(value, parseFormats, opts) {
1390
1494
  // Only a single textbox is used in year mode
@@ -1395,9 +1499,10 @@ class YearSelectionStrategy extends DateInputSelectionStrategyBase {
1395
1499
  return this.getSelectionFromDate(date);
1396
1500
  }
1397
1501
  getSelectionFromDate(date) {
1502
+ const dt = DateTime.fromJSDate(date);
1398
1503
  return {
1399
- start: moment(date).startOf('year').toDate(),
1400
- end: moment(date).endOf('year').toDate()
1504
+ start: dt.startOf('year').toJSDate(),
1505
+ end: dt.endOf('year').toJSDate()
1401
1506
  };
1402
1507
  }
1403
1508
  getNewSelectionFromExisting(previousSelection) {
@@ -1420,8 +1525,8 @@ class YearSelectionStrategy extends DateInputSelectionStrategyBase {
1420
1525
  getNextSelection(selection) {
1421
1526
  // Move the selection to the next year
1422
1527
  if (DateInput.isSelectionRange(selection) && selection.start) {
1423
- const date = moment(selection.start).add(1, 'year');
1424
- return this.getSelectionFromDate(date.toDate());
1528
+ const date = DateTime.fromJSDate(selection.start).plus({ years: 1 });
1529
+ return this.getSelectionFromDate(date.toJSDate());
1425
1530
  }
1426
1531
  // This shouldn't happen since the next stepper is disabled if the selection only has one date.
1427
1532
  // If it does, just return the selection as-is.
@@ -1430,8 +1535,8 @@ class YearSelectionStrategy extends DateInputSelectionStrategyBase {
1430
1535
  getPreviousSelection(selection) {
1431
1536
  // Move the selection to the previous year
1432
1537
  if (DateInput.isSelectionRange(selection) && selection.start) {
1433
- const date = moment(selection.start).subtract(1, 'year');
1434
- return this.getSelectionFromDate(date.toDate());
1538
+ const date = DateTime.fromJSDate(selection.start).minus({ years: 1 });
1539
+ return this.getSelectionFromDate(date.toJSDate());
1435
1540
  }
1436
1541
  // This shouldn't happen since the previous stepper is disabled if the selection only has one date.
1437
1542
  // If it does, just return the selection as-is.
@@ -1470,10 +1575,10 @@ class DateDisplayPipe {
1470
1575
  transform(date, showEndOfTime, showTime, showSeconds) {
1471
1576
  let display = '';
1472
1577
  let formatString = '';
1473
- if (date && moment(date).isValid() && (showEndOfTime || !DateTimeHelper.isEndOfTime(date))) {
1578
+ if (date != null && DateTimeHelper.toDateTime(date).isValid && (showEndOfTime || !DateTimeHelper.isEndOfTime(date))) {
1474
1579
  // use user-preferred formats
1475
1580
  this.userPreferenceService.getPreferences().subscribe(result => {
1476
- //if preferences exist then format date to users preference
1581
+ //if preferences exist then format date to users preference
1477
1582
  //otherwise use the last user preference
1478
1583
  if (result.preference) {
1479
1584
  formatString = result.preference.dateFormat;
@@ -1487,7 +1592,7 @@ class DateDisplayPipe {
1487
1592
  this.lastFormatString = formatString;
1488
1593
  }
1489
1594
  });
1490
- display = moment(date).format(this.lastFormatString);
1595
+ display = DateTimeHelper.formatDate(date, this.lastFormatString);
1491
1596
  }
1492
1597
  return display;
1493
1598
  }
@@ -1554,9 +1659,14 @@ class CalendarItemComponent {
1554
1659
  this.today = false;
1555
1660
  this.outsideActiveMonth = false;
1556
1661
  }
1662
+ else if (this.item?.date) {
1663
+ const itemDt = DateTime.fromJSDate(this.item.date);
1664
+ this.today = itemDt.hasSame(DateTime.now(), 'day');
1665
+ this.outsideActiveMonth = !itemDt.hasSame(DateTime.fromJSDate(this.view.date), 'month');
1666
+ }
1557
1667
  else {
1558
- this.today = moment(this.item?.date).isSame(moment(), 'day');
1559
- this.outsideActiveMonth = !moment(this.item?.date).isSame(this.view.date, 'month');
1668
+ this.today = false;
1669
+ this.outsideActiveMonth = false;
1560
1670
  }
1561
1671
  if (this.item?.date) {
1562
1672
  this.hidden = this.isHidden(this.item.date, this.minDate, this.maxDate, this.view.mode);
@@ -1570,24 +1680,30 @@ class CalendarItemComponent {
1570
1680
  if (!date || !selection) {
1571
1681
  return false;
1572
1682
  }
1683
+ const unit = view ?? 'day';
1684
+ const dt = DateTime.fromJSDate(date);
1573
1685
  if (DateInput.isSelectionSingleDate(selection)) {
1574
- return moment(date).isSame(selection, view);
1686
+ return dt.hasSame(DateTime.fromJSDate(selection), unit);
1575
1687
  }
1576
1688
  else {
1577
1689
  if (selection.start && !selection.end) {
1578
- return moment(date).isSame(selection.start, view);
1690
+ return dt.hasSame(DateTime.fromJSDate(selection.start), unit);
1579
1691
  }
1580
1692
  else if (!selection.start && selection.end) {
1581
- return moment(date).isSame(selection.end, view);
1693
+ return dt.hasSame(DateTime.fromJSDate(selection.end), unit);
1582
1694
  }
1583
1695
  else if (selection.start && selection.end) {
1584
- return moment(date).isBetween(selection.start, selection.end, view, '[]');
1696
+ const d = dt.startOf(unit);
1697
+ const s = DateTime.fromJSDate(selection.start).startOf(unit);
1698
+ const e = DateTime.fromJSDate(selection.end).startOf(unit);
1699
+ return d >= s && d <= e;
1585
1700
  }
1586
1701
  }
1587
1702
  return false;
1588
1703
  }
1589
1704
  isHidden(date, minDate, maxDate, view) {
1590
- return moment(date).isBefore(minDate, view) || moment(date).isAfter(maxDate, view);
1705
+ const d = DateTime.fromJSDate(date).startOf(view);
1706
+ return d < DateTime.fromJSDate(minDate).startOf(view) || d > DateTime.fromJSDate(maxDate).startOf(view);
1591
1707
  }
1592
1708
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CalendarItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1593
1709
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: CalendarItemComponent, isStandalone: false, selector: "button[ec-calendar-item]", inputs: { item: "item", selection: "selection", view: "view", minDate: "minDate", maxDate: "maxDate" }, host: { properties: { "class.is-today": "this.today", "class.is-selected": "this.selected", "class.is-outside-active-month": "this.outsideActiveMonth", "class.is-hidden": "this.hidden", "attr.disabled": "this.disabled" } }, usesOnChanges: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host{font-size:var(--ec-font-size-action);height:2rem;line-height:1.25rem;padding:.3125rem .5rem;border:0;border-radius:var(--ec-border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer}:host .label{display:flex;align-items:center;justify-content:center;white-space:nowrap;flex:auto}:host .ec-icon{flex:none}:host .ec-icon+.label{flex:none;margin-left:.25rem}:host.has-badge{padding-right:.0625rem}:host:focus{outline:none;position:relative;z-index:1}:host:disabled{background-color:var(--ec-background-color-disabled);border:1px solid var(--ec-form-control-border-color-disabled);color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled);cursor:default}:host:disabled .ec-icon{color:var(--ec-color-disabled-dark)}:host{background-color:transparent}:host:disabled{background-color:transparent;border-color:transparent;color:var(--ec-color-hint-dark);--ec-color-icon: var(--ec-color-hint-dark)}:host:hover:not(:disabled){background-color:var(--ec-background-color-hover)}:host:active:not(:disabled){background-color:var(--ec-background-color-selected);font-weight:700}:host:focus:not(:disabled){box-shadow:var(--ec-button-box-shadow-active, 0 0 0 2px var(--ec-border-color-focus))}:host.is-selected{background-color:var(--ec-background-color-selected);font-weight:700}:host{line-height:1.125rem}:host.is-selected,:host.is-selected:disabled{background-color:var(--ec-background-color-selected);font-weight:700}:host.is-today{position:relative}:host.is-today:after{content:\"\";position:absolute;top:50%;left:50%;width:1.75rem;height:1.75rem;transform:translate(-50%,-50%);border:1px solid;border-radius:50%;pointer-events:none}:host.is-outside-active-month{color:var(--ec-color-hint-dark)}:host.is-hidden{opacity:0!important}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
@@ -1636,8 +1752,12 @@ class CalendarComponent {
1636
1752
  this.viewChange = new EventEmitter();
1637
1753
  /** Array of calendar item rows to display in the calendar. */
1638
1754
  this.calendarItems = [];
1639
- /** Weekday labels to show at the top of the calendar in day view. */
1640
- this.weekDays = moment.weekdaysShort().map(d => d.slice(0, 1));
1755
+ /** Weekday labels to show at the top of the calendar in day view. Starts on Sunday to match the calendar grid layout. */
1756
+ this.weekDays = (() => {
1757
+ // Info.weekdays returns Monday-first; reorder so Sunday is first to match the calendar grid.
1758
+ const mondayFirst = Info.weekdays('short');
1759
+ return [mondayFirst[6], ...mondayFirst.slice(0, 6)].map(d => d.slice(0, 1));
1760
+ })();
1641
1761
  this.disablePreviousButton = false;
1642
1762
  this.disableNextButton = false;
1643
1763
  // Trackby functions for ngFor loops. These reduce the number of DOM elements that need to be updated when the calendar is re-drawn.
@@ -1661,19 +1781,19 @@ class CalendarComponent {
1661
1781
  onNextClick() {
1662
1782
  // If we're in day view, we're incrementing by month
1663
1783
  // In month, quarter, and year views we're incrementing by year\
1664
- const unit = this.view.mode === 'day' ? 'month' : 'year';
1784
+ const unit = this.view.mode === 'day' ? 'months' : 'years';
1665
1785
  // In year view, we're moving by 16 years at a time. Otherwise we're just moving by 1 month/year.
1666
1786
  const count = this.view.mode === 'year' ? 16 : 1;
1667
- const goToDate = moment(this.view.date).add(count, unit).toDate();
1787
+ const goToDate = DateTime.fromJSDate(this.view.date).plus({ [unit]: count }).toJSDate();
1668
1788
  this.drawCalendar({ mode: this.view.mode, date: goToDate });
1669
1789
  }
1670
1790
  onPreviousClick() {
1671
1791
  // If we're in day view, we're incrementing by month
1672
1792
  // In month, quarter, and year views we're incrementing by year
1673
- const unit = this.view.mode === 'day' ? 'month' : 'year';
1793
+ const unit = this.view.mode === 'day' ? 'months' : 'years';
1674
1794
  // In year view, we're moving by 16 years at a time. Otherwise we're just moving by 1 month/year.
1675
1795
  const count = this.view.mode === 'year' ? 16 : 1;
1676
- const goToDate = moment(this.view.date).subtract(count, unit).toDate();
1796
+ const goToDate = DateTime.fromJSDate(this.view.date).minus({ [unit]: count }).toJSDate();
1677
1797
  this.drawCalendar({ mode: this.view.mode, date: goToDate });
1678
1798
  }
1679
1799
  /** Switches the calendar to month view. */
@@ -1740,13 +1860,14 @@ class CalendarComponent {
1740
1860
  this.view = view;
1741
1861
  this.viewChange.emit(view);
1742
1862
  }
1743
- this.month = moment(this.view.date).format('MMM');
1744
- this.year = moment(this.view.date).format('YYYY');
1863
+ const viewDt = DateTime.fromJSDate(this.view.date);
1864
+ this.month = viewDt.toFormat('MMM');
1865
+ this.year = viewDt.toFormat('yyyy');
1745
1866
  this.calendarItems = this.getCalendarItems(this.view);
1746
1867
  const startYear = this.calendarItems[0][0].date < this.minDate ? this.minDate : this.calendarItems[0][0].date;
1747
1868
  const lastItem = this.getLastItem();
1748
1869
  const endYear = lastItem.date > this.maxDate ? this.maxDate : lastItem.date;
1749
- this.yearRange = `${moment(startYear).format('YYYY')}&ndash;${moment(endYear).format('YYYY')}`;
1870
+ this.yearRange = `${DateTime.fromJSDate(startYear).toFormat('yyyy')}&ndash;${DateTime.fromJSDate(endYear).toFormat('yyyy')}`;
1750
1871
  this.updateNextPreviousStates();
1751
1872
  }
1752
1873
  getCalendarItems(view) {
@@ -1758,53 +1879,58 @@ class CalendarComponent {
1758
1879
  }
1759
1880
  }
1760
1881
  getDayViewItems(activeDate) {
1761
- // 6 rows of 7 days = 42 days
1762
- return range(0, 6).map(r => {
1763
- return range(0, 7).map(d => {
1764
- // Use the start of the week of the first day of the month.
1765
- // This pads out the first week with any days from the previous month.
1766
- const date = moment(activeDate).startOf('month').startOf('week').add(r * 7 + d, 'day');
1882
+ // 6 rows of 7 days = 42 days.
1883
+ // Use the start of the week of the first day of the month, anchored to Sunday to match the calendar grid.
1884
+ // Luxon's startOf('week') is Monday-based per ISO, so shift back to Sunday explicitly.
1885
+ const monthStart = DateTime.fromJSDate(activeDate).startOf('month');
1886
+ const sundayStart = monthStart.weekday === 7 ? monthStart : monthStart.startOf('week').minus({ days: 1 });
1887
+ return range(0, 6).map((r) => {
1888
+ return range(0, 7).map((d) => {
1889
+ const date = sundayStart.plus({ days: r * 7 + d });
1767
1890
  return {
1768
- date: date.toDate(),
1769
- label: date.format('D')
1891
+ date: date.toJSDate(),
1892
+ label: date.toFormat('d')
1770
1893
  };
1771
1894
  });
1772
1895
  });
1773
1896
  }
1774
1897
  getMonthViewItems(activeDate) {
1775
1898
  // 4 rows of 3 months = 12 months
1776
- return range(0, 4).map(r => {
1777
- return range(0, 3).map(m => {
1778
- const date = moment(activeDate).startOf('year').add(r * 3 + m, 'month');
1899
+ const yearStart = DateTime.fromJSDate(activeDate).startOf('year');
1900
+ return range(0, 4).map((r) => {
1901
+ return range(0, 3).map((m) => {
1902
+ const date = yearStart.plus({ months: r * 3 + m });
1779
1903
  return {
1780
- date: date.toDate(),
1781
- label: date.format('MMM')
1904
+ date: date.toJSDate(),
1905
+ label: date.toFormat('MMM')
1782
1906
  };
1783
1907
  });
1784
1908
  });
1785
1909
  }
1786
1910
  getQuarterViewItems(activeDate) {
1787
1911
  // 2 rows of 2 quarters = 4 quarters
1788
- return range(0, 2).map(r => {
1789
- return range(0, 2).map(q => {
1790
- const date = moment(activeDate).startOf('year').add(r * 2 + q, 'quarter');
1791
- const endDate = moment(date).endOf('quarter');
1912
+ const yearStart = DateTime.fromJSDate(activeDate).startOf('year');
1913
+ return range(0, 2).map((r) => {
1914
+ return range(0, 2).map((q) => {
1915
+ const date = yearStart.plus({ quarters: r * 2 + q });
1916
+ const endDate = date.endOf('quarter');
1792
1917
  return {
1793
- date: date.toDate(),
1794
- label: `${date.format('MMM')}&ndash;${endDate.format('MMM')}`
1918
+ date: date.toJSDate(),
1919
+ label: `${date.toFormat('MMM')}&ndash;${endDate.toFormat('MMM')}`
1795
1920
  };
1796
1921
  });
1797
1922
  });
1798
1923
  }
1799
1924
  getYearViewItems(activeDate) {
1800
1925
  // 4 rows of 4 years = 16 years
1801
- return range(0, 4).map(r => {
1802
- return range(0, 4).map(y => {
1803
- // Subtracting 8 years to put the current active year at the beginning of the 3rd row.
1804
- const date = moment(activeDate).startOf('year').subtract(8, 'years').add(r * 4 + y, 'year');
1926
+ // Subtracting 8 years to put the current active year at the beginning of the 3rd row.
1927
+ const yearStart = DateTime.fromJSDate(activeDate).startOf('year').minus({ years: 8 });
1928
+ return range(0, 4).map((r) => {
1929
+ return range(0, 4).map((y) => {
1930
+ const date = yearStart.plus({ years: r * 4 + y });
1805
1931
  return {
1806
- date: date.toDate(),
1807
- label: date.format('YYYY')
1932
+ date: date.toJSDate(),
1933
+ label: date.toFormat('yyyy')
1808
1934
  };
1809
1935
  });
1810
1936
  });
@@ -1814,24 +1940,20 @@ class CalendarComponent {
1814
1940
  // We don't want to disable the next/previous buttons if the min or max date is within the
1815
1941
  // next or previous view
1816
1942
  const unit = this.view.mode === 'day' ? 'month' : 'year';
1943
+ const pluralUnit = this.view.mode === 'day' ? 'months' : 'years';
1944
+ const viewDt = DateTime.fromJSDate(this.view.date);
1817
1945
  // When in year view, we need to subtract 9 years to determine if we're past the min date.
1818
1946
  // The year view is 16 years long, and the current date is the 9th year in the view.
1819
1947
  const subCount = this.view.mode === 'year' ? 9 : 1;
1820
- if (moment(this.view.date).subtract(subCount, unit).isBefore(this.minDate, unit)) {
1821
- this.disablePreviousButton = true;
1822
- }
1823
- else {
1824
- this.disablePreviousButton = false;
1825
- }
1948
+ const prev = viewDt.minus({ [pluralUnit]: subCount }).startOf(unit);
1949
+ const minDt = DateTime.fromJSDate(this.minDate).startOf(unit);
1950
+ this.disablePreviousButton = prev < minDt;
1826
1951
  // When in year view, we need to add 8 years to determine if we're past the max date.
1827
1952
  // The year view is 16 years long, and the current date is the 9th year in the view.
1828
1953
  const addCount = this.view.mode === 'year' ? 8 : 1;
1829
- if (moment(this.view.date).add(addCount, unit).isAfter(this.maxDate, unit)) {
1830
- this.disableNextButton = true;
1831
- }
1832
- else {
1833
- this.disableNextButton = false;
1834
- }
1954
+ const next = viewDt.plus({ [pluralUnit]: addCount }).startOf(unit);
1955
+ const maxDt = DateTime.fromJSDate(this.maxDate).startOf(unit);
1956
+ this.disableNextButton = next > maxDt;
1835
1957
  }
1836
1958
  getLastItem() {
1837
1959
  const lastRow = this.calendarItems[this.calendarItems.length - 1];
@@ -5122,7 +5244,7 @@ class DateInputComponent extends FormControlBase {
5122
5244
  * Date parsing formats for user-entered dates. Defaults to month-first formats, but is updated in onInit
5123
5245
  * to use the user's preferred date format.
5124
5246
  */
5125
- this.parseFormats = DateTimeHelper.getMomentParseFormats();
5247
+ this.parseFormats = DateTimeHelper.getLuxonParseFormats();
5126
5248
  }
5127
5249
  ngOnChanges(changes) {
5128
5250
  if (changes.selectionMode && !changes.selectionMode.isFirstChange()) {
@@ -5239,7 +5361,7 @@ class DateInputComponent extends FormControlBase {
5239
5361
  goToToday() {
5240
5362
  // If both calendars are visible, show today in the secondary calendar and the month before in the primary calendar.
5241
5363
  if (this.selectionStrategy.showSecondaryCalendar) {
5242
- this.primaryCalendarView = { mode: 'day', date: moment().subtract(1, 'month').toDate() };
5364
+ this.primaryCalendarView = { mode: 'day', date: DateTime.now().minus({ months: 1 }).toJSDate() };
5243
5365
  this.secondaryCalendarView = { mode: 'day', date: new Date() };
5244
5366
  // If we're in a single date mode, show today in the primary calendar.
5245
5367
  }
@@ -5372,7 +5494,7 @@ class DateInputComponent extends FormControlBase {
5372
5494
  const { preference } = await lastValueFrom(this.userPreferenceService.getPreferences());
5373
5495
  const dateFormat = preference?.dateFormat;
5374
5496
  this.placeholder = dateFormat ?? this.placeholder;
5375
- this.parseFormats = DateTimeHelper.getMomentParseFormats(dateFormat);
5497
+ this.parseFormats = DateTimeHelper.getLuxonParseFormats(dateFormat);
5376
5498
  }
5377
5499
  /** Focuses the date input. */
5378
5500
  focusInput() {
@@ -5392,10 +5514,10 @@ class DateInputComponent extends FormControlBase {
5392
5514
  // This would cause the dates in the other calendar to be unselectable if we were to
5393
5515
  // update the min/max dates in these cases.
5394
5516
  if (this.primaryCalendarView?.mode === 'day') {
5395
- this.secondaryCalendarMinDate = moment(this.primaryCalendarView?.date).add(1, 'month').startOf('month').toDate();
5517
+ this.secondaryCalendarMinDate = DateTime.fromJSDate(this.primaryCalendarView.date).plus({ months: 1 }).startOf('month').toJSDate();
5396
5518
  }
5397
5519
  if (this.secondaryCalendarView?.mode === 'day') {
5398
- this.primaryCalendarMaxDate = moment(this.secondaryCalendarView?.date).subtract(1, 'month').endOf('month').toDate();
5520
+ this.primaryCalendarMaxDate = DateTime.fromJSDate(this.secondaryCalendarView.date).minus({ months: 1 }).endOf('month').toJSDate();
5399
5521
  }
5400
5522
  }
5401
5523
  updateCalendars(selection) {
@@ -5411,8 +5533,10 @@ class DateInputComponent extends FormControlBase {
5411
5533
  // However, it's possible that the new date is after the secondary calendar's date. In this case,
5412
5534
  // We want to shift the secondary calendar so the calendars stay in order.
5413
5535
  if (shiftSecondary && this.secondaryCalendarView) {
5414
- if (moment(this.primaryCalendarView.date).isSameOrAfter(this.secondaryCalendarView.date, 'month')) {
5415
- let newSecondaryDate = moment(this.primaryCalendarView.date).add(1, 'month').toDate();
5536
+ const primaryDt = DateTime.fromJSDate(this.primaryCalendarView.date);
5537
+ const secondaryDt = DateTime.fromJSDate(this.secondaryCalendarView.date);
5538
+ if (primaryDt.startOf('month') >= secondaryDt.startOf('month')) {
5539
+ const newSecondaryDate = primaryDt.plus({ months: 1 }).toJSDate();
5416
5540
  this.secondaryCalendarView = { mode: this.selectionStrategy.selectionViewMode, date: newSecondaryDate };
5417
5541
  }
5418
5542
  }
@@ -5423,8 +5547,10 @@ class DateInputComponent extends FormControlBase {
5423
5547
  // However, it's possible that the new date is before the primary calendar's date. In this case,
5424
5548
  // We want to shift the primary calendar so the calendars stay in order.
5425
5549
  if (shiftPrimary && this.primaryCalendarView) {
5426
- if (moment(this.primaryCalendarView.date).isSameOrAfter(this.secondaryCalendarView.date, 'month')) {
5427
- let newPrimaryDate = moment(this.secondaryCalendarView.date).subtract(1, 'month').toDate();
5550
+ const primaryDt = DateTime.fromJSDate(this.primaryCalendarView.date);
5551
+ const secondaryDt = DateTime.fromJSDate(this.secondaryCalendarView.date);
5552
+ if (primaryDt.startOf('month') >= secondaryDt.startOf('month')) {
5553
+ const newPrimaryDate = secondaryDt.minus({ months: 1 }).toJSDate();
5428
5554
  this.primaryCalendarView = { mode: this.selectionStrategy.selectionViewMode, date: newPrimaryDate };
5429
5555
  }
5430
5556
  }
@@ -5474,10 +5600,12 @@ class DateInputComponent extends FormControlBase {
5474
5600
  // We're using the view mode as the granularity. We don't want to invalidate
5475
5601
  // the date in the case where you have a month/quarter/year selected and the min
5476
5602
  // or max date is somewhere within that month/quarter/year.
5477
- if (moment(value).isBefore(this.minDate, this.selectionStrategy.selectionViewMode)) {
5603
+ const unit = this.selectionStrategy.selectionViewMode;
5604
+ const valueDt = DateTime.fromJSDate(value).startOf(unit);
5605
+ if (valueDt < DateTime.fromJSDate(this.minDate).startOf(unit)) {
5478
5606
  return { minDate: { minValue: this.minDate } };
5479
5607
  }
5480
- else if (moment(value).isAfter(this.maxDate, this.selectionStrategy.selectionViewMode)) {
5608
+ else if (valueDt > DateTime.fromJSDate(this.maxDate).startOf(unit)) {
5481
5609
  return { maxDate: { maxValue: this.maxDate } };
5482
5610
  }
5483
5611
  }
@@ -11734,7 +11862,9 @@ class DateDisplayPipe2 {
11734
11862
  }
11735
11863
  async transform(date, options) {
11736
11864
  const { showEndOfTime, showTime, showSeconds, displayInUTC } = options || {};
11737
- if (!date || !moment(date).isValid() || (!showEndOfTime && DateTimeHelper.isEndOfTime(date))) {
11865
+ if (date == null)
11866
+ return '';
11867
+ if (!DateTimeHelper.toDateTime(date).isValid || (!showEndOfTime && DateTimeHelper.isEndOfTime(date))) {
11738
11868
  return '';
11739
11869
  }
11740
11870
  const { preference } = await lastValueFrom(this.userPrefs.getPreferences());
@@ -11746,8 +11876,7 @@ class DateDisplayPipe2 {
11746
11876
  }
11747
11877
  formatString += ` ${timeFormat}`;
11748
11878
  }
11749
- // Parse and format the date using moment. If displayInUTC is true, use moment.utc() to shift the date to UTC.
11750
- return (displayInUTC ? moment.utc(date) : moment(date)).format(formatString);
11879
+ return DateTimeHelper.formatDate(date, formatString, displayInUTC);
11751
11880
  }
11752
11881
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: DateDisplayPipe2, deps: [{ token: UserPreferenceService }], target: i0.ɵɵFactoryTarget.Pipe }); }
11753
11882
  static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.4", ngImport: i0, type: DateDisplayPipe2, isStandalone: false, name: "dateDisplay2" }); }
@@ -11760,6 +11889,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
11760
11889
  }]
11761
11890
  }], ctorParameters: () => [{ type: UserPreferenceService }] });
11762
11891
 
11892
+ /**
11893
+ * Same behavior as {@link DateDisplayPipe2}, but always appends the short named
11894
+ * timezone abbreviation (e.g. `EST`, `PDT`, `UTC`) to the output. Use this when
11895
+ * downstream consumers need to disambiguate the timezone of a rendered date.
11896
+ *
11897
+ * @example <span>{{ someDate | dateDisplay3 | async }}</span>
11898
+ */
11899
+ class DateDisplayPipe3 {
11900
+ constructor(userPrefs) {
11901
+ this.userPrefs = userPrefs;
11902
+ }
11903
+ async transform(date, options) {
11904
+ const { showEndOfTime, showTime, showSeconds, displayInUTC } = options || {};
11905
+ if (date == null)
11906
+ return '';
11907
+ if (!DateTimeHelper.toDateTime(date).isValid || (!showEndOfTime && DateTimeHelper.isEndOfTime(date))) {
11908
+ return '';
11909
+ }
11910
+ const { preference } = await lastValueFrom(this.userPrefs.getPreferences());
11911
+ let formatString = preference?.dateFormat || 'MM/DD/YYYY';
11912
+ if (showTime) {
11913
+ let timeFormat = preference.timeFormat;
11914
+ if (!showSeconds) {
11915
+ timeFormat = timeFormat.replace(':ss', '');
11916
+ }
11917
+ formatString += ` ${timeFormat}`;
11918
+ }
11919
+ // Luxon's `ZZZZ` renders the short named offset (e.g. `EST`, `EDT`, `UTC`).
11920
+ // The token passes through `momentToLuxonFormat` unchanged.
11921
+ formatString += ' ZZZZ';
11922
+ return DateTimeHelper.formatDate(date, formatString, !!displayInUTC);
11923
+ }
11924
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: DateDisplayPipe3, deps: [{ token: UserPreferenceService }], target: i0.ɵɵFactoryTarget.Pipe }); }
11925
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.4", ngImport: i0, type: DateDisplayPipe3, isStandalone: false, name: "dateDisplay3" }); }
11926
+ }
11927
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: DateDisplayPipe3, decorators: [{
11928
+ type: Pipe,
11929
+ args: [{
11930
+ name: 'dateDisplay3',
11931
+ standalone: false
11932
+ }]
11933
+ }], ctorParameters: () => [{ type: UserPreferenceService }] });
11934
+
11763
11935
  /**
11764
11936
  * Format a time to the user's preference for display
11765
11937
  */
@@ -11772,11 +11944,10 @@ class TimeDisplayPipe {
11772
11944
  * Format a time for display, accounting for user's display preferences.
11773
11945
  */
11774
11946
  transform(time, showSeconds) {
11775
- let display = '';
11776
11947
  let formatString = '';
11777
11948
  // use user-preferred formats
11778
11949
  this.userPreferenceService.getPreferences().subscribe(result => {
11779
- //if preferences exist then format time to users preference
11950
+ //if preferences exist then format time to users preference
11780
11951
  //otherwise use the last user preference
11781
11952
  if (result.preference) {
11782
11953
  formatString = result.preference.timeFormat;
@@ -11786,8 +11957,7 @@ class TimeDisplayPipe {
11786
11957
  this.lastFormatString = formatString;
11787
11958
  }
11788
11959
  });
11789
- display = moment(time).format(this.lastFormatString);
11790
- return display;
11960
+ return DateTimeHelper.formatDate(time ?? null, this.lastFormatString);
11791
11961
  }
11792
11962
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: TimeDisplayPipe, deps: [{ token: UserPreferenceService }], target: i0.ɵɵFactoryTarget.Pipe }); }
11793
11963
  static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.4", ngImport: i0, type: TimeDisplayPipe, isStandalone: false, name: "timeDisplay" }); }
@@ -11815,21 +11985,21 @@ class RelativeDatePipe {
11815
11985
  * If any of todayLabel, yesterdayLabel is supplied, use the supplied label.
11816
11986
  */
11817
11987
  transform(timeSelected, options) {
11818
- const selected = moment(timeSelected);
11819
- const today = moment();
11820
- const yesterday = moment().subtract(1, 'day');
11988
+ const selected = DateTime.fromISO(timeSelected);
11989
+ const today = DateTime.now();
11990
+ const yesterday = today.minus({ days: 1 });
11821
11991
  const timeDisplay = options?.dateOnly ? `` : ` ${this.timeDisplayPipe.transform(timeSelected)}`;
11822
11992
  let displayValue = null;
11823
11993
  let prefixValue = '';
11824
- if (selected.isSame(today, 'day') && !options?.showTimeForToday) {
11994
+ if (selected.hasSame(today, 'day') && !options?.showTimeForToday) {
11825
11995
  displayValue = this.translateService.instant(options?.todayLabel ? options?.todayLabel : 'today');
11826
11996
  prefixValue = options?.todayPrefix ?? '';
11827
11997
  }
11828
- else if (selected.isSame(today, 'day') && options?.showTimeForToday && !timeDisplay) {
11998
+ else if (selected.hasSame(today, 'day') && options?.showTimeForToday && !timeDisplay) {
11829
11999
  displayValue = this.timeDisplayPipe.transform(timeSelected);
11830
12000
  prefixValue = options?.todayTimePrefix ?? '';
11831
12001
  }
11832
- else if (selected.isSame(yesterday, 'day')) {
12002
+ else if (selected.hasSame(yesterday, 'day')) {
11833
12003
  displayValue = this.translateService.instant(options?.yesterdayLabel ? options?.yesterdayLabel : 'yesterday');
11834
12004
  prefixValue = options?.yesterdayPrefix ?? '';
11835
12005
  }
@@ -12467,6 +12637,7 @@ class ComponentsModule {
12467
12637
  DateInputComponent,
12468
12638
  KeyboardNavContainerDirective,
12469
12639
  DateDisplayPipe2,
12640
+ DateDisplayPipe3,
12470
12641
  MultiselectComponent], imports: [CommonModule,
12471
12642
  FormsModule,
12472
12643
  ReactiveFormsModule,
@@ -12539,7 +12710,8 @@ class ComponentsModule {
12539
12710
  CalendarComponent,
12540
12711
  DateInputComponent,
12541
12712
  KeyboardNavContainerDirective,
12542
- DateDisplayPipe2] }); }
12713
+ DateDisplayPipe2,
12714
+ DateDisplayPipe3] }); }
12543
12715
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ComponentsModule, providers: [
12544
12716
  FormGroupHelper,
12545
12717
  DialogService,
@@ -12549,7 +12721,8 @@ class ComponentsModule {
12549
12721
  RowCountPipe,
12550
12722
  RelativeDatePipe,
12551
12723
  HighlightTextPipe,
12552
- DateDisplayPipe2
12724
+ DateDisplayPipe2,
12725
+ DateDisplayPipe3
12553
12726
  ], imports: [CommonModule,
12554
12727
  FormsModule,
12555
12728
  ReactiveFormsModule,
@@ -12635,6 +12808,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
12635
12808
  DateInputComponent,
12636
12809
  KeyboardNavContainerDirective,
12637
12810
  DateDisplayPipe2,
12811
+ DateDisplayPipe3,
12638
12812
  MultiselectComponent
12639
12813
  ],
12640
12814
  imports: [
@@ -12656,7 +12830,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
12656
12830
  RowCountPipe,
12657
12831
  RelativeDatePipe,
12658
12832
  HighlightTextPipe,
12659
- DateDisplayPipe2
12833
+ DateDisplayPipe2,
12834
+ DateDisplayPipe3
12660
12835
  ],
12661
12836
  exports: [
12662
12837
  ButtonComponent,
@@ -12724,7 +12899,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
12724
12899
  CalendarComponent,
12725
12900
  DateInputComponent,
12726
12901
  KeyboardNavContainerDirective,
12727
- DateDisplayPipe2
12902
+ DateDisplayPipe2,
12903
+ DateDisplayPipe3
12728
12904
  ]
12729
12905
  }]
12730
12906
  }] });
@@ -13720,5 +13896,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
13720
13896
  * Generated bundle index. Do not edit.
13721
13897
  */
13722
13898
 
13723
- export { AppBarComponent, AvatarComponent, BannerComponent, ButtonComponent, CacheService, CalendarComponent, CheckboxComponent, ClickAreaForDirective, CollapsibleToggleComponent, ComboboxComponent, ComponentsModule, ConfirmComponent, ConfirmDialogContext, CopyButtonBaseTestInjectorFactory, CopyButtonDirective, CopyTableButtonDirective, CustomValidators, DateDisplayPipe, DateDisplayPipe2, DateInput, DateInputComponent, DateTimeHelper, DialogCloseDuration, DialogCloseEvent, DialogCloseLatestEvent, DialogComponent, DialogEvent, DialogGroupComponent, DialogOpenDuration, DialogOpenEndEvent, DialogOpenStartEvent, DialogResult, DialogService, DropdownComponent, ErrorService, FileTypeExtensions, FileUploadComponent, FormControlBase, FormControlComponent, FormControlLabelComponent, FormGroupComponent, FormGroupHelper, HelpPopoverComponent, HierarchyBase, HierarchyBaseTestInjectorFactory, HierarchyItem, HierarchyMocks, HierarchyTreeComponent, HighlightTextPipe, IfViewportWidthDirective, ItemDisplayComponent, ItemPickerComponent, ItemPickerSelectableContext, JsonDisplayComponent, JsonHelper, KeyboardNavContainerDirective, LinkButtonComponent, MenuComponent, MockActivatedRoute, MockDateDisplayPipe, MockDialog, MockDialogContent, MockTranslateService, MockTranslationHelperService, MultiselectComponent, NavGroup, NavItemActiveDirective, NumericboxComponent, Overlay, PageBaseComponent, PageBaseComponentTestHelper, PageBaseComponentTestInjectorFactory, PageInitResult, PageStatus, PageStatuses, PageTitleComponent, PageViewComponent, PanelCloseDuration, PanelOpenDuration, PopoverComponent, PopupContainerDirective, RadioButtonComponent, RadioButtonOption, RelativeDatePipe, ResizableBase, ResizableColumnComponent, ResizableComponent, RouterHelper, RowCountPipe, ScrollService, SearchableTableComponent, SelectComponent, SpinnerComponent, SplashComponent, SplashService, SpyFactory, TableComponent, TableLockedColumnComponent, TableMasterHeaderRowComponent, TableMasterRowComponent, TablePaginationComponent, TableSelectableRowComponent, TableSelectableRowContext, TabsComponent, Tag, TagsComponent, TelemetryService, TelemetryTrackerService, TextboxComponent, TimeDisplayPipe, ToastComponent, ToastEvent, ToastService, ToasterComponent, TooltipComponent, TooltipDirective, TooltipService, TreeComponent, UnicodeStrings, UserPreferenceService, ValidationMessageService, ViewOverlayComponent, WindowService, WizardBaseComponent, WizardButtonsComponent, WizardProgressComponent, canadianPostalCodeRegex, clickEvent, dateInputFormatRegex, domainPattern, findAllSpacesPattern, forEachFormControl, getApiError, getControlValue, getDecimalPattern, handleKeyNavigate, integerPattern, isApiError, menuAnimationSpeed, mockRouterFactory, mockRouterHelperFactory, numericboxValidation, orderByIgnoreCase, otherZipCodeRegex, phoneNumberValidationPattern, sortByIgnoreCase, textboxValidation, unitedStatesZipCodeRegex, urlValidationPattern, validateFormGroupValuesAreUnique };
13899
+ export { AppBarComponent, AvatarComponent, BannerComponent, ButtonComponent, CacheService, CalendarComponent, CheckboxComponent, ClickAreaForDirective, CollapsibleToggleComponent, ComboboxComponent, ComponentsModule, ConfirmComponent, ConfirmDialogContext, CopyButtonBaseTestInjectorFactory, CopyButtonDirective, CopyTableButtonDirective, CustomValidators, DateDisplayPipe, DateDisplayPipe2, DateDisplayPipe3, DateInput, DateInputComponent, DateTimeHelper, DialogCloseDuration, DialogCloseEvent, DialogCloseLatestEvent, DialogComponent, DialogEvent, DialogGroupComponent, DialogOpenDuration, DialogOpenEndEvent, DialogOpenStartEvent, DialogResult, DialogService, DropdownComponent, ErrorService, FileTypeExtensions, FileUploadComponent, FormControlBase, FormControlComponent, FormControlLabelComponent, FormGroupComponent, FormGroupHelper, HelpPopoverComponent, HierarchyBase, HierarchyBaseTestInjectorFactory, HierarchyItem, HierarchyMocks, HierarchyTreeComponent, HighlightTextPipe, IfViewportWidthDirective, ItemDisplayComponent, ItemPickerComponent, ItemPickerSelectableContext, JsonDisplayComponent, JsonHelper, KeyboardNavContainerDirective, LinkButtonComponent, MenuComponent, MockActivatedRoute, MockDateDisplayPipe, MockDialog, MockDialogContent, MockTranslateService, MockTranslationHelperService, MultiselectComponent, NavGroup, NavItemActiveDirective, NumericboxComponent, Overlay, PageBaseComponent, PageBaseComponentTestHelper, PageBaseComponentTestInjectorFactory, PageInitResult, PageStatus, PageStatuses, PageTitleComponent, PageViewComponent, PanelCloseDuration, PanelOpenDuration, PopoverComponent, PopupContainerDirective, RadioButtonComponent, RadioButtonOption, RelativeDatePipe, ResizableBase, ResizableColumnComponent, ResizableComponent, RouterHelper, RowCountPipe, ScrollService, SearchableTableComponent, SelectComponent, SpinnerComponent, SplashComponent, SplashService, SpyFactory, TableComponent, TableLockedColumnComponent, TableMasterHeaderRowComponent, TableMasterRowComponent, TablePaginationComponent, TableSelectableRowComponent, TableSelectableRowContext, TabsComponent, Tag, TagsComponent, TelemetryService, TelemetryTrackerService, TextboxComponent, TimeDisplayPipe, ToastComponent, ToastEvent, ToastService, ToasterComponent, TooltipComponent, TooltipDirective, TooltipService, TreeComponent, UnicodeStrings, UserPreferenceService, ValidationMessageService, ViewOverlayComponent, WindowService, WizardBaseComponent, WizardButtonsComponent, WizardProgressComponent, canadianPostalCodeRegex, clickEvent, dateInputFormatRegex, domainPattern, findAllSpacesPattern, forEachFormControl, getApiError, getControlValue, getDecimalPattern, handleKeyNavigate, integerPattern, isApiError, menuAnimationSpeed, mockRouterFactory, mockRouterHelperFactory, numericboxValidation, orderByIgnoreCase, otherZipCodeRegex, phoneNumberValidationPattern, sortByIgnoreCase, textboxValidation, unitedStatesZipCodeRegex, urlValidationPattern, validateFormGroupValuesAreUnique };
13724
13900
  //# sourceMappingURL=energycap-components.mjs.map