date-vir 7.4.3 → 8.1.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.
- package/dist/date-operations/date-position.d.ts +7 -7
- package/dist/date-operations/date-position.js +12 -10
- package/dist/date-operations/diff-dates.d.ts +2 -2
- package/dist/date-operations/diff-dates.js +4 -5
- package/dist/formatting/formatted-string.js +1 -1
- package/dist/formatting/relative-string.d.ts +59 -20
- package/dist/formatting/relative-string.js +137 -72
- package/dist/full-date/luxon-date-time-conversion.d.ts +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/package.json +9 -9
- package/dist/locales.d.ts +0 -6
- package/dist/locales.js +0 -7
|
@@ -89,25 +89,25 @@ export declare function getEndDate<const SpecificTimezone extends Timezone>(date
|
|
|
89
89
|
*/
|
|
90
90
|
export declare const datePositionCalculationShape: import("object-shape-tester").Shape<import("object-shape-tester").Shape<import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TObject<{
|
|
91
91
|
get: import("@sinclair/typebox").TUnsafe<DateUnit.Month>;
|
|
92
|
-
in: import("@sinclair/typebox").TUnion<
|
|
92
|
+
in: import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TUnsafe<DateUnit.Year>[]>;
|
|
93
93
|
}> | import("@sinclair/typebox").TObject<{
|
|
94
94
|
get: import("@sinclair/typebox").TUnsafe<DateUnit.Week>;
|
|
95
|
-
in: import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUnsafe<DateUnit.Month> | import("@sinclair/typebox").TUnsafe<DateUnit.Year>
|
|
95
|
+
in: import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUnsafe<DateUnit.Month> | import("@sinclair/typebox").TUnsafe<DateUnit.Year>)[]>;
|
|
96
96
|
}> | import("@sinclair/typebox").TObject<{
|
|
97
97
|
get: import("@sinclair/typebox").TUnsafe<DateUnit.Day>;
|
|
98
|
-
in: import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUnsafe<DateUnit.Month> | import("@sinclair/typebox").TUnsafe<DateUnit.Year> | import("@sinclair/typebox").TUnsafe<DateUnit.
|
|
98
|
+
in: import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUnsafe<DateUnit.Month> | import("@sinclair/typebox").TUnsafe<DateUnit.Year> | import("@sinclair/typebox").TUnsafe<DateUnit.Week>)[]>;
|
|
99
99
|
}> | import("@sinclair/typebox").TObject<{
|
|
100
100
|
get: import("@sinclair/typebox").TUnsafe<DateUnit.Hour>;
|
|
101
|
-
in: import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUnsafe<DateUnit.Month> | import("@sinclair/typebox").TUnsafe<DateUnit.Year> | import("@sinclair/typebox").TUnsafe<DateUnit.
|
|
101
|
+
in: import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUnsafe<DateUnit.Month> | import("@sinclair/typebox").TUnsafe<DateUnit.Year> | import("@sinclair/typebox").TUnsafe<DateUnit.Week> | import("@sinclair/typebox").TUnsafe<DateUnit.Day>)[]>;
|
|
102
102
|
}> | import("@sinclair/typebox").TObject<{
|
|
103
103
|
get: import("@sinclair/typebox").TUnsafe<DateUnit.Minute>;
|
|
104
|
-
in: import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUnsafe<DateUnit.Month> | import("@sinclair/typebox").TUnsafe<DateUnit.Year> | import("@sinclair/typebox").TUnsafe<DateUnit.
|
|
104
|
+
in: import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUnsafe<DateUnit.Month> | import("@sinclair/typebox").TUnsafe<DateUnit.Year> | import("@sinclair/typebox").TUnsafe<DateUnit.Week> | import("@sinclair/typebox").TUnsafe<DateUnit.Day> | import("@sinclair/typebox").TUnsafe<DateUnit.Hour>)[]>;
|
|
105
105
|
}> | import("@sinclair/typebox").TObject<{
|
|
106
106
|
get: import("@sinclair/typebox").TUnsafe<DateUnit.Second>;
|
|
107
|
-
in: import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUnsafe<DateUnit.Month> | import("@sinclair/typebox").TUnsafe<DateUnit.Year> | import("@sinclair/typebox").TUnsafe<DateUnit.
|
|
107
|
+
in: import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUnsafe<DateUnit.Month> | import("@sinclair/typebox").TUnsafe<DateUnit.Year> | import("@sinclair/typebox").TUnsafe<DateUnit.Week> | import("@sinclair/typebox").TUnsafe<DateUnit.Day> | import("@sinclair/typebox").TUnsafe<DateUnit.Hour> | import("@sinclair/typebox").TUnsafe<DateUnit.Minute>)[]>;
|
|
108
108
|
}> | import("@sinclair/typebox").TObject<{
|
|
109
109
|
get: import("@sinclair/typebox").TUnsafe<DateUnit.Millisecond>;
|
|
110
|
-
in: import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUnsafe<DateUnit.Month> | import("@sinclair/typebox").TUnsafe<DateUnit.Year> | import("@sinclair/typebox").TUnsafe<DateUnit.
|
|
110
|
+
in: import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUnsafe<DateUnit.Month> | import("@sinclair/typebox").TUnsafe<DateUnit.Year> | import("@sinclair/typebox").TUnsafe<DateUnit.Week> | import("@sinclair/typebox").TUnsafe<DateUnit.Day> | import("@sinclair/typebox").TUnsafe<DateUnit.Hour> | import("@sinclair/typebox").TUnsafe<DateUnit.Minute> | import("@sinclair/typebox").TUnsafe<DateUnit.Second>)[]>;
|
|
111
111
|
}>)[]>>>;
|
|
112
112
|
/**
|
|
113
113
|
* All valid date position calculations. Used for {@link calculateDatePosition}.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { check } from '@augment-vir/assert';
|
|
1
|
+
import { assertWrap, check } from '@augment-vir/assert';
|
|
2
2
|
import { stringify } from '@augment-vir/common';
|
|
3
3
|
import { DateUnit, oneIndexedDateUnits } from '@date-vir/duration';
|
|
4
4
|
import { checkValidShape, defineShape, exactShape, unionShape } from 'object-shape-tester';
|
|
@@ -128,25 +128,25 @@ export function getEndDate(date, unit) {
|
|
|
128
128
|
*/
|
|
129
129
|
export const datePositionCalculationShape = defineShape(unionShape({
|
|
130
130
|
get: exactShape(DateUnit.Month),
|
|
131
|
-
in: unionShape(exactShape(DateUnit.Year)
|
|
131
|
+
in: unionShape(exactShape(DateUnit.Year)),
|
|
132
132
|
}, {
|
|
133
133
|
get: exactShape(DateUnit.Week),
|
|
134
|
-
in: unionShape(exactShape(DateUnit.Year), exactShape(DateUnit.
|
|
134
|
+
in: unionShape(exactShape(DateUnit.Year), exactShape(DateUnit.Month)),
|
|
135
135
|
}, {
|
|
136
136
|
get: exactShape(DateUnit.Day),
|
|
137
|
-
in: unionShape(exactShape(DateUnit.Year), exactShape(DateUnit.
|
|
137
|
+
in: unionShape(exactShape(DateUnit.Year), exactShape(DateUnit.Month), exactShape(DateUnit.Week)),
|
|
138
138
|
}, {
|
|
139
139
|
get: exactShape(DateUnit.Hour),
|
|
140
|
-
in: unionShape(exactShape(DateUnit.Year), exactShape(DateUnit.
|
|
140
|
+
in: unionShape(exactShape(DateUnit.Year), exactShape(DateUnit.Month), exactShape(DateUnit.Week), exactShape(DateUnit.Day)),
|
|
141
141
|
}, {
|
|
142
142
|
get: exactShape(DateUnit.Minute),
|
|
143
|
-
in: unionShape(exactShape(DateUnit.Year), exactShape(DateUnit.
|
|
143
|
+
in: unionShape(exactShape(DateUnit.Year), exactShape(DateUnit.Month), exactShape(DateUnit.Week), exactShape(DateUnit.Day), exactShape(DateUnit.Hour)),
|
|
144
144
|
}, {
|
|
145
145
|
get: exactShape(DateUnit.Second),
|
|
146
|
-
in: unionShape(exactShape(DateUnit.Year), exactShape(DateUnit.
|
|
146
|
+
in: unionShape(exactShape(DateUnit.Year), exactShape(DateUnit.Month), exactShape(DateUnit.Week), exactShape(DateUnit.Day), exactShape(DateUnit.Hour), exactShape(DateUnit.Minute)),
|
|
147
147
|
}, {
|
|
148
148
|
get: exactShape(DateUnit.Millisecond),
|
|
149
|
-
in: unionShape(exactShape(DateUnit.Year), exactShape(DateUnit.
|
|
149
|
+
in: unionShape(exactShape(DateUnit.Year), exactShape(DateUnit.Month), exactShape(DateUnit.Week), exactShape(DateUnit.Day), exactShape(DateUnit.Hour), exactShape(DateUnit.Minute), exactShape(DateUnit.Second)),
|
|
150
150
|
}));
|
|
151
151
|
/**
|
|
152
152
|
* Calculate the position of the given date's "get" unit within the given "in" unit.
|
|
@@ -211,8 +211,10 @@ export function calculateDatePosition(date, calculation) {
|
|
|
211
211
|
})
|
|
212
212
|
: start;
|
|
213
213
|
const diffUnit = `${calculation.get}s`;
|
|
214
|
-
const diff = diffDates({ start: startWithOffset, end: date }, {
|
|
215
|
-
|
|
214
|
+
const diff = diffDates({ start: startWithOffset, end: date }, {
|
|
215
|
+
[diffUnit]: true,
|
|
216
|
+
});
|
|
217
|
+
const value = assertWrap.isDefined(diff[diffUnit]);
|
|
216
218
|
const isDayOfWeek = calculation.get === DateUnit.Day && calculation.in === DateUnit.Week;
|
|
217
219
|
if (!isDayOfWeek && check.isIn(calculation.get, oneIndexedDateUnits)) {
|
|
218
220
|
return value + 1;
|
|
@@ -5,8 +5,8 @@ import { type FullDate } from '../full-date/full-date-shape.js';
|
|
|
5
5
|
* provided with the `units` input property, an array is returned with the full diff duration
|
|
6
6
|
* contained in each entry in the requested unit.
|
|
7
7
|
*
|
|
8
|
-
* Note: when years
|
|
9
|
-
*
|
|
8
|
+
* Note: when years or months are used for the unit, "long term" durations are used to calculate the
|
|
9
|
+
* diff. See more details here:
|
|
10
10
|
* https://moment.github.io/luxon/#/math?id=casual-vs-longterm-conversion-accuracy
|
|
11
11
|
*
|
|
12
12
|
* @category Calculation
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { DurationUnit,
|
|
1
|
+
import { DurationUnit, flattenUnitsSmallestToLargest, roundDuration, } from '@date-vir/duration';
|
|
2
2
|
import { toLuxonDateTime } from '../full-date/luxon-date-time-conversion.js';
|
|
3
3
|
const conversionAccuracies = {
|
|
4
4
|
[DurationUnit.Years]: 'longterm',
|
|
5
|
-
[DurationUnit.Quarters]: 'longterm',
|
|
6
5
|
[DurationUnit.Months]: 'longterm',
|
|
7
6
|
[DurationUnit.Weeks]: 'casual',
|
|
8
7
|
[DurationUnit.Days]: 'casual',
|
|
@@ -24,8 +23,8 @@ function getHighestPriorityConversionAccuracy(units) {
|
|
|
24
23
|
* provided with the `units` input property, an array is returned with the full diff duration
|
|
25
24
|
* contained in each entry in the requested unit.
|
|
26
25
|
*
|
|
27
|
-
* Note: when years
|
|
28
|
-
*
|
|
26
|
+
* Note: when years or months are used for the unit, "long term" durations are used to calculate the
|
|
27
|
+
* diff. See more details here:
|
|
29
28
|
* https://moment.github.io/luxon/#/math?id=casual-vs-longterm-conversion-accuracy
|
|
30
29
|
*
|
|
31
30
|
* @category Calculation
|
|
@@ -70,7 +69,7 @@ export function diffDates({ start, end, },
|
|
|
70
69
|
units, options = {}) {
|
|
71
70
|
const luxonDateStart = toLuxonDateTime(start);
|
|
72
71
|
const luxonDateEnd = toLuxonDateTime(end);
|
|
73
|
-
const selectedUnits =
|
|
72
|
+
const selectedUnits = flattenUnitsSmallestToLargest(units);
|
|
74
73
|
const conversionAccuracy = getHighestPriorityConversionAccuracy(selectedUnits);
|
|
75
74
|
const additiveDiff = luxonDateEnd
|
|
76
75
|
.diff(luxonDateStart, selectedUnits, {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { userLocale } from '@date-vir/duration';
|
|
1
2
|
import { toLuxonDateTime } from '../full-date/luxon-date-time-conversion.js';
|
|
2
|
-
import { userLocale } from '../locales.js';
|
|
3
3
|
/**
|
|
4
4
|
* Chromium has a weird behavior where the "NARROW NO-BREAK SPACE" character (code 8239) is used
|
|
5
5
|
* instead of a space (code 32) before AM/PM.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type PartialWithUndefined } from '@augment-vir/common';
|
|
2
|
-
import { type AnyDuration, type DurationUnitSelection } from '@date-vir/duration';
|
|
1
|
+
import { type PartialWithUndefined, type RequiredAndNotNull } from '@augment-vir/common';
|
|
2
|
+
import { type AnyDuration, type DurationUnitSelection, type LocaleOptions, type RoundOptions } from '@date-vir/duration';
|
|
3
3
|
import { type FullDate } from '../full-date/full-date-shape.js';
|
|
4
4
|
/**
|
|
5
5
|
* Options for {@link toRelativeString}.
|
|
@@ -8,10 +8,11 @@ import { type FullDate } from '../full-date/full-date-shape.js';
|
|
|
8
8
|
*/
|
|
9
9
|
export type RelativeStringOptions = PartialWithUndefined<{
|
|
10
10
|
/**
|
|
11
|
-
* Set this to `true` to
|
|
12
|
-
*
|
|
11
|
+
* Set this to `true` to block a "just now" string to be used when the two dates are very close
|
|
12
|
+
* or the duration is very small (or 0).
|
|
13
13
|
*
|
|
14
14
|
* @default false // (`'just now'` is used)
|
|
15
|
+
* @see `RelativeStringOptions.justNowThresholds`
|
|
15
16
|
*/
|
|
16
17
|
blockJustNow: boolean;
|
|
17
18
|
/**
|
|
@@ -22,27 +23,61 @@ export type RelativeStringOptions = PartialWithUndefined<{
|
|
|
22
23
|
*/
|
|
23
24
|
useOnlyLargestUnit: boolean;
|
|
24
25
|
/**
|
|
25
|
-
*
|
|
26
|
+
* Any values below this will trigger "just now".
|
|
26
27
|
*
|
|
27
|
-
* @default
|
|
28
|
+
* @default `defaultJustNowThresholds`
|
|
29
|
+
* @see {@link defaultJustNowThresholds} .
|
|
28
30
|
*/
|
|
29
|
-
|
|
31
|
+
justNowThresholds: AnyDuration;
|
|
30
32
|
/**
|
|
31
|
-
*
|
|
33
|
+
* The separator between each unit.
|
|
34
|
+
*
|
|
35
|
+
* @default ', '
|
|
36
|
+
*/
|
|
37
|
+
sep: string;
|
|
38
|
+
/**
|
|
39
|
+
* By default, when `blockJustNow` is `true` and there is no duration to print (the diff is 0),
|
|
40
|
+
* this will return the smallest selected unit set to 0 and use "0 <unit> ago". Set this
|
|
41
|
+
* property to `true` to instead use "in 0 <unit>".
|
|
32
42
|
*
|
|
33
|
-
* @default
|
|
43
|
+
* @default false
|
|
44
|
+
*/
|
|
45
|
+
useFutureWhenNothing: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* If `true`, unit names are abbreviated.
|
|
34
48
|
*
|
|
35
|
-
*
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
49
|
+
* @default false
|
|
50
|
+
*/
|
|
51
|
+
abbreviate: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Customize translations. If this is not provided, or any property is missing, the default
|
|
54
|
+
* english phrases will be used.
|
|
39
55
|
*/
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
56
|
+
i18n: Partial<{
|
|
57
|
+
/** Creates past relative strings like "5 seconds ago". */
|
|
58
|
+
timeAgo(
|
|
59
|
+
/**
|
|
60
|
+
* This will look like "5 seconds" or "1 year", translated to the configured locale (or
|
|
61
|
+
* the user's current locale.
|
|
62
|
+
*/
|
|
63
|
+
unitString: string): string;
|
|
64
|
+
/** Creates future relative strings like "in 5 seconds". */
|
|
65
|
+
timeIn(
|
|
66
|
+
/**
|
|
67
|
+
* This will look like "5 seconds" or "1 year", translated to the configured locale (or
|
|
68
|
+
* the user's current locale.
|
|
69
|
+
*/
|
|
70
|
+
unitString: string): string;
|
|
71
|
+
/** The string to be used when "just now" is chosen. */
|
|
72
|
+
justNow: string;
|
|
73
|
+
}>;
|
|
74
|
+
}> & RequiredAndNotNull<RoundOptions> & LocaleOptions;
|
|
75
|
+
/**
|
|
76
|
+
* Default value for `RelativeStringOptions.justNowThresholds`.
|
|
77
|
+
*
|
|
78
|
+
* @category Internal
|
|
79
|
+
*/
|
|
80
|
+
export declare const defaultJustNowThresholds: AnyDuration;
|
|
46
81
|
/**
|
|
47
82
|
* This function starts with a duration (either by being directly passed a duration or by diffing
|
|
48
83
|
* two dates into a duration) and converts that duration into a relative string like "1 month ago"
|
|
@@ -61,8 +96,12 @@ export type RelativeStringOptions = PartialWithUndefined<{
|
|
|
61
96
|
* toRelativeString({days: 1.6}, {days: true, hours: true}); // `'in 1 day, 14 hours'`
|
|
62
97
|
* toRelativeString({seconds: 1}, selectAllDurationUnits); // `'just now'`
|
|
63
98
|
* ```
|
|
99
|
+
*
|
|
100
|
+
* @throws If no units are selected
|
|
64
101
|
*/
|
|
65
102
|
export declare function toRelativeString(datesOrDuration: Readonly<{
|
|
66
103
|
start: Readonly<FullDate>;
|
|
67
104
|
end: Readonly<FullDate>;
|
|
68
|
-
}> | Readonly<AnyDuration>,
|
|
105
|
+
}> | Readonly<AnyDuration>,
|
|
106
|
+
/** The units to use in the relative string. */
|
|
107
|
+
units: Readonly<DurationUnitSelection>, options: Readonly<RelativeStringOptions>): string;
|
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
import { check } from '@augment-vir/assert';
|
|
2
|
-
import {
|
|
3
|
-
import { convertDuration,
|
|
2
|
+
import { filterMap, } from '@augment-vir/common';
|
|
3
|
+
import { convertDuration, flattenUnitsSmallestToLargest, getDateUnitString, } from '@date-vir/duration';
|
|
4
4
|
import { diffDates } from '../date-operations/diff-dates.js';
|
|
5
|
-
const
|
|
5
|
+
const defaultRelativeStringI18n = {
|
|
6
|
+
justNow: 'just now',
|
|
7
|
+
timeAgo(unitString) {
|
|
8
|
+
return `${unitString} ago`;
|
|
9
|
+
},
|
|
10
|
+
timeIn(unitString) {
|
|
11
|
+
return `in ${unitString}`;
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Default value for `RelativeStringOptions.justNowThresholds`.
|
|
16
|
+
*
|
|
17
|
+
* @category Internal
|
|
18
|
+
*/
|
|
19
|
+
export const defaultJustNowThresholds = {
|
|
6
20
|
minutes: 1.5,
|
|
7
21
|
seconds: 5,
|
|
8
|
-
milliseconds:
|
|
22
|
+
milliseconds: 200,
|
|
9
23
|
};
|
|
10
24
|
/**
|
|
11
25
|
* This function starts with a duration (either by being directly passed a duration or by diffing
|
|
@@ -25,85 +39,136 @@ const defaultJustNowThresholds = {
|
|
|
25
39
|
* toRelativeString({days: 1.6}, {days: true, hours: true}); // `'in 1 day, 14 hours'`
|
|
26
40
|
* toRelativeString({seconds: 1}, selectAllDurationUnits); // `'just now'`
|
|
27
41
|
* ```
|
|
42
|
+
*
|
|
43
|
+
* @throws If no units are selected
|
|
28
44
|
*/
|
|
29
|
-
export function toRelativeString(datesOrDuration,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
45
|
+
export function toRelativeString(datesOrDuration,
|
|
46
|
+
/** The units to use in the relative string. */
|
|
47
|
+
units, options) {
|
|
48
|
+
/**
|
|
49
|
+
* Don't use Luxon's implementation of this (`DateTime.toRelative()`) because it's a hopeless
|
|
50
|
+
* mess.
|
|
51
|
+
*/
|
|
52
|
+
const smallestToLargestSelectedUnit = flattenUnitsSmallestToLargest(units);
|
|
53
|
+
const smallestSelectedUnit = smallestToLargestSelectedUnit[0];
|
|
54
|
+
const largestToSmallestSelectedUnit = smallestToLargestSelectedUnit.toReversed();
|
|
55
|
+
if (smallestSelectedUnit == undefined) {
|
|
56
|
+
throw new Error('No units selected for relative string.');
|
|
34
57
|
}
|
|
35
|
-
const diff =
|
|
36
|
-
|
|
58
|
+
const diff = getRelativeStringDiff({
|
|
59
|
+
datesOrDuration,
|
|
60
|
+
options,
|
|
61
|
+
units,
|
|
62
|
+
largestToSmallestSelectedUnit,
|
|
37
63
|
});
|
|
64
|
+
const unitCounts = {};
|
|
38
65
|
const isDiffPositive = convertDuration(diff, { milliseconds: true }).milliseconds >= 0;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
66
|
+
largestToSmallestSelectedUnit.forEach((unit) => {
|
|
67
|
+
if (options.useOnlyLargestUnit && Object.keys(unitCounts).length) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const unitCount = diff[unit] || 0;
|
|
71
|
+
if (unitCount) {
|
|
72
|
+
unitCounts[unit] = unitCount;
|
|
43
73
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const shouldUseJustNow = !options.blockJustNow &&
|
|
51
|
-
(!check.isLengthAtLeast(unitValues, 1) ||
|
|
52
|
-
(unitValues[0].unit === DurationUnit.Minutes &&
|
|
53
|
-
/* node:coverage ignore next 1 */
|
|
54
|
-
Math.abs(diff.minutes || 0) < justNowThresholds.minutes) ||
|
|
55
|
-
(unitValues[0].unit === DurationUnit.Seconds &&
|
|
56
|
-
/* node:coverage ignore next 1 */
|
|
57
|
-
Math.abs(diff.seconds || 0) < justNowThresholds.seconds) ||
|
|
58
|
-
(unitValues[0].unit === DurationUnit.Milliseconds &&
|
|
59
|
-
/* node:coverage ignore next 1 */
|
|
60
|
-
Math.abs(diff.milliseconds || 0) < justNowThresholds.milliseconds));
|
|
74
|
+
});
|
|
75
|
+
const shouldUseJustNow = determineShouldUseJustNow({ options, smallestSelectedUnit, unitCounts });
|
|
76
|
+
const i18n = {
|
|
77
|
+
...defaultRelativeStringI18n,
|
|
78
|
+
...options.i18n,
|
|
79
|
+
};
|
|
61
80
|
if (shouldUseJustNow) {
|
|
62
|
-
return
|
|
81
|
+
return i18n.justNow;
|
|
63
82
|
}
|
|
64
|
-
else if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
83
|
+
else if (Object.keys(unitCounts).length) {
|
|
84
|
+
const unitStrings = filterMap(largestToSmallestSelectedUnit, (unit) => {
|
|
85
|
+
const unitCount = unitCounts[unit];
|
|
86
|
+
if (unitCount) {
|
|
87
|
+
return getDateUnitString({
|
|
88
|
+
count: Math.abs(unitCount),
|
|
89
|
+
unit,
|
|
90
|
+
locale: options.locale,
|
|
91
|
+
abbreviate: options.abbreviate,
|
|
92
|
+
decimalCount: options.decimalCount,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
}, check.isTruthy);
|
|
99
|
+
const allUnitStrings = unitStrings.join(options.sep ?? ', ');
|
|
100
|
+
if (isDiffPositive) {
|
|
101
|
+
return i18n.timeIn(allUnitStrings);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
return i18n.timeAgo(allUnitStrings);
|
|
68
105
|
}
|
|
69
|
-
return toRelativeString(datesOrDuration, { [unitValues[0].unit]: true }, {
|
|
70
|
-
...options,
|
|
71
|
-
useOnlyLargestUnit: false,
|
|
72
|
-
});
|
|
73
106
|
}
|
|
74
|
-
else
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
107
|
+
else {
|
|
108
|
+
const unitString = getDateUnitString({
|
|
109
|
+
count: 0,
|
|
110
|
+
unit: smallestSelectedUnit,
|
|
111
|
+
locale: options.locale,
|
|
112
|
+
abbreviate: options.abbreviate,
|
|
113
|
+
decimalCount: options.decimalCount,
|
|
114
|
+
});
|
|
115
|
+
if (options.useFutureWhenNothing) {
|
|
116
|
+
return i18n.timeIn(unitString);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
return i18n.timeAgo(unitString);
|
|
120
|
+
}
|
|
85
121
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return
|
|
90
|
-
absoluteQuantity,
|
|
91
|
-
' ',
|
|
92
|
-
singularDurationUnitNames[unit],
|
|
93
|
-
absoluteQuantity > 1 ? 's' : '',
|
|
94
|
-
].join('');
|
|
95
|
-
})
|
|
96
|
-
.join(', ');
|
|
97
|
-
if (isDiffPositive) {
|
|
98
|
-
return [
|
|
99
|
-
'in',
|
|
100
|
-
unitsString,
|
|
101
|
-
].join(' ');
|
|
122
|
+
}
|
|
123
|
+
function getRelativeStringDiff({ datesOrDuration, units, options, largestToSmallestSelectedUnit, }) {
|
|
124
|
+
if (options.useOnlyLargestUnit) {
|
|
125
|
+
return findLargestDiff({ datesOrDuration, largestToSmallestSelectedUnit, options });
|
|
102
126
|
}
|
|
103
127
|
else {
|
|
104
|
-
return
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
128
|
+
return createDiff(datesOrDuration, { decimalCount: undefined }, units);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function createDiff(datesOrDuration, options, units) {
|
|
132
|
+
return 'start' in datesOrDuration
|
|
133
|
+
? diffDates(datesOrDuration, units, options)
|
|
134
|
+
: convertDuration(datesOrDuration, units, options);
|
|
135
|
+
}
|
|
136
|
+
function findLargestDiff({ datesOrDuration, options, largestToSmallestSelectedUnit, }) {
|
|
137
|
+
for (const unit of largestToSmallestSelectedUnit) {
|
|
138
|
+
const innerDiff = createDiff(datesOrDuration, options, {
|
|
139
|
+
[unit]: true,
|
|
140
|
+
});
|
|
141
|
+
if (innerDiff[unit]) {
|
|
142
|
+
return innerDiff;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return {};
|
|
146
|
+
}
|
|
147
|
+
function determineShouldUseJustNow({ options, smallestSelectedUnit, unitCounts, }) {
|
|
148
|
+
if (options.blockJustNow) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
const thresholds = {
|
|
152
|
+
...defaultJustNowThresholds,
|
|
153
|
+
...options.justNowThresholds,
|
|
154
|
+
};
|
|
155
|
+
if (!(smallestSelectedUnit in thresholds) || Object.keys(unitCounts).length > 1) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
if (!Object.keys(unitCounts).length || smallestSelectedUnit in unitCounts) {
|
|
159
|
+
/* node:coverage disable: these fallbacks aren't required at runtime but are required for type safety. */
|
|
160
|
+
/**
|
|
161
|
+
* We've already verify that `smallestSelectedUnit` is in `thresholds` so the `|| 0`
|
|
162
|
+
* fallback is safe.
|
|
163
|
+
*/
|
|
164
|
+
const unitThreshold = thresholds[smallestSelectedUnit] || 0;
|
|
165
|
+
/**
|
|
166
|
+
* We've already verify that `smallestSelectedUnit` is in `unitCounts` so the `|| 0`
|
|
167
|
+
* fallback is safe.
|
|
168
|
+
*/
|
|
169
|
+
const unitValue = unitCounts[smallestSelectedUnit] || 0;
|
|
170
|
+
/* node:coverage enable */
|
|
171
|
+
return unitValue <= unitThreshold;
|
|
108
172
|
}
|
|
173
|
+
return false;
|
|
109
174
|
}
|
|
@@ -8,7 +8,7 @@ import { type FullDate } from './full-date-shape.js';
|
|
|
8
8
|
*
|
|
9
9
|
* @category Internal
|
|
10
10
|
*/
|
|
11
|
-
export declare function toLuxonDateTime(fullDateInput: Readonly<FullDate>): DateTime
|
|
11
|
+
export declare function toLuxonDateTime(fullDateInput: Readonly<FullDate>): DateTime<true>;
|
|
12
12
|
/**
|
|
13
13
|
* Convert a Luxon DateTime object into a {@link FullDate} instance. Used internally inside of
|
|
14
14
|
* date-vir, but could be helpful if you need it. Usually you should prefer using the
|
package/dist/index.d.ts
CHANGED
|
@@ -23,7 +23,6 @@ export * from './full-date/full-date-shape.js';
|
|
|
23
23
|
export * from './full-date/is-valid-full-date.js';
|
|
24
24
|
export * from './full-date/luxon-date-time-conversion.js';
|
|
25
25
|
export * from './full-date/parsing.js';
|
|
26
|
-
export * from './locales.js';
|
|
27
26
|
export * from './timezone/timezone-checks.js';
|
|
28
27
|
export * from './timezone/timezone-names.js';
|
|
29
28
|
export * from './timezone/timezones.js';
|
package/dist/index.js
CHANGED
|
@@ -23,7 +23,6 @@ export * from './full-date/full-date-shape.js';
|
|
|
23
23
|
export * from './full-date/is-valid-full-date.js';
|
|
24
24
|
export * from './full-date/luxon-date-time-conversion.js';
|
|
25
25
|
export * from './full-date/parsing.js';
|
|
26
|
-
export * from './locales.js';
|
|
27
26
|
export * from './timezone/timezone-checks.js';
|
|
28
27
|
export * from './timezone/timezone-names.js';
|
|
29
28
|
export * from './timezone/timezones.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "date-vir",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"description": "Easy and explicit dates and times.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"date",
|
|
@@ -34,25 +34,25 @@
|
|
|
34
34
|
"test:docs": "virmator docs check"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@augment-vir/assert": "^31.
|
|
38
|
-
"@augment-vir/common": "^31.
|
|
39
|
-
"@date-vir/duration": "^
|
|
37
|
+
"@augment-vir/assert": "^31.54.3",
|
|
38
|
+
"@augment-vir/common": "^31.54.3",
|
|
39
|
+
"@date-vir/duration": "^8.1.0",
|
|
40
40
|
"@types/luxon": "^3.7.1",
|
|
41
41
|
"luxon": "^3.7.2",
|
|
42
|
-
"object-shape-tester": "^6.
|
|
43
|
-
"type-fest": "^5.
|
|
42
|
+
"object-shape-tester": "^6.10.0",
|
|
43
|
+
"type-fest": "^5.3.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@augment-vir/test": "^31.
|
|
46
|
+
"@augment-vir/test": "^31.54.3",
|
|
47
47
|
"@web/dev-server-esbuild": "^1.0.4",
|
|
48
48
|
"@web/test-runner": "^0.20.2",
|
|
49
49
|
"@web/test-runner-commands": "^0.9.0",
|
|
50
50
|
"@web/test-runner-playwright": "^0.11.1",
|
|
51
51
|
"@web/test-runner-visual-regression": "^0.10.0",
|
|
52
|
-
"element-vir": "^26.
|
|
52
|
+
"element-vir": "^26.12.1",
|
|
53
53
|
"istanbul-smart-text-reporter": "^1.1.5",
|
|
54
54
|
"markdown-code-example-inserter": "^3.0.3",
|
|
55
|
-
"typedoc": "^0.28.
|
|
55
|
+
"typedoc": "^0.28.15",
|
|
56
56
|
"typescript": "^5.9.3"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
package/dist/locales.d.ts
DELETED