date-vir 5.3.2 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/LICENSE-MIT +1 -1
  2. package/README.md +28 -28
  3. package/dist/date-operations/calculate-relative-date.d.ts +17 -0
  4. package/dist/{esm/date-operations → date-operations}/calculate-relative-date.js +10 -1
  5. package/dist/date-operations/combine-dates.d.ts +43 -0
  6. package/dist/{esm/date-operations → date-operations}/combine-dates.js +6 -4
  7. package/dist/date-operations/date-position.d.ts +149 -0
  8. package/dist/date-operations/date-position.js +175 -0
  9. package/dist/date-operations/diff-dates.d.ts +95 -0
  10. package/dist/date-operations/diff-dates.js +124 -0
  11. package/dist/extra-utils/end.d.ts +11 -0
  12. package/dist/extra-utils/end.js +11 -0
  13. package/dist/extra-utils/has-date-props.d.ts +35 -0
  14. package/dist/extra-utils/has-date-props.js +46 -0
  15. package/dist/extra-utils/js-date-conversion.d.ts +26 -0
  16. package/dist/extra-utils/js-date-conversion.js +28 -0
  17. package/dist/extra-utils/now.d.ts +56 -0
  18. package/dist/extra-utils/now.js +68 -0
  19. package/dist/extra-utils/override-date.d.ts +27 -0
  20. package/dist/extra-utils/override-date.js +27 -0
  21. package/dist/extra-utils/zero.d.ts +109 -0
  22. package/dist/extra-utils/zero.js +94 -0
  23. package/dist/formatting/formatted-string.d.ts +58 -0
  24. package/dist/formatting/formatted-string.js +73 -0
  25. package/dist/formatting/html-input.d.ts +30 -0
  26. package/dist/formatting/html-input.js +47 -0
  27. package/dist/formatting/relative-string.d.ts +53 -0
  28. package/dist/formatting/relative-string.js +93 -0
  29. package/dist/formatting/simple-strings.d.ts +187 -0
  30. package/dist/formatting/simple-strings.js +120 -0
  31. package/dist/formatting/string-format-types.d.ts +59 -0
  32. package/dist/formatting/string-format-types.js +19 -0
  33. package/dist/formatting/timestamp.d.ts +51 -0
  34. package/dist/formatting/timestamp.js +61 -0
  35. package/dist/full-date/create-full-date.d.ts +91 -0
  36. package/dist/full-date/create-full-date.js +142 -0
  37. package/dist/full-date/date-like.d.ts +9 -0
  38. package/dist/{esm/full-date → full-date}/format-presets.d.ts +4 -2
  39. package/dist/{esm/full-date → full-date}/format-presets.js +4 -2
  40. package/dist/full-date/full-date-parts.d.ts +44 -0
  41. package/dist/full-date/full-date-parts.js +47 -0
  42. package/dist/full-date/full-date-shape.d.ts +108 -0
  43. package/dist/full-date/full-date-shape.js +45 -0
  44. package/dist/full-date/is-valid-full-date.d.ts +21 -0
  45. package/dist/full-date/is-valid-full-date.js +38 -0
  46. package/dist/full-date/luxon-date-time-conversion.d.ts +19 -0
  47. package/dist/full-date/luxon-date-time-conversion.js +43 -0
  48. package/dist/full-date/parsing.d.ts +33 -0
  49. package/dist/full-date/parsing.js +47 -0
  50. package/dist/full-date/string-parsing.d.ts +9 -0
  51. package/dist/{esm/full-date → full-date}/string-parsing.js +6 -0
  52. package/dist/index.d.ts +29 -0
  53. package/dist/index.js +29 -0
  54. package/dist/locales.d.ts +6 -0
  55. package/dist/locales.js +7 -0
  56. package/dist/timezone/timezone-checks.d.ts +21 -0
  57. package/dist/timezone/timezone-checks.js +34 -0
  58. package/dist/{esm/timezone → timezone}/timezone-names.d.ts +11 -5
  59. package/dist/{esm/timezone → timezone}/timezone-names.js +11 -3
  60. package/dist/timezone/timezones.d.ts +42 -0
  61. package/dist/timezone/timezones.js +31 -0
  62. package/package.json +33 -51
  63. package/cspell.config.cjs +0 -13
  64. package/dist/cjs/date-operations/calculate-relative-date.js +0 -12
  65. package/dist/cjs/date-operations/combine-dates.js +0 -50
  66. package/dist/cjs/date-operations/diff-dates.js +0 -105
  67. package/dist/cjs/duration/duration-unit.js +0 -41
  68. package/dist/cjs/duration/duration-utils.js +0 -42
  69. package/dist/cjs/duration/duration.js +0 -2
  70. package/dist/cjs/extra-utils/date-transforms.js +0 -8
  71. package/dist/cjs/extra-utils/has-date-props.js +0 -25
  72. package/dist/cjs/extra-utils/js-date-conversion.js +0 -8
  73. package/dist/cjs/extra-utils/now.js +0 -22
  74. package/dist/cjs/extra-utils/zero.js +0 -31
  75. package/dist/cjs/formatting/formatted-string.js +0 -34
  76. package/dist/cjs/formatting/html-input.js +0 -37
  77. package/dist/cjs/formatting/relative-string.js +0 -77
  78. package/dist/cjs/formatting/simple-strings.js +0 -58
  79. package/dist/cjs/formatting/string-format-types.js +0 -9
  80. package/dist/cjs/formatting/timestamp.js +0 -21
  81. package/dist/cjs/full-date/create-full-date.js +0 -81
  82. package/dist/cjs/full-date/date-like.js +0 -2
  83. package/dist/cjs/full-date/format-presets.js +0 -32
  84. package/dist/cjs/full-date/full-date-shape.js +0 -54
  85. package/dist/cjs/full-date/is-valid-full-date.js +0 -28
  86. package/dist/cjs/full-date/luxon-date-time-conversion.js +0 -43
  87. package/dist/cjs/full-date/parsing.js +0 -48
  88. package/dist/cjs/full-date/string-parsing.js +0 -33
  89. package/dist/cjs/index.js +0 -44
  90. package/dist/cjs/locales.js +0 -5
  91. package/dist/cjs/timezone/timezone-checks.js +0 -34
  92. package/dist/cjs/timezone/timezone-names.js +0 -479
  93. package/dist/cjs/timezone/timezones.js +0 -14
  94. package/dist/esm/date-operations/calculate-relative-date.d.ts +0 -8
  95. package/dist/esm/date-operations/combine-dates.d.ts +0 -35
  96. package/dist/esm/date-operations/diff-dates.d.ts +0 -66
  97. package/dist/esm/date-operations/diff-dates.js +0 -100
  98. package/dist/esm/duration/duration-unit.d.ts +0 -27
  99. package/dist/esm/duration/duration-unit.js +0 -38
  100. package/dist/esm/duration/duration-utils.d.ts +0 -11
  101. package/dist/esm/duration/duration-utils.js +0 -37
  102. package/dist/esm/duration/duration.d.ts +0 -32
  103. package/dist/esm/duration/duration.js +0 -1
  104. package/dist/esm/extra-utils/date-transforms.d.ts +0 -4
  105. package/dist/esm/extra-utils/date-transforms.js +0 -4
  106. package/dist/esm/extra-utils/has-date-props.d.ts +0 -9
  107. package/dist/esm/extra-utils/has-date-props.js +0 -20
  108. package/dist/esm/extra-utils/js-date-conversion.d.ts +0 -2
  109. package/dist/esm/extra-utils/js-date-conversion.js +0 -4
  110. package/dist/esm/extra-utils/now.d.ts +0 -6
  111. package/dist/esm/extra-utils/now.js +0 -16
  112. package/dist/esm/extra-utils/zero.d.ts +0 -31
  113. package/dist/esm/extra-utils/zero.js +0 -26
  114. package/dist/esm/formatting/formatted-string.d.ts +0 -14
  115. package/dist/esm/formatting/formatted-string.js +0 -29
  116. package/dist/esm/formatting/html-input.d.ts +0 -19
  117. package/dist/esm/formatting/html-input.js +0 -33
  118. package/dist/esm/formatting/relative-string.d.ts +0 -31
  119. package/dist/esm/formatting/relative-string.js +0 -73
  120. package/dist/esm/formatting/simple-strings.d.ts +0 -71
  121. package/dist/esm/formatting/simple-strings.js +0 -51
  122. package/dist/esm/formatting/string-format-types.d.ts +0 -7
  123. package/dist/esm/formatting/string-format-types.js +0 -5
  124. package/dist/esm/formatting/timestamp.d.ts +0 -6
  125. package/dist/esm/formatting/timestamp.js +0 -16
  126. package/dist/esm/full-date/create-full-date.d.ts +0 -21
  127. package/dist/esm/full-date/create-full-date.js +0 -73
  128. package/dist/esm/full-date/date-like.d.ts +0 -5
  129. package/dist/esm/full-date/full-date-shape.d.ts +0 -80
  130. package/dist/esm/full-date/full-date-shape.js +0 -51
  131. package/dist/esm/full-date/is-valid-full-date.d.ts +0 -5
  132. package/dist/esm/full-date/is-valid-full-date.js +0 -22
  133. package/dist/esm/full-date/luxon-date-time-conversion.d.ts +0 -15
  134. package/dist/esm/full-date/luxon-date-time-conversion.js +0 -38
  135. package/dist/esm/full-date/parsing.d.ts +0 -27
  136. package/dist/esm/full-date/parsing.js +0 -43
  137. package/dist/esm/full-date/string-parsing.d.ts +0 -3
  138. package/dist/esm/index.d.ts +0 -28
  139. package/dist/esm/index.js +0 -28
  140. package/dist/esm/locales.d.ts +0 -1
  141. package/dist/esm/locales.js +0 -2
  142. package/dist/esm/timezone/timezone-checks.d.ts +0 -17
  143. package/dist/esm/timezone/timezone-checks.js +0 -29
  144. package/dist/esm/timezone/timezones.d.ts +0 -480
  145. package/dist/esm/timezone/timezones.js +0 -11
  146. package/public/index.css +0 -7
  147. /package/dist/{esm/full-date → full-date}/date-like.js +0 -0
@@ -0,0 +1,94 @@
1
+ import { getEnumValues, pickObjectKeys, typedObjectFromEntries } from '@augment-vir/common';
2
+ import { TimeKey } from '../full-date/full-date-parts.js';
3
+ import { overrideDateParts } from './override-date.js';
4
+ /**
5
+ * A {@link FullDate} instance that has the lowest, valid, non-negative, value for each property.
6
+ *
7
+ * @category Constants
8
+ */
9
+ export const zeroDate = {
10
+ year: 0,
11
+ month: 1,
12
+ day: 1,
13
+ hour: 0,
14
+ minute: 0,
15
+ second: 0,
16
+ millisecond: 0,
17
+ };
18
+ /**
19
+ * A {@link FullDate} instance that has the lowest, valid, non-negative, value for each property.
20
+ * Alias for {@link zeroDate}.
21
+ *
22
+ * @category Constants
23
+ */
24
+ export const emptyDate = zeroDate;
25
+ /**
26
+ * An object that contains the time parts of {@link FullDate} all set to `0`.
27
+ *
28
+ * @category Constants
29
+ */
30
+ export const zeroTime = pickObjectKeys(zeroDate, getEnumValues(TimeKey));
31
+ /**
32
+ * Clear the time parts of a {@link FullDate}, setting them all to `0`.
33
+ *
34
+ * @category Clear
35
+ * @example
36
+ *
37
+ * ```ts
38
+ * import {clearTime, type FullDate} from 'date-vir';
39
+ *
40
+ * const exampleDate: Readonly<FullDate> = {
41
+ * year: 2024,
42
+ * month: 1,
43
+ * day: 5,
44
+ * hour: 1,
45
+ * minute: 1,
46
+ * second: 1,
47
+ * millisecond: 1,
48
+ * timezone: 'UTC',
49
+ * };
50
+ *
51
+ * clearTime(exampleDate);
52
+ * // `{year: 2024, month: 1, day: 5, hour: 0, minute: 0, second: 0, millisecond: 0, timezone: 'UTC'}`
53
+ * ```
54
+ */
55
+ export function clearTime(inputFullDate) {
56
+ return clearParts(inputFullDate, getEnumValues(TimeKey));
57
+ }
58
+ /**
59
+ * Clear all the selected parts of {@link FullDate} by setting them each to their lowest, valid
60
+ * value. See {@link zeroDate} for the lowest valid values for each property.
61
+ *
62
+ * @category Clear
63
+ * @example
64
+ *
65
+ * ```ts
66
+ * import {clearTime, type FullDate} from 'date-vir';
67
+ *
68
+ * const exampleDate: Readonly<FullDate> = {
69
+ * year: 2024,
70
+ * month: 1,
71
+ * day: 5,
72
+ * hour: 1,
73
+ * minute: 1,
74
+ * second: 1,
75
+ * millisecond: 1,
76
+ * timezone: 'UTC',
77
+ * };
78
+ *
79
+ * clearParts(exampleDate, [
80
+ * 'year',
81
+ * 'day',
82
+ * ]);
83
+ * // `{year: 0, month: 1, day: 1, hour: 1, minute: 1, second: 1, millisecond: 1, timezone: 'UTC'}`
84
+ * ```
85
+ */
86
+ export function clearParts(inputFullDate, parts) {
87
+ const clearParts = typedObjectFromEntries(parts.map((keyName) => {
88
+ return [
89
+ keyName,
90
+ zeroDate[keyName],
91
+ ];
92
+ }));
93
+ return overrideDateParts(inputFullDate, clearParts);
94
+ }
@@ -0,0 +1,58 @@
1
+ import { type PartialWithUndefined } from '@augment-vir/common';
2
+ import { type FullDate } from '../full-date/full-date-shape.js';
3
+ /**
4
+ * Converts the given {@link FullDate} into a string based the user's locale, or the given locale
5
+ * options.
6
+ *
7
+ * @category Formatting
8
+ * @example
9
+ *
10
+ * ```ts
11
+ * import {toLocaleString} from 'date-vir';
12
+ *
13
+ * ToLocaleString({
14
+ * year: 2024,
15
+ * month: 9,
16
+ * day: 25,
17
+ * hour: 0,
18
+ * minute: 0,
19
+ * second: 0,
20
+ * millisecond: 0,
21
+ * });
22
+ * // `'9/25/2024'` in my locale, yours may be different
23
+ * ```
24
+ */
25
+ export declare function toLocaleString(fullDate: FullDate,
26
+ /** Defaults to using the user's own locale. */
27
+ formatOptions?: (Intl.DateTimeFormatOptions & PartialWithUndefined<{
28
+ locale: string;
29
+ }>) | undefined): string;
30
+ /**
31
+ * Provides arbitrary date formatting control (using Luxon under the hood). For full details on the
32
+ * options for format control, see https://moment.github.io/luxon/#/formatting?id=table-of-tokens
33
+ *
34
+ * In most cases you should prefer {@link toLocaleString} so your users see the format they expect.
35
+ * {@link toLocaleString} already has many formatting options.
36
+ *
37
+ * @category Formatting
38
+ * @example
39
+ *
40
+ * ```ts
41
+ * import {toFormattedString} from 'date-vir';
42
+ *
43
+ * toFormattedString(
44
+ * {
45
+ * year: 2024,
46
+ * month: 9,
47
+ * day: 25,
48
+ * hour: 0,
49
+ * minute: 0,
50
+ * second: 0,
51
+ * millisecond: 0,
52
+ * },
53
+ * 'MMM-yyyy',
54
+ * );
55
+ * // `'Sep-2024'`
56
+ * ```
57
+ */
58
+ export declare function toFormattedString(fullDate: FullDate, format: string, localeOverride?: string): string;
@@ -0,0 +1,73 @@
1
+ import { toLuxonDateTime } from '../full-date/luxon-date-time-conversion.js';
2
+ import { userLocale } from '../locales.js';
3
+ /**
4
+ * Chromium has a weird behavior where the "NARROW NO-BREAK SPACE" character (code 8239) is used
5
+ * instead of a space (code 32) before AM/PM.
6
+ */
7
+ function fixChromiumSpace(original) {
8
+ return original.replace(new RegExp(String.fromCodePoint(8239), 'g'), ' ');
9
+ }
10
+ /**
11
+ * Converts the given {@link FullDate} into a string based the user's locale, or the given locale
12
+ * options.
13
+ *
14
+ * @category Formatting
15
+ * @example
16
+ *
17
+ * ```ts
18
+ * import {toLocaleString} from 'date-vir';
19
+ *
20
+ * ToLocaleString({
21
+ * year: 2024,
22
+ * month: 9,
23
+ * day: 25,
24
+ * hour: 0,
25
+ * minute: 0,
26
+ * second: 0,
27
+ * millisecond: 0,
28
+ * });
29
+ * // `'9/25/2024'` in my locale, yours may be different
30
+ * ```
31
+ */
32
+ export function toLocaleString(fullDate,
33
+ /** Defaults to using the user's own locale. */
34
+ formatOptions) {
35
+ const localeString = toLuxonDateTime(fullDate).toLocaleString({
36
+ ...formatOptions,
37
+ }, {
38
+ locale: formatOptions?.locale ?? userLocale,
39
+ });
40
+ return fixChromiumSpace(localeString);
41
+ }
42
+ /**
43
+ * Provides arbitrary date formatting control (using Luxon under the hood). For full details on the
44
+ * options for format control, see https://moment.github.io/luxon/#/formatting?id=table-of-tokens
45
+ *
46
+ * In most cases you should prefer {@link toLocaleString} so your users see the format they expect.
47
+ * {@link toLocaleString} already has many formatting options.
48
+ *
49
+ * @category Formatting
50
+ * @example
51
+ *
52
+ * ```ts
53
+ * import {toFormattedString} from 'date-vir';
54
+ *
55
+ * toFormattedString(
56
+ * {
57
+ * year: 2024,
58
+ * month: 9,
59
+ * day: 25,
60
+ * hour: 0,
61
+ * minute: 0,
62
+ * second: 0,
63
+ * millisecond: 0,
64
+ * },
65
+ * 'MMM-yyyy',
66
+ * );
67
+ * // `'Sep-2024'`
68
+ * ```
69
+ */
70
+ export function toFormattedString(fullDate, format, localeOverride = userLocale) {
71
+ const formattedString = toLuxonDateTime(fullDate).toFormat(format, { locale: localeOverride });
72
+ return fixChromiumSpace(formattedString);
73
+ }
@@ -0,0 +1,30 @@
1
+ import { FullDatePart } from '../full-date/full-date-parts.js';
2
+ import { DatePart, FullDate } from '../full-date/full-date-shape.js';
3
+ import { DateTimeString, DateTimeWithSeconds, JustDateString, JustTimeString, JustTimeWithSecondsString } from './string-format-types.js';
4
+ /**
5
+ * Only the date part of a {@link FullDate}, without timezone.
6
+ *
7
+ * @category Internal
8
+ */
9
+ export type OnlyDatePart = Omit<DatePart, 'timezone'>;
10
+ /**
11
+ * Only the hour and minute part of a {@link FullDate}, made optional.
12
+ *
13
+ * @category Internal
14
+ */
15
+ export type OnlyHourMinutePart = Pick<Partial<FullDate>, 'hour' | 'minute'>;
16
+ /**
17
+ * Only the hour, minute, and second part of a {@link FullDate}, made optional.
18
+ *
19
+ * @category Internal
20
+ */
21
+ export type OnlyHourMinuteSecondPart = Pick<Partial<FullDate>, 'hour' | 'minute' | 'second'>;
22
+ export declare function toHtmlInputString(fullDate: Omit<FullDate, 'timezone'>, inputType: FullDatePart.DateTime, includeSeconds: true): DateTimeWithSeconds;
23
+ export declare function toHtmlInputString(fullDate: Omit<FullDate, 'timezone'>, inputType: FullDatePart.DateTime, includeSeconds?: false | undefined): DateTimeString;
24
+ export declare function toHtmlInputString(fullDate: OnlyDatePart, inputType: FullDatePart.Date): JustDateString;
25
+ export declare function toHtmlInputString(fullDate: OnlyHourMinutePart, inputType: FullDatePart.Time, includeSeconds?: false | undefined): JustTimeString;
26
+ export declare function toHtmlInputString(fullDate: OnlyHourMinuteSecondPart, inputType: FullDatePart.Time, includeSeconds: true): JustTimeWithSecondsString;
27
+ export declare function toHtmlInputString(fullDate: OnlyHourMinutePart | OnlyHourMinuteSecondPart, inputType: FullDatePart.Time, includeSeconds?: boolean | undefined): JustTimeWithSecondsString | JustTimeString;
28
+ export declare function toHtmlInputString(fullDate: OnlyHourMinuteSecondPart | OnlyDatePart, inputType: FullDatePart, includeSeconds: true): JustDateString | JustTimeWithSecondsString;
29
+ export declare function toHtmlInputString(fullDate: OnlyHourMinutePart | OnlyDatePart, inputType: FullDatePart, includeSeconds?: false | undefined): JustDateString | JustTimeString;
30
+ export declare function toHtmlInputString(fullDate: Omit<FullDate, 'timezone'> | OnlyHourMinutePart | OnlyHourMinuteSecondPart | OnlyDatePart, inputType: FullDatePart, includeSeconds?: boolean | undefined): JustDateString | JustTimeWithSecondsString | JustTimeString | DateTimeWithSeconds | DateTimeString;
@@ -0,0 +1,47 @@
1
+ import { getEnumValues } from '@augment-vir/common';
2
+ import { assertHasFullDateKeys } from '../extra-utils/has-date-props.js';
3
+ import { FullDatePart } from '../full-date/full-date-parts.js';
4
+ import { toSimpleDatePartString, toSimpleTimePartString } from './simple-strings.js';
5
+ /**
6
+ * Converts a {@link FullDate} instance into a string that is understood by
7
+ * [`type="date"`](https://developer.mozilla.org/docs/Web/HTML/Element/input/date) or
8
+ * [`type="time"`](https://developer.mozilla.org/docs/Web/HTML/Element/input/time) instances of
9
+ * [`HTMLInputElement`](https://developer.mozilla.org/docs/Web/HTML/Element/input). This can
10
+ * optionally include seconds as well for `type="time"`.
11
+ *
12
+ * This function ignores timezone, the literal stored date and time numbers are simply concatenated
13
+ * into a string. If you wish to convert time zones, first call {@link toNewTimezone} on your
14
+ * {@link FullDate} instance.
15
+ *
16
+ * @category HTML
17
+ * @category Formatting
18
+ */
19
+ export function toHtmlInputString(fullDate, inputType, includeSeconds) {
20
+ const internalFullDate = fullDate;
21
+ if (inputType === FullDatePart.Date) {
22
+ assertHasFullDateKeys(internalFullDate, [
23
+ 'year',
24
+ 'month',
25
+ 'day',
26
+ ]);
27
+ return toSimpleDatePartString(internalFullDate);
28
+ }
29
+ else if (inputType === FullDatePart.Time) {
30
+ if (includeSeconds && internalFullDate.second == undefined) {
31
+ throw new Error('Tried to include seconds in the time string but no seconds were provided.');
32
+ }
33
+ assertHasFullDateKeys(internalFullDate, [
34
+ 'hour',
35
+ 'minute',
36
+ ]);
37
+ return toSimpleTimePartString(internalFullDate, !!includeSeconds);
38
+ }
39
+ else if (inputType === FullDatePart.DateTime) {
40
+ const datePart = toHtmlInputString(fullDate, FullDatePart.Date);
41
+ const timePart = toHtmlInputString(fullDate, FullDatePart.Time, includeSeconds);
42
+ return `${datePart}T${timePart}`;
43
+ }
44
+ else {
45
+ throw new Error(`Unexpected inputTyped: '${String(inputType)}'. Expected usage of FullDatePart, one of ${getEnumValues(FullDatePart).join(', ')}.`);
46
+ }
47
+ }
@@ -0,0 +1,53 @@
1
+ import { type PartialWithUndefined } from '@augment-vir/common';
2
+ import { AnyDuration, DurationUnitSelection } from '@date-vir/duration';
3
+ import { FullDate } from '../full-date/full-date-shape.js';
4
+ /**
5
+ * Options for {@link toRelativeString}.
6
+ *
7
+ * @category Internal
8
+ */
9
+ export type RelativeStringOptions = PartialWithUndefined<{
10
+ /**
11
+ * Set this to `true` to prevent the `'just now'` relative string from being used when the two
12
+ * dates are very close.
13
+ *
14
+ * @default false // (`'just now'` is used)
15
+ */
16
+ blockJustNow: boolean;
17
+ /**
18
+ * Set this to `true` to only use the largest selected unit with a non-zero value. Otherwise,
19
+ * the output string will contain all selected non-zero units.
20
+ *
21
+ * @default false
22
+ */
23
+ useOnlyLargestUnit: boolean;
24
+ /**
25
+ * The number of decimals to allow for each duration unit's value.
26
+ *
27
+ * @default 0
28
+ */
29
+ allowedDecimals: number;
30
+ }>;
31
+ /**
32
+ * This function starts with a duration (either by being directly passed a duration or by diffing
33
+ * two dates into a duration) and converts that duration into a relative string like "1 month ago"
34
+ * or "in 1 month". Rounding is automatically set to 0 decimal points, but that can be changed.
35
+ *
36
+ * When extremely close to a `0` difference, the output string will be `'just now'`, which can be
37
+ * disabled.
38
+ *
39
+ * @category Formatting
40
+ * @example
41
+ *
42
+ * ```ts
43
+ * import {toRelativeString, selectAllDurationUnits} from 'date-vir';
44
+ *
45
+ * toRelativeString({days: 1.6}, {days: true}); // `'in 2 days'`
46
+ * toRelativeString({days: 1.6}, {days: true, hours: true}); // `'in 1 day, 14 hours'`
47
+ * toRelativeString({seconds: 1}, selectAllDurationUnits); // `'just now'`
48
+ * ```
49
+ */
50
+ export declare function toRelativeString(datesOrDuration: Readonly<{
51
+ start: Readonly<FullDate>;
52
+ end: Readonly<FullDate>;
53
+ }> | Readonly<AnyDuration>, units: Readonly<DurationUnitSelection>, options?: Readonly<RelativeStringOptions>): string;
@@ -0,0 +1,93 @@
1
+ import { check } from '@augment-vir/assert';
2
+ import { arrayToObject, filterMap } from '@augment-vir/common';
3
+ import { DurationUnit, convertDuration, flattenUnitSelection, singularDurationUnitNames, } from '@date-vir/duration';
4
+ import { diffDates } from '../date-operations/diff-dates.js';
5
+ /**
6
+ * This function starts with a duration (either by being directly passed a duration or by diffing
7
+ * two dates into a duration) and converts that duration into a relative string like "1 month ago"
8
+ * or "in 1 month". Rounding is automatically set to 0 decimal points, but that can be changed.
9
+ *
10
+ * When extremely close to a `0` difference, the output string will be `'just now'`, which can be
11
+ * disabled.
12
+ *
13
+ * @category Formatting
14
+ * @example
15
+ *
16
+ * ```ts
17
+ * import {toRelativeString, selectAllDurationUnits} from 'date-vir';
18
+ *
19
+ * toRelativeString({days: 1.6}, {days: true}); // `'in 2 days'`
20
+ * toRelativeString({days: 1.6}, {days: true, hours: true}); // `'in 1 day, 14 hours'`
21
+ * toRelativeString({seconds: 1}, selectAllDurationUnits); // `'just now'`
22
+ * ```
23
+ */
24
+ export function toRelativeString(datesOrDuration, units, options = {}) {
25
+ const selectedUnits = flattenUnitSelection(units);
26
+ /** If there are no selected units, return nothing. */
27
+ if (!check.isLengthAtLeast(selectedUnits, 1)) {
28
+ return '';
29
+ }
30
+ const diff = convertDuration('start' in datesOrDuration ? diffDates(datesOrDuration, units) : datesOrDuration, units, {
31
+ roundToDigits: options.allowedDecimals || 0,
32
+ });
33
+ const isDiffPositive = convertDuration(diff, { milliseconds: true }).milliseconds >= 0;
34
+ const unitValues = filterMap(selectedUnits, (unit) => {
35
+ const quantity = diff[unit] || 0;
36
+ if (!quantity) {
37
+ return undefined;
38
+ }
39
+ return {
40
+ quantity,
41
+ unit,
42
+ };
43
+ }, check.isTruthy).reverse();
44
+ const shouldUseJustNow = !options.blockJustNow &&
45
+ (!check.isLengthAtLeast(unitValues, 1) ||
46
+ (unitValues[0].unit === DurationUnit.Minutes && (diff.minutes || 0) < 1.5) ||
47
+ (unitValues[0].unit === DurationUnit.Seconds && (diff.seconds || 0) < 11) ||
48
+ (unitValues[0].unit === DurationUnit.Milliseconds && (diff.milliseconds || 0) < 750));
49
+ if (shouldUseJustNow) {
50
+ return 'just now';
51
+ }
52
+ else if (options.useOnlyLargestUnit) {
53
+ return toRelativeString(datesOrDuration, { [unitValues[0].unit]: true }, {
54
+ ...options,
55
+ useOnlyLargestUnit: false,
56
+ });
57
+ }
58
+ else if (unitValues.length < selectedUnits.length) {
59
+ /**
60
+ * If the finalized units are less than the selected units, rerun the whole calculation to
61
+ * make sure we're using the right accuracy.
62
+ */
63
+ return toRelativeString(datesOrDuration, arrayToObject(unitValues, ({ unit }) => {
64
+ return {
65
+ key: unit,
66
+ value: true,
67
+ };
68
+ }), options);
69
+ }
70
+ const unitsString = unitValues
71
+ .map(({ quantity, unit }) => {
72
+ const absoluteQuantity = Math.abs(quantity);
73
+ return [
74
+ absoluteQuantity,
75
+ ' ',
76
+ singularDurationUnitNames[unit],
77
+ absoluteQuantity > 1 ? 's' : '',
78
+ ].join('');
79
+ })
80
+ .join(', ');
81
+ if (isDiffPositive) {
82
+ return [
83
+ 'in',
84
+ unitsString,
85
+ ].join(' ');
86
+ }
87
+ else {
88
+ return [
89
+ unitsString,
90
+ 'ago',
91
+ ].join(' ');
92
+ }
93
+ }
@@ -0,0 +1,187 @@
1
+ import type { SetOptionalAndNullable } from '@augment-vir/common';
2
+ import { FullDate } from '../full-date/full-date-shape.js';
3
+ import { JustDateString, JustTimeString, JustTimeWithSecondsString } from './string-format-types.js';
4
+ /**
5
+ * Create a string based on just the date parts of a FullDate.
6
+ *
7
+ * **CAUTION**: this does not user locale setting. Prefer {@link toLocaleString} whenever possible.
8
+ *
9
+ * Example output: `'2023-12-05'`
10
+ *
11
+ * @category Internal
12
+ */
13
+ export declare function toSimpleDatePartString(fullDate: Pick<FullDate, 'year' | 'month' | 'day'>): JustDateString;
14
+ /**
15
+ * Creates a string based on just the time parts of a FullDate.
16
+ *
17
+ * **CAUTION**: this does not user locale setting. Prefer {@link toLocaleString} whenever possible.
18
+ *
19
+ * Example output: `'05:32:21'`
20
+ *
21
+ * @category Internal
22
+ */
23
+ export declare function toSimpleTimePartString(fullDate: Pick<FullDate, 'hour' | 'minute' | 'second'> | Pick<FullDate, 'hour' | 'minute'>, includeSeconds: boolean): JustTimeWithSecondsString | JustTimeString;
24
+ /**
25
+ * The parts of {@link FullDate} required for {@link toDatePartStrings}.
26
+ *
27
+ * @category Internal
28
+ */
29
+ export type FullDateForParts = SetOptionalAndNullable<FullDate, 'millisecond'>;
30
+ /**
31
+ * Splits a FullDate up into multiple formatted string representations.
32
+ *
33
+ * **CAUTION**: this does not user locale setting. Prefer {@link toLocaleString} whenever possible.
34
+ *
35
+ * This uses numbers for everything.
36
+ *
37
+ * @category Formatting
38
+ * @example
39
+ *
40
+ * ```ts
41
+ * import {toDatePartStrings, utcTimezone} from 'date-vir';
42
+ *
43
+ * let result = toDatePartStrings(
44
+ * {
45
+ * year: 2024,
46
+ * month: 4,
47
+ * day: 24,
48
+ * hour: 6,
49
+ * minute: 4,
50
+ * second: 9,
51
+ * millisecond: 123,
52
+ * timezone: utcTimezone,
53
+ * },
54
+ * {includeSeconds: true},
55
+ * );
56
+ * // outputs:
57
+ * result = {
58
+ * date: '2024-04-24',
59
+ * time: '06:04:09',
60
+ * timezone: 'UTC',
61
+ * };
62
+ * ```
63
+ */
64
+ export declare function toDatePartStrings(fullDate: FullDateForParts, options: {
65
+ includeSeconds: true;
66
+ }): {
67
+ date: JustDateString;
68
+ time: JustTimeWithSecondsString;
69
+ timezone: string;
70
+ };
71
+ /**
72
+ * Splits a FullDate up into multiple formatted string representations.
73
+ *
74
+ * **CAUTION**: this does not user locale setting. Prefer {@link toLocaleString} whenever possible.
75
+ *
76
+ * This uses numbers for everything.
77
+ *
78
+ * @category Formatting
79
+ * @example
80
+ *
81
+ * ```ts
82
+ * import {toDatePartStrings, utcTimezone} from 'date-vir';
83
+ *
84
+ * let result = toDatePartStrings(
85
+ * {
86
+ * year: 2024,
87
+ * month: 4,
88
+ * day: 24,
89
+ * hour: 6,
90
+ * minute: 4,
91
+ * second: 9,
92
+ * millisecond: 123,
93
+ * timezone: utcTimezone,
94
+ * },
95
+ * {includeSeconds: true},
96
+ * );
97
+ * // outputs:
98
+ * result = {
99
+ * date: '2024-04-24',
100
+ * time: '06:04:09',
101
+ * timezone: 'UTC',
102
+ * };
103
+ * ```
104
+ */
105
+ export declare function toDatePartStrings(fullDate: SetOptionalAndNullable<FullDateForParts, 'second'>, options: {
106
+ includeSeconds: false;
107
+ }): {
108
+ date: JustDateString;
109
+ time: JustTimeString;
110
+ timezone: string;
111
+ };
112
+ /**
113
+ * Splits a FullDate up into multiple formatted string representations.
114
+ *
115
+ * **CAUTION**: this does not user locale setting. Prefer {@link toLocaleString} whenever possible.
116
+ *
117
+ * This uses numbers for everything.
118
+ *
119
+ * @category Formatting
120
+ * @example
121
+ *
122
+ * ```ts
123
+ * import {toDatePartStrings, utcTimezone} from 'date-vir';
124
+ *
125
+ * let result = toDatePartStrings(
126
+ * {
127
+ * year: 2024,
128
+ * month: 4,
129
+ * day: 24,
130
+ * hour: 6,
131
+ * minute: 4,
132
+ * second: 9,
133
+ * millisecond: 123,
134
+ * timezone: utcTimezone,
135
+ * },
136
+ * {includeSeconds: true},
137
+ * );
138
+ * // outputs:
139
+ * result = {
140
+ * date: '2024-04-24',
141
+ * time: '06:04:09',
142
+ * timezone: 'UTC',
143
+ * };
144
+ * ```
145
+ */
146
+ export declare function toDatePartStrings(fullDate: FullDateForParts, options: {
147
+ includeSeconds: boolean;
148
+ }): {
149
+ date: JustDateString;
150
+ time: JustTimeWithSecondsString | JustTimeString;
151
+ timezone: string;
152
+ };
153
+ /**
154
+ * Converts a date into a simple, unambiguous date string.
155
+ *
156
+ * **CAUTION**: this does not user locale setting. Prefer {@link toLocaleString} whenever possible.
157
+ *
158
+ * @category Formatting
159
+ * @example
160
+ *
161
+ * ```ts
162
+ * import {toSimpleString} from 'date-vir';
163
+ *
164
+ * let result = toSimpleString(
165
+ * {
166
+ * year: 2024,
167
+ * month: 4,
168
+ * day: 24,
169
+ * hour: 6,
170
+ * minute: 4,
171
+ * second: 9,
172
+ * millisecond: 123,
173
+ * timezone: utcTimezone,
174
+ * },
175
+ * {
176
+ * includeSeconds: false,
177
+ * includeTimezone: false,
178
+ * },
179
+ * );
180
+ * // outputs:
181
+ * result = '2024-04-24 06:04';
182
+ * ```
183
+ */
184
+ export declare function toSimpleString(fullDate: FullDateForParts, options: {
185
+ includeSeconds: boolean;
186
+ includeTimezone: boolean;
187
+ }): string;