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.
- package/LICENSE-MIT +1 -1
- package/README.md +28 -28
- package/dist/date-operations/calculate-relative-date.d.ts +17 -0
- package/dist/{esm/date-operations → date-operations}/calculate-relative-date.js +10 -1
- package/dist/date-operations/combine-dates.d.ts +43 -0
- package/dist/{esm/date-operations → date-operations}/combine-dates.js +6 -4
- package/dist/date-operations/diff-dates.d.ts +95 -0
- package/dist/date-operations/diff-dates.js +124 -0
- package/dist/extra-utils/has-date-props.d.ts +35 -0
- package/dist/extra-utils/has-date-props.js +46 -0
- package/dist/extra-utils/js-date-conversion.d.ts +26 -0
- package/dist/extra-utils/js-date-conversion.js +28 -0
- package/dist/extra-utils/now.d.ts +56 -0
- package/dist/extra-utils/now.js +68 -0
- package/dist/extra-utils/override-date.d.ts +27 -0
- package/dist/extra-utils/override-date.js +27 -0
- package/dist/extra-utils/zero.d.ts +99 -0
- package/dist/extra-utils/zero.js +94 -0
- package/dist/formatting/formatted-string.d.ts +58 -0
- package/dist/formatting/formatted-string.js +73 -0
- package/dist/formatting/html-input.d.ts +30 -0
- package/dist/formatting/html-input.js +47 -0
- package/dist/formatting/relative-string.d.ts +53 -0
- package/dist/formatting/relative-string.js +93 -0
- package/dist/formatting/simple-strings.d.ts +187 -0
- package/dist/formatting/simple-strings.js +120 -0
- package/dist/formatting/string-format-types.d.ts +59 -0
- package/dist/formatting/string-format-types.js +19 -0
- package/dist/formatting/timestamp.d.ts +51 -0
- package/dist/formatting/timestamp.js +61 -0
- package/dist/full-date/create-full-date.d.ts +91 -0
- package/dist/full-date/create-full-date.js +142 -0
- package/dist/full-date/date-like.d.ts +9 -0
- package/dist/{esm/full-date → full-date}/format-presets.d.ts +4 -2
- package/dist/{esm/full-date → full-date}/format-presets.js +4 -2
- package/dist/full-date/full-date-parts.d.ts +48 -0
- package/dist/full-date/full-date-parts.js +45 -0
- package/dist/full-date/full-date-shape.d.ts +106 -0
- package/dist/{esm/full-date → full-date}/full-date-shape.js +15 -22
- package/dist/full-date/is-valid-full-date.d.ts +21 -0
- package/dist/full-date/is-valid-full-date.js +38 -0
- package/dist/full-date/luxon-date-time-conversion.d.ts +19 -0
- package/dist/{esm/full-date → full-date}/luxon-date-time-conversion.js +10 -6
- package/dist/full-date/parsing.d.ts +33 -0
- package/dist/full-date/parsing.js +47 -0
- package/dist/full-date/string-parsing.d.ts +9 -0
- package/dist/{esm/full-date → full-date}/string-parsing.js +6 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +27 -0
- package/dist/locales.d.ts +6 -0
- package/dist/locales.js +7 -0
- package/dist/timezone/timezone-checks.d.ts +21 -0
- package/dist/timezone/timezone-checks.js +34 -0
- package/dist/{esm/timezone → timezone}/timezone-names.d.ts +11 -5
- package/dist/{esm/timezone → timezone}/timezone-names.js +11 -3
- package/dist/timezone/timezones.d.ts +42 -0
- package/dist/timezone/timezones.js +31 -0
- package/package.json +30 -48
- package/cspell.config.cjs +0 -13
- package/dist/cjs/date-operations/calculate-relative-date.js +0 -12
- package/dist/cjs/date-operations/combine-dates.js +0 -50
- package/dist/cjs/date-operations/diff-dates.js +0 -105
- package/dist/cjs/duration/duration-unit.js +0 -41
- package/dist/cjs/duration/duration-utils.js +0 -42
- package/dist/cjs/duration/duration.js +0 -2
- package/dist/cjs/extra-utils/date-transforms.js +0 -8
- package/dist/cjs/extra-utils/has-date-props.js +0 -25
- package/dist/cjs/extra-utils/js-date-conversion.js +0 -8
- package/dist/cjs/extra-utils/now.js +0 -22
- package/dist/cjs/extra-utils/zero.js +0 -31
- package/dist/cjs/formatting/formatted-string.js +0 -34
- package/dist/cjs/formatting/html-input.js +0 -37
- package/dist/cjs/formatting/relative-string.js +0 -77
- package/dist/cjs/formatting/simple-strings.js +0 -58
- package/dist/cjs/formatting/string-format-types.js +0 -9
- package/dist/cjs/formatting/timestamp.js +0 -21
- package/dist/cjs/full-date/create-full-date.js +0 -81
- package/dist/cjs/full-date/date-like.js +0 -2
- package/dist/cjs/full-date/format-presets.js +0 -32
- package/dist/cjs/full-date/full-date-shape.js +0 -54
- package/dist/cjs/full-date/is-valid-full-date.js +0 -28
- package/dist/cjs/full-date/luxon-date-time-conversion.js +0 -43
- package/dist/cjs/full-date/parsing.js +0 -48
- package/dist/cjs/full-date/string-parsing.js +0 -33
- package/dist/cjs/index.js +0 -44
- package/dist/cjs/locales.js +0 -5
- package/dist/cjs/timezone/timezone-checks.js +0 -34
- package/dist/cjs/timezone/timezone-names.js +0 -479
- package/dist/cjs/timezone/timezones.js +0 -14
- package/dist/esm/date-operations/calculate-relative-date.d.ts +0 -8
- package/dist/esm/date-operations/combine-dates.d.ts +0 -35
- package/dist/esm/date-operations/diff-dates.d.ts +0 -66
- package/dist/esm/date-operations/diff-dates.js +0 -100
- package/dist/esm/duration/duration-unit.d.ts +0 -27
- package/dist/esm/duration/duration-unit.js +0 -38
- package/dist/esm/duration/duration-utils.d.ts +0 -11
- package/dist/esm/duration/duration-utils.js +0 -37
- package/dist/esm/duration/duration.d.ts +0 -32
- package/dist/esm/duration/duration.js +0 -1
- package/dist/esm/extra-utils/date-transforms.d.ts +0 -4
- package/dist/esm/extra-utils/date-transforms.js +0 -4
- package/dist/esm/extra-utils/has-date-props.d.ts +0 -9
- package/dist/esm/extra-utils/has-date-props.js +0 -20
- package/dist/esm/extra-utils/js-date-conversion.d.ts +0 -2
- package/dist/esm/extra-utils/js-date-conversion.js +0 -4
- package/dist/esm/extra-utils/now.d.ts +0 -5
- package/dist/esm/extra-utils/now.js +0 -16
- package/dist/esm/extra-utils/zero.d.ts +0 -31
- package/dist/esm/extra-utils/zero.js +0 -26
- package/dist/esm/formatting/formatted-string.d.ts +0 -14
- package/dist/esm/formatting/formatted-string.js +0 -29
- package/dist/esm/formatting/html-input.d.ts +0 -19
- package/dist/esm/formatting/html-input.js +0 -33
- package/dist/esm/formatting/relative-string.d.ts +0 -31
- package/dist/esm/formatting/relative-string.js +0 -73
- package/dist/esm/formatting/simple-strings.d.ts +0 -71
- package/dist/esm/formatting/simple-strings.js +0 -51
- package/dist/esm/formatting/string-format-types.d.ts +0 -7
- package/dist/esm/formatting/string-format-types.js +0 -5
- package/dist/esm/formatting/timestamp.d.ts +0 -6
- package/dist/esm/formatting/timestamp.js +0 -16
- package/dist/esm/full-date/create-full-date.d.ts +0 -21
- package/dist/esm/full-date/create-full-date.js +0 -73
- package/dist/esm/full-date/date-like.d.ts +0 -5
- package/dist/esm/full-date/full-date-shape.d.ts +0 -80
- package/dist/esm/full-date/is-valid-full-date.d.ts +0 -5
- package/dist/esm/full-date/is-valid-full-date.js +0 -22
- package/dist/esm/full-date/luxon-date-time-conversion.d.ts +0 -15
- package/dist/esm/full-date/parsing.d.ts +0 -27
- package/dist/esm/full-date/parsing.js +0 -43
- package/dist/esm/full-date/string-parsing.d.ts +0 -3
- package/dist/esm/index.d.ts +0 -28
- package/dist/esm/index.js +0 -28
- package/dist/esm/locales.d.ts +0 -1
- package/dist/esm/locales.js +0 -2
- package/dist/esm/timezone/timezone-checks.d.ts +0 -17
- package/dist/esm/timezone/timezone-checks.js +0 -29
- package/dist/esm/timezone/timezones.d.ts +0 -480
- package/dist/esm/timezone/timezones.js +0 -11
- package/public/index.css +0 -7
- /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
|
+
}
|