date-vir 9.3.0 → 9.4.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/dist/formatting/date-only-iso-string.d.ts +119 -0
- package/dist/formatting/date-only-iso-string.js +141 -0
- package/dist/formatting/string-format-types.d.ts +1 -1
- package/dist/formatting/string-format-types.js +13 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +7 -7
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { type Branded } from '@augment-vir/common';
|
|
2
|
+
import { type RoundOptions } from '@date-vir/duration';
|
|
3
|
+
import { type FullDate } from '../full-date/full-date-shape.js';
|
|
4
|
+
import { type Timezone } from '../timezone/timezones.js';
|
|
5
|
+
import { type UtcIsoString } from './string-format-types.js';
|
|
6
|
+
/**
|
|
7
|
+
* A calendar day with no time of day and no timezone, stored as a {@link UtcIsoString} at midnight
|
|
8
|
+
* UTC of that day. This matches how database `DATE` columns (such as Prisma's `@db.Date`) are read,
|
|
9
|
+
* so the value passes between a database and an API unchanged.
|
|
10
|
+
*
|
|
11
|
+
* @category ISO
|
|
12
|
+
*/
|
|
13
|
+
export type DateOnlyUtcIsoString = Branded<UtcIsoString, 'date-only-utc-iso-string'>;
|
|
14
|
+
/**
|
|
15
|
+
* Checks if the input is a valid {@link DateOnlyUtcIsoString}: a {@link UtcIsoString} whose time is
|
|
16
|
+
* exactly midnight UTC.
|
|
17
|
+
*
|
|
18
|
+
* @category ISO
|
|
19
|
+
* @category Assertion
|
|
20
|
+
* @example
|
|
21
|
+
*
|
|
22
|
+
* ```ts
|
|
23
|
+
* import {isValidDateOnlyUtcIsoString} from 'date-vir';
|
|
24
|
+
*
|
|
25
|
+
* isValidDateOnlyUtcIsoString('2024-05-01T00:00:00.000Z'); // `true`
|
|
26
|
+
* isValidDateOnlyUtcIsoString('2024-05-01T20:18:17.123Z'); // `false`
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function isValidDateOnlyUtcIsoString(input: unknown): input is DateOnlyUtcIsoString;
|
|
30
|
+
/**
|
|
31
|
+
* A shape definition for {@link DateOnlyUtcIsoString}.
|
|
32
|
+
*
|
|
33
|
+
* @category ISO
|
|
34
|
+
*/
|
|
35
|
+
export declare const dateOnlyUtcIsoStringShape: (defaultValue?: DateOnlyUtcIsoString | undefined) => import("object-shape-tester").Shape<import("@sinclair/typebox").TUnsafe<DateOnlyUtcIsoString>>;
|
|
36
|
+
/**
|
|
37
|
+
* Converts a {@link FullDate} into the {@link DateOnlyUtcIsoString} of the calendar day it falls on
|
|
38
|
+
* in its own timezone. To get the day in a different timezone, convert the date first with
|
|
39
|
+
* `toNewTimezone`.
|
|
40
|
+
*
|
|
41
|
+
* @category ISO
|
|
42
|
+
* @category Conversion
|
|
43
|
+
* @example
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* import {TimezoneName, toDateOnlyUtcIsoString} from 'date-vir';
|
|
47
|
+
*
|
|
48
|
+
* toDateOnlyUtcIsoString({
|
|
49
|
+
* year: 2026,
|
|
50
|
+
* month: 10,
|
|
51
|
+
* day: 2,
|
|
52
|
+
*
|
|
53
|
+
* hour: 23,
|
|
54
|
+
* minute: 30,
|
|
55
|
+
* second: 0,
|
|
56
|
+
* millisecond: 0,
|
|
57
|
+
*
|
|
58
|
+
* timezone: TimezoneName['America/Denver'],
|
|
59
|
+
* }); // outputs `'2026-10-02T00:00:00.000Z'` (even though this is October 3rd in UTC)
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare function toDateOnlyUtcIsoString(date: Readonly<FullDate>): DateOnlyUtcIsoString;
|
|
63
|
+
/**
|
|
64
|
+
* Converts a {@link DateOnlyUtcIsoString} into a {@link FullDate} at the start of that same calendar
|
|
65
|
+
* day in the given timezone. The calendar day never shifts. The start of a day is usually midnight
|
|
66
|
+
* but can be later in timezones that have had a DST transition at midnight.
|
|
67
|
+
*
|
|
68
|
+
* @category ISO
|
|
69
|
+
* @category Conversion
|
|
70
|
+
* @example
|
|
71
|
+
*
|
|
72
|
+
* ```ts
|
|
73
|
+
* import {
|
|
74
|
+
* createUtcFullDate,
|
|
75
|
+
* dateOnlyUtcIsoStringToFullDate,
|
|
76
|
+
* TimezoneName,
|
|
77
|
+
* toDateOnlyUtcIsoString,
|
|
78
|
+
* } from 'date-vir';
|
|
79
|
+
*
|
|
80
|
+
* const day = toDateOnlyUtcIsoString(createUtcFullDate('2026-10-02T00:00:00.000Z'));
|
|
81
|
+
*
|
|
82
|
+
* dateOnlyUtcIsoStringToFullDate(day, TimezoneName['America/Denver']);
|
|
83
|
+
* // outputs `{year: 2026, month: 10, day: 2, hour: 0, minute: 0, second: 0, millisecond: 0, timezone: 'America/Denver'}`
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export declare function dateOnlyUtcIsoStringToFullDate<const SpecificTimezone extends Timezone>(dateOnly: DateOnlyUtcIsoString, timezone: SpecificTimezone): FullDate<SpecificTimezone>;
|
|
87
|
+
/**
|
|
88
|
+
* Gets today's calendar day in the given timezone as a {@link DateOnlyUtcIsoString}.
|
|
89
|
+
*
|
|
90
|
+
* @category Now
|
|
91
|
+
* @example
|
|
92
|
+
*
|
|
93
|
+
* ```ts
|
|
94
|
+
* import {getTodayDateOnlyUtcIsoString, TimezoneName} from 'date-vir';
|
|
95
|
+
*
|
|
96
|
+
* getTodayDateOnlyUtcIsoString(TimezoneName['America/Denver']);
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export declare function getTodayDateOnlyUtcIsoString(timezone: Timezone): DateOnlyUtcIsoString;
|
|
100
|
+
/**
|
|
101
|
+
* Counts the whole calendar days from `start` to `end`. Negative when `end` is before `start`. Add
|
|
102
|
+
* `1` for an inclusive count of the days in the range.
|
|
103
|
+
*
|
|
104
|
+
* @category Calculation
|
|
105
|
+
* @example
|
|
106
|
+
*
|
|
107
|
+
* ```ts
|
|
108
|
+
* import {createUtcFullDate, diffDateOnlyDays, toDateOnlyUtcIsoString} from 'date-vir';
|
|
109
|
+
*
|
|
110
|
+
* diffDateOnlyDays({
|
|
111
|
+
* start: toDateOnlyUtcIsoString(createUtcFullDate('2026-10-02T00:00:00.000Z')),
|
|
112
|
+
* end: toDateOnlyUtcIsoString(createUtcFullDate('2026-10-05T00:00:00.000Z')),
|
|
113
|
+
* }); // outputs `3`
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export declare function diffDateOnlyDays({ start, end, }: Readonly<{
|
|
117
|
+
start: DateOnlyUtcIsoString;
|
|
118
|
+
end: DateOnlyUtcIsoString;
|
|
119
|
+
}>, options?: Readonly<RoundOptions>): number;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { applyBrand } from '@augment-vir/common';
|
|
2
|
+
import { DateUnit } from '@date-vir/duration';
|
|
3
|
+
import { createCustomShape } from 'object-shape-tester';
|
|
4
|
+
import { getStartDate } from '../date-operations/date-position.js';
|
|
5
|
+
import { diffDates } from '../date-operations/diff-dates.js';
|
|
6
|
+
import { getNowFullDate } from '../extra-utils/now.js';
|
|
7
|
+
import { clearTime } from '../extra-utils/zero.js';
|
|
8
|
+
import { createUtcFullDate } from '../full-date/create-full-date.js';
|
|
9
|
+
import { utcTimezone } from '../timezone/timezones.js';
|
|
10
|
+
import { isValidIsoString } from './string-format-types.js';
|
|
11
|
+
import { toUtcIsoString } from './timestamp.js';
|
|
12
|
+
/**
|
|
13
|
+
* Checks if the input is a valid {@link DateOnlyUtcIsoString}: a {@link UtcIsoString} whose time is
|
|
14
|
+
* exactly midnight UTC.
|
|
15
|
+
*
|
|
16
|
+
* @category ISO
|
|
17
|
+
* @category Assertion
|
|
18
|
+
* @example
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* import {isValidDateOnlyUtcIsoString} from 'date-vir';
|
|
22
|
+
*
|
|
23
|
+
* isValidDateOnlyUtcIsoString('2024-05-01T00:00:00.000Z'); // `true`
|
|
24
|
+
* isValidDateOnlyUtcIsoString('2024-05-01T20:18:17.123Z'); // `false`
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function isValidDateOnlyUtcIsoString(input) {
|
|
28
|
+
return isValidIsoString(input) && toDateOnlyUtcIsoString(createUtcFullDate(input)) === input;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A shape definition for {@link DateOnlyUtcIsoString}.
|
|
32
|
+
*
|
|
33
|
+
* @category ISO
|
|
34
|
+
*/
|
|
35
|
+
export const dateOnlyUtcIsoStringShape = createCustomShape({
|
|
36
|
+
default: applyBrand('2000-01-01T00:00:00.000Z'),
|
|
37
|
+
name: 'DateOnlyUtcIsoString',
|
|
38
|
+
checkValue(value) {
|
|
39
|
+
return isValidDateOnlyUtcIsoString(value);
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
/**
|
|
43
|
+
* Converts a {@link FullDate} into the {@link DateOnlyUtcIsoString} of the calendar day it falls on
|
|
44
|
+
* in its own timezone. To get the day in a different timezone, convert the date first with
|
|
45
|
+
* `toNewTimezone`.
|
|
46
|
+
*
|
|
47
|
+
* @category ISO
|
|
48
|
+
* @category Conversion
|
|
49
|
+
* @example
|
|
50
|
+
*
|
|
51
|
+
* ```ts
|
|
52
|
+
* import {TimezoneName, toDateOnlyUtcIsoString} from 'date-vir';
|
|
53
|
+
*
|
|
54
|
+
* toDateOnlyUtcIsoString({
|
|
55
|
+
* year: 2026,
|
|
56
|
+
* month: 10,
|
|
57
|
+
* day: 2,
|
|
58
|
+
*
|
|
59
|
+
* hour: 23,
|
|
60
|
+
* minute: 30,
|
|
61
|
+
* second: 0,
|
|
62
|
+
* millisecond: 0,
|
|
63
|
+
*
|
|
64
|
+
* timezone: TimezoneName['America/Denver'],
|
|
65
|
+
* }); // outputs `'2026-10-02T00:00:00.000Z'` (even though this is October 3rd in UTC)
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export function toDateOnlyUtcIsoString(date) {
|
|
69
|
+
return applyBrand(toUtcIsoString({
|
|
70
|
+
...clearTime(date),
|
|
71
|
+
timezone: utcTimezone,
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Converts a {@link DateOnlyUtcIsoString} into a {@link FullDate} at the start of that same calendar
|
|
76
|
+
* day in the given timezone. The calendar day never shifts. The start of a day is usually midnight
|
|
77
|
+
* but can be later in timezones that have had a DST transition at midnight.
|
|
78
|
+
*
|
|
79
|
+
* @category ISO
|
|
80
|
+
* @category Conversion
|
|
81
|
+
* @example
|
|
82
|
+
*
|
|
83
|
+
* ```ts
|
|
84
|
+
* import {
|
|
85
|
+
* createUtcFullDate,
|
|
86
|
+
* dateOnlyUtcIsoStringToFullDate,
|
|
87
|
+
* TimezoneName,
|
|
88
|
+
* toDateOnlyUtcIsoString,
|
|
89
|
+
* } from 'date-vir';
|
|
90
|
+
*
|
|
91
|
+
* const day = toDateOnlyUtcIsoString(createUtcFullDate('2026-10-02T00:00:00.000Z'));
|
|
92
|
+
*
|
|
93
|
+
* dateOnlyUtcIsoStringToFullDate(day, TimezoneName['America/Denver']);
|
|
94
|
+
* // outputs `{year: 2026, month: 10, day: 2, hour: 0, minute: 0, second: 0, millisecond: 0, timezone: 'America/Denver'}`
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export function dateOnlyUtcIsoStringToFullDate(dateOnly, timezone) {
|
|
98
|
+
return getStartDate({
|
|
99
|
+
...createUtcFullDate(dateOnly),
|
|
100
|
+
timezone,
|
|
101
|
+
}, DateUnit.Day);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Gets today's calendar day in the given timezone as a {@link DateOnlyUtcIsoString}.
|
|
105
|
+
*
|
|
106
|
+
* @category Now
|
|
107
|
+
* @example
|
|
108
|
+
*
|
|
109
|
+
* ```ts
|
|
110
|
+
* import {getTodayDateOnlyUtcIsoString, TimezoneName} from 'date-vir';
|
|
111
|
+
*
|
|
112
|
+
* getTodayDateOnlyUtcIsoString(TimezoneName['America/Denver']);
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
export function getTodayDateOnlyUtcIsoString(timezone) {
|
|
116
|
+
return toDateOnlyUtcIsoString(getNowFullDate(timezone));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Counts the whole calendar days from `start` to `end`. Negative when `end` is before `start`. Add
|
|
120
|
+
* `1` for an inclusive count of the days in the range.
|
|
121
|
+
*
|
|
122
|
+
* @category Calculation
|
|
123
|
+
* @example
|
|
124
|
+
*
|
|
125
|
+
* ```ts
|
|
126
|
+
* import {createUtcFullDate, diffDateOnlyDays, toDateOnlyUtcIsoString} from 'date-vir';
|
|
127
|
+
*
|
|
128
|
+
* diffDateOnlyDays({
|
|
129
|
+
* start: toDateOnlyUtcIsoString(createUtcFullDate('2026-10-02T00:00:00.000Z')),
|
|
130
|
+
* end: toDateOnlyUtcIsoString(createUtcFullDate('2026-10-05T00:00:00.000Z')),
|
|
131
|
+
* }); // outputs `3`
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
export function diffDateOnlyDays({ start, end, }, options = {}) {
|
|
135
|
+
return diffDates({
|
|
136
|
+
start: createUtcFullDate(start),
|
|
137
|
+
end: createUtcFullDate(end),
|
|
138
|
+
}, {
|
|
139
|
+
days: true,
|
|
140
|
+
}, options).days;
|
|
141
|
+
}
|
|
@@ -47,7 +47,7 @@ export type UtcIsoString = `${JustDateString}T${JustTimeWithSecondsString}.${num
|
|
|
47
47
|
*
|
|
48
48
|
* @category ISO
|
|
49
49
|
*/
|
|
50
|
-
export declare
|
|
50
|
+
export declare function utcIsoStringShape(defaultValue?: UtcIsoString): import("object-shape-tester").Shape<import("@sinclair/typebox").TUnsafe<`${number}-${number}-${number}T${number}:${number}:${number}.${number}Z`>>;
|
|
51
51
|
/**
|
|
52
52
|
* Checks if the input is a valid UTC ISO string and type guards the input.
|
|
53
53
|
*
|
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
import { DateTime } from 'luxon';
|
|
2
2
|
import { createCustomShape } from 'object-shape-tester';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* @
|
|
4
|
+
* Bundlers ignore `@__NO_SIDE_EFFECTS__` on the function `createCustomShape` returns, so
|
|
5
|
+
* {@link utcIsoStringShape} wraps this in a declaration that can carry it. That lets bundlers drop
|
|
6
|
+
* unused shapes that call {@link utcIsoStringShape}.
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
const createUtcIsoStringShape = createCustomShape({
|
|
9
9
|
default: new Date().toISOString(),
|
|
10
10
|
name: 'UtcIsoString',
|
|
11
11
|
checkValue(value) {
|
|
12
12
|
return isValidIsoString(value);
|
|
13
13
|
},
|
|
14
14
|
});
|
|
15
|
+
/**
|
|
16
|
+
* A shape definition for {@link UtcIsoString}.
|
|
17
|
+
*
|
|
18
|
+
* @category ISO
|
|
19
|
+
*/
|
|
20
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
21
|
+
export function utcIsoStringShape(defaultValue) {
|
|
22
|
+
return createUtcIsoStringShape(defaultValue);
|
|
23
|
+
}
|
|
15
24
|
/**
|
|
16
25
|
* Checks if the input is a valid UTC ISO string and type guards the input.
|
|
17
26
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from './extra-utils/js-date-conversion.js';
|
|
|
10
10
|
export * from './extra-utils/now.js';
|
|
11
11
|
export * from './extra-utils/override-date.js';
|
|
12
12
|
export * from './extra-utils/zero.js';
|
|
13
|
+
export * from './formatting/date-only-iso-string.js';
|
|
13
14
|
export * from './formatting/formatted-string.js';
|
|
14
15
|
export * from './formatting/html-input.js';
|
|
15
16
|
export * from './formatting/relative-string.js';
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export * from './extra-utils/js-date-conversion.js';
|
|
|
10
10
|
export * from './extra-utils/now.js';
|
|
11
11
|
export * from './extra-utils/override-date.js';
|
|
12
12
|
export * from './extra-utils/zero.js';
|
|
13
|
+
export * from './formatting/date-only-iso-string.js';
|
|
13
14
|
export * from './formatting/formatted-string.js';
|
|
14
15
|
export * from './formatting/html-input.js';
|
|
15
16
|
export * from './formatting/relative-string.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "date-vir",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.4.1",
|
|
4
4
|
"description": "Easy and explicit dates and times.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"date",
|
|
@@ -35,16 +35,16 @@
|
|
|
35
35
|
"test:docs": "virmator docs check"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@augment-vir/assert": "^32.
|
|
39
|
-
"@augment-vir/common": "^32.
|
|
40
|
-
"@date-vir/duration": "^9.
|
|
41
|
-
"@types/luxon": "^3.7.
|
|
38
|
+
"@augment-vir/assert": "^32.6.0",
|
|
39
|
+
"@augment-vir/common": "^32.6.0",
|
|
40
|
+
"@date-vir/duration": "^9.4.1",
|
|
41
|
+
"@types/luxon": "^3.7.6",
|
|
42
42
|
"luxon": "^3.7.2",
|
|
43
43
|
"object-shape-tester": "^6.15.1",
|
|
44
44
|
"type-fest": "^5.10.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@augment-vir/test": "^32.
|
|
47
|
+
"@augment-vir/test": "^32.6.0",
|
|
48
48
|
"@web/dev-server-esbuild": "^2.0.0",
|
|
49
49
|
"@web/test-runner": "^1.0.0",
|
|
50
50
|
"@web/test-runner-commands": "^1.0.1",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"@web/test-runner-visual-regression": "^1.0.1",
|
|
53
53
|
"element-vir": "^27.0.2",
|
|
54
54
|
"istanbul-smart-text-reporter": "^1.1.5",
|
|
55
|
-
"markdown-code-example-inserter": "^3.
|
|
55
|
+
"markdown-code-example-inserter": "^3.1.1",
|
|
56
56
|
"typedoc": "^0.28.20",
|
|
57
57
|
"typescript": "^6.0.3"
|
|
58
58
|
},
|