date-vir 5.3.1 → 6.0.1

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 (141) 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/diff-dates.d.ts +95 -0
  8. package/dist/date-operations/diff-dates.js +124 -0
  9. package/dist/extra-utils/has-date-props.d.ts +35 -0
  10. package/dist/extra-utils/has-date-props.js +46 -0
  11. package/dist/extra-utils/js-date-conversion.d.ts +26 -0
  12. package/dist/extra-utils/js-date-conversion.js +28 -0
  13. package/dist/extra-utils/now.d.ts +56 -0
  14. package/dist/extra-utils/now.js +68 -0
  15. package/dist/extra-utils/override-date.d.ts +27 -0
  16. package/dist/extra-utils/override-date.js +27 -0
  17. package/dist/extra-utils/zero.d.ts +99 -0
  18. package/dist/extra-utils/zero.js +94 -0
  19. package/dist/formatting/formatted-string.d.ts +58 -0
  20. package/dist/formatting/formatted-string.js +73 -0
  21. package/dist/formatting/html-input.d.ts +30 -0
  22. package/dist/formatting/html-input.js +47 -0
  23. package/dist/formatting/relative-string.d.ts +53 -0
  24. package/dist/formatting/relative-string.js +93 -0
  25. package/dist/formatting/simple-strings.d.ts +187 -0
  26. package/dist/formatting/simple-strings.js +120 -0
  27. package/dist/formatting/string-format-types.d.ts +59 -0
  28. package/dist/formatting/string-format-types.js +19 -0
  29. package/dist/formatting/timestamp.d.ts +51 -0
  30. package/dist/formatting/timestamp.js +61 -0
  31. package/dist/full-date/create-full-date.d.ts +91 -0
  32. package/dist/full-date/create-full-date.js +142 -0
  33. package/dist/full-date/date-like.d.ts +9 -0
  34. package/dist/{esm/full-date → full-date}/format-presets.d.ts +4 -2
  35. package/dist/{esm/full-date → full-date}/format-presets.js +4 -2
  36. package/dist/full-date/full-date-parts.d.ts +48 -0
  37. package/dist/full-date/full-date-parts.js +45 -0
  38. package/dist/full-date/full-date-shape.d.ts +106 -0
  39. package/dist/{esm/full-date → full-date}/full-date-shape.js +15 -22
  40. package/dist/full-date/is-valid-full-date.d.ts +21 -0
  41. package/dist/full-date/is-valid-full-date.js +38 -0
  42. package/dist/full-date/luxon-date-time-conversion.d.ts +19 -0
  43. package/dist/{esm/full-date → full-date}/luxon-date-time-conversion.js +10 -6
  44. package/dist/full-date/parsing.d.ts +33 -0
  45. package/dist/full-date/parsing.js +47 -0
  46. package/dist/full-date/string-parsing.d.ts +9 -0
  47. package/dist/{esm/full-date → full-date}/string-parsing.js +6 -0
  48. package/dist/index.d.ts +27 -0
  49. package/dist/index.js +27 -0
  50. package/dist/locales.d.ts +6 -0
  51. package/dist/locales.js +7 -0
  52. package/dist/timezone/timezone-checks.d.ts +21 -0
  53. package/dist/timezone/timezone-checks.js +34 -0
  54. package/dist/{esm/timezone → timezone}/timezone-names.d.ts +11 -5
  55. package/dist/{esm/timezone → timezone}/timezone-names.js +11 -3
  56. package/dist/timezone/timezones.d.ts +42 -0
  57. package/dist/timezone/timezones.js +31 -0
  58. package/package.json +30 -48
  59. package/cspell.config.cjs +0 -13
  60. package/dist/cjs/date-operations/calculate-relative-date.js +0 -12
  61. package/dist/cjs/date-operations/combine-dates.js +0 -50
  62. package/dist/cjs/date-operations/diff-dates.js +0 -105
  63. package/dist/cjs/duration/duration-unit.js +0 -41
  64. package/dist/cjs/duration/duration-utils.js +0 -42
  65. package/dist/cjs/duration/duration.js +0 -2
  66. package/dist/cjs/extra-utils/date-transforms.js +0 -8
  67. package/dist/cjs/extra-utils/has-date-props.js +0 -25
  68. package/dist/cjs/extra-utils/js-date-conversion.js +0 -8
  69. package/dist/cjs/extra-utils/now.js +0 -22
  70. package/dist/cjs/extra-utils/zero.js +0 -31
  71. package/dist/cjs/formatting/formatted-string.js +0 -34
  72. package/dist/cjs/formatting/html-input.js +0 -37
  73. package/dist/cjs/formatting/relative-string.js +0 -77
  74. package/dist/cjs/formatting/simple-strings.js +0 -58
  75. package/dist/cjs/formatting/string-format-types.js +0 -9
  76. package/dist/cjs/formatting/timestamp.js +0 -21
  77. package/dist/cjs/full-date/create-full-date.js +0 -81
  78. package/dist/cjs/full-date/date-like.js +0 -2
  79. package/dist/cjs/full-date/format-presets.js +0 -32
  80. package/dist/cjs/full-date/full-date-shape.js +0 -54
  81. package/dist/cjs/full-date/is-valid-full-date.js +0 -28
  82. package/dist/cjs/full-date/luxon-date-time-conversion.js +0 -43
  83. package/dist/cjs/full-date/parsing.js +0 -48
  84. package/dist/cjs/full-date/string-parsing.js +0 -33
  85. package/dist/cjs/index.js +0 -44
  86. package/dist/cjs/locales.js +0 -5
  87. package/dist/cjs/timezone/timezone-checks.js +0 -34
  88. package/dist/cjs/timezone/timezone-names.js +0 -479
  89. package/dist/cjs/timezone/timezones.js +0 -14
  90. package/dist/esm/date-operations/calculate-relative-date.d.ts +0 -8
  91. package/dist/esm/date-operations/combine-dates.d.ts +0 -35
  92. package/dist/esm/date-operations/diff-dates.d.ts +0 -66
  93. package/dist/esm/date-operations/diff-dates.js +0 -100
  94. package/dist/esm/duration/duration-unit.d.ts +0 -27
  95. package/dist/esm/duration/duration-unit.js +0 -38
  96. package/dist/esm/duration/duration-utils.d.ts +0 -11
  97. package/dist/esm/duration/duration-utils.js +0 -37
  98. package/dist/esm/duration/duration.d.ts +0 -32
  99. package/dist/esm/duration/duration.js +0 -1
  100. package/dist/esm/extra-utils/date-transforms.d.ts +0 -4
  101. package/dist/esm/extra-utils/date-transforms.js +0 -4
  102. package/dist/esm/extra-utils/has-date-props.d.ts +0 -9
  103. package/dist/esm/extra-utils/has-date-props.js +0 -20
  104. package/dist/esm/extra-utils/js-date-conversion.d.ts +0 -2
  105. package/dist/esm/extra-utils/js-date-conversion.js +0 -4
  106. package/dist/esm/extra-utils/now.d.ts +0 -5
  107. package/dist/esm/extra-utils/now.js +0 -16
  108. package/dist/esm/extra-utils/zero.d.ts +0 -31
  109. package/dist/esm/extra-utils/zero.js +0 -26
  110. package/dist/esm/formatting/formatted-string.d.ts +0 -14
  111. package/dist/esm/formatting/formatted-string.js +0 -29
  112. package/dist/esm/formatting/html-input.d.ts +0 -19
  113. package/dist/esm/formatting/html-input.js +0 -33
  114. package/dist/esm/formatting/relative-string.d.ts +0 -31
  115. package/dist/esm/formatting/relative-string.js +0 -73
  116. package/dist/esm/formatting/simple-strings.d.ts +0 -71
  117. package/dist/esm/formatting/simple-strings.js +0 -51
  118. package/dist/esm/formatting/string-format-types.d.ts +0 -7
  119. package/dist/esm/formatting/string-format-types.js +0 -5
  120. package/dist/esm/formatting/timestamp.d.ts +0 -6
  121. package/dist/esm/formatting/timestamp.js +0 -16
  122. package/dist/esm/full-date/create-full-date.d.ts +0 -21
  123. package/dist/esm/full-date/create-full-date.js +0 -73
  124. package/dist/esm/full-date/date-like.d.ts +0 -5
  125. package/dist/esm/full-date/full-date-shape.d.ts +0 -80
  126. package/dist/esm/full-date/is-valid-full-date.d.ts +0 -5
  127. package/dist/esm/full-date/is-valid-full-date.js +0 -22
  128. package/dist/esm/full-date/luxon-date-time-conversion.d.ts +0 -15
  129. package/dist/esm/full-date/parsing.d.ts +0 -27
  130. package/dist/esm/full-date/parsing.js +0 -43
  131. package/dist/esm/full-date/string-parsing.d.ts +0 -3
  132. package/dist/esm/index.d.ts +0 -28
  133. package/dist/esm/index.js +0 -28
  134. package/dist/esm/locales.d.ts +0 -1
  135. package/dist/esm/locales.js +0 -2
  136. package/dist/esm/timezone/timezone-checks.d.ts +0 -17
  137. package/dist/esm/timezone/timezone-checks.js +0 -29
  138. package/dist/esm/timezone/timezones.d.ts +0 -480
  139. package/dist/esm/timezone/timezones.js +0 -11
  140. package/public/index.css +0 -7
  141. /package/dist/{esm/full-date → full-date}/date-like.js +0 -0
@@ -0,0 +1,68 @@
1
+ import { toUtcIsoString } from '../formatting/timestamp.js';
2
+ import { createFullDate } from '../full-date/create-full-date.js';
3
+ import { userTimezone, utcTimezone } from '../timezone/timezones.js';
4
+ /**
5
+ * Get the time right now as a UTC ISO.
6
+ *
7
+ * @category Now
8
+ * @example
9
+ *
10
+ * ```ts
11
+ * import {getNowInIsoString} from 'date-vir';
12
+ *
13
+ * getNowInIsoString();
14
+ * ```
15
+ */
16
+ export function getNowInIsoString() {
17
+ /**
18
+ * The time zone doesn't matter here because the ISO string will be identical for a given date
19
+ * no matter what its timezone is.
20
+ */
21
+ return toUtcIsoString(getNowFullDate(utcTimezone));
22
+ }
23
+ /**
24
+ * Get the time right now as a {@link FullDate} represented in the current user's timezone.
25
+ *
26
+ * @category Now
27
+ * @example
28
+ *
29
+ * ```ts
30
+ * import {getNowInUserTimezone} from 'date-vir';
31
+ *
32
+ * getNowInUserTimezone();
33
+ * ```
34
+ */
35
+ export function getNowInUserTimezone() {
36
+ return getNowFullDate(userTimezone);
37
+ }
38
+ /**
39
+ * Get the time right now as a {@link FullDate} represented in the UTC timezone.
40
+ *
41
+ * @category Now
42
+ * @example
43
+ *
44
+ * ```ts
45
+ * import {getNowInUtcTimezone} from 'date-vir';
46
+ *
47
+ * getNowInUtcTimezone();
48
+ * ```
49
+ */
50
+ export function getNowInUtcTimezone() {
51
+ return getNowFullDate(utcTimezone);
52
+ }
53
+ /**
54
+ * Get the time right now as a {@link FullDate} represented in the given timezone.
55
+ *
56
+ * @category Now
57
+ * @example
58
+ *
59
+ * ```ts
60
+ * import {getNowFullDate, utcTimezone, timezones} from 'date-vir';
61
+ *
62
+ * getNowFullDate(utcTimezone);
63
+ * getNowFullDate(timezones['Australia/Brisbane']);
64
+ * ```
65
+ */
66
+ export function getNowFullDate(timezone) {
67
+ return createFullDate(Date.now(), timezone);
68
+ }
@@ -0,0 +1,27 @@
1
+ import { FullDate } from '../full-date/full-date-shape.js';
2
+ import { Timezone } from '../timezone/timezones.js';
3
+ /**
4
+ * Override the initial provided FullDate with all subsequent FullDate parts.
5
+ *
6
+ * @category Util
7
+ * @example
8
+ *
9
+ * ```ts
10
+ * import {overrideDateParts, type FullDate} from 'date-vir';
11
+ *
12
+ * const exampleDate: Readonly<FullDate> = {
13
+ * year: 2024,
14
+ * month: 1,
15
+ * day: 5,
16
+ * hour: 1,
17
+ * minute: 1,
18
+ * second: 1,
19
+ * millisecond: 1,
20
+ * timezone: 'UTC',
21
+ * };
22
+ *
23
+ * overrideDateParts(exampleDate, {day: 20}, {second: 10});
24
+ * // `{year: 2024, month: 1, day: 20, hour: 1, minute: 1, second: 10, millisecond: 1, timezone: 'UTC'}`
25
+ * ```
26
+ */
27
+ export declare function overrideDateParts<const SpecificTimezone extends Timezone>(date: FullDate<SpecificTimezone>, ...overrides: Partial<FullDate<SpecificTimezone>>[]): FullDate<SpecificTimezone>;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Override the initial provided FullDate with all subsequent FullDate parts.
3
+ *
4
+ * @category Util
5
+ * @example
6
+ *
7
+ * ```ts
8
+ * import {overrideDateParts, type FullDate} from 'date-vir';
9
+ *
10
+ * const exampleDate: Readonly<FullDate> = {
11
+ * year: 2024,
12
+ * month: 1,
13
+ * day: 5,
14
+ * hour: 1,
15
+ * minute: 1,
16
+ * second: 1,
17
+ * millisecond: 1,
18
+ * timezone: 'UTC',
19
+ * };
20
+ *
21
+ * overrideDateParts(exampleDate, {day: 20}, {second: 10});
22
+ * // `{year: 2024, month: 1, day: 20, hour: 1, minute: 1, second: 10, millisecond: 1, timezone: 'UTC'}`
23
+ * ```
24
+ */
25
+ export function overrideDateParts(date, ...overrides) {
26
+ return Object.assign({}, date, ...overrides);
27
+ }
@@ -0,0 +1,99 @@
1
+ import { FullDate } from '../full-date/full-date-shape.js';
2
+ import { Timezone } from '../timezone/timezones.js';
3
+ /**
4
+ * A {@link FullDate} instance that has the lowest, valid, non-negative, value for each property.
5
+ *
6
+ * @category Zero
7
+ */
8
+ export declare const zeroDate: {
9
+ readonly year: 0;
10
+ readonly month: 1;
11
+ readonly day: 1;
12
+ readonly hour: 0;
13
+ readonly minute: 0;
14
+ readonly second: 0;
15
+ readonly millisecond: 0;
16
+ };
17
+ /**
18
+ * A {@link FullDate} instance that has the lowest, valid, non-negative, value for each property.
19
+ * Alias for {@link zeroDate}.
20
+ *
21
+ * @category Zero
22
+ */
23
+ export declare const emptyDate: {
24
+ readonly year: 0;
25
+ readonly month: 1;
26
+ readonly day: 1;
27
+ readonly hour: 0;
28
+ readonly minute: 0;
29
+ readonly second: 0;
30
+ readonly millisecond: 0;
31
+ };
32
+ /**
33
+ * An object that contains the time parts of {@link FullDate} all set to `0`.
34
+ *
35
+ * @category Zero
36
+ */
37
+ export declare const zeroTime: Pick<{
38
+ year: 0;
39
+ month: 1;
40
+ day: 1;
41
+ hour: 0;
42
+ minute: 0;
43
+ second: 0;
44
+ millisecond: 0;
45
+ }, "hour" | "minute" | "second" | "millisecond">;
46
+ /**
47
+ * Clear the time parts of a {@link FullDate}, setting them all to `0`.
48
+ *
49
+ * @category Zero
50
+ * @example
51
+ *
52
+ * ```ts
53
+ * import {clearTime, type FullDate} from 'date-vir';
54
+ *
55
+ * const exampleDate: Readonly<FullDate> = {
56
+ * year: 2024,
57
+ * month: 1,
58
+ * day: 5,
59
+ * hour: 1,
60
+ * minute: 1,
61
+ * second: 1,
62
+ * millisecond: 1,
63
+ * timezone: 'UTC',
64
+ * };
65
+ *
66
+ * clearTime(exampleDate);
67
+ * // `{year: 2024, month: 1, day: 5, hour: 0, minute: 0, second: 0, millisecond: 0, timezone: 'UTC'}`
68
+ * ```
69
+ */
70
+ export declare function clearTime<const SpecificTimezone extends Timezone>(inputFullDate: Readonly<FullDate<SpecificTimezone>>): FullDate<SpecificTimezone>;
71
+ /**
72
+ * Clear all the selected parts of {@link FullDate} by setting them each to their lowest, valid
73
+ * value. See {@link zeroDate} for the lowest valid values for each property.
74
+ *
75
+ * @category Zero
76
+ * @example
77
+ *
78
+ * ```ts
79
+ * import {clearTime, type FullDate} from 'date-vir';
80
+ *
81
+ * const exampleDate: Readonly<FullDate> = {
82
+ * year: 2024,
83
+ * month: 1,
84
+ * day: 5,
85
+ * hour: 1,
86
+ * minute: 1,
87
+ * second: 1,
88
+ * millisecond: 1,
89
+ * timezone: 'UTC',
90
+ * };
91
+ *
92
+ * clearParts(exampleDate, [
93
+ * 'year',
94
+ * 'day',
95
+ * ]);
96
+ * // `{year: 0, month: 1, day: 1, hour: 1, minute: 1, second: 1, millisecond: 1, timezone: 'UTC'}`
97
+ * ```
98
+ */
99
+ export declare function clearParts<const SpecificTimezone extends Timezone>(inputFullDate: Readonly<FullDate<SpecificTimezone>>, parts: ReadonlyArray<Exclude<keyof FullDate, 'timezone'>>): FullDate<SpecificTimezone>;
@@ -0,0 +1,94 @@
1
+ import { pickObjectKeys, typedObjectFromEntries } from '@augment-vir/common';
2
+ import { timeFullDateKeys } 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 Zero
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 Zero
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 Zero
29
+ */
30
+ export const zeroTime = pickObjectKeys(zeroDate, timeFullDateKeys);
31
+ /**
32
+ * Clear the time parts of a {@link FullDate}, setting them all to `0`.
33
+ *
34
+ * @category Zero
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, timeFullDateKeys);
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 Zero
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
+ }