date-vir 3.0.0 → 4.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/dist/cjs/date-operations/diff-dates.js +57 -4
- package/dist/cjs/duration.js +30 -9
- package/dist/cjs/extra-utils/has-date-props.js +25 -0
- package/dist/cjs/extra-utils/js-date-conversion.js +2 -2
- package/dist/cjs/extra-utils/now.js +2 -2
- package/dist/cjs/formatting/formatted-string.js +34 -0
- package/dist/cjs/formatting/html-input.js +37 -0
- package/dist/cjs/formatting/relative-string.js +53 -0
- package/dist/cjs/formatting/simple-strings.js +58 -0
- package/dist/cjs/formatting/timestamp.js +21 -0
- package/dist/cjs/index.js +7 -3
- package/dist/esm/date-operations/diff-dates.d.ts +25 -6
- package/dist/esm/date-operations/diff-dates.js +56 -4
- package/dist/esm/duration.d.ts +42 -14
- package/dist/esm/duration.js +29 -8
- package/dist/esm/extra-utils/has-date-props.d.ts +8 -0
- package/dist/esm/extra-utils/has-date-props.js +20 -0
- package/dist/esm/extra-utils/js-date-conversion.js +1 -1
- package/dist/esm/extra-utils/now.d.ts +1 -1
- package/dist/esm/extra-utils/now.js +1 -1
- package/dist/esm/extra-utils/zero.d.ts +1 -1
- package/dist/esm/formatting/formatted-string.d.ts +14 -0
- package/dist/esm/formatting/formatted-string.js +29 -0
- package/dist/esm/{full-date/primitive-conversions.d.ts → formatting/html-input.d.ts} +2 -19
- package/dist/esm/formatting/html-input.js +33 -0
- package/dist/esm/formatting/relative-string.d.ts +25 -0
- package/dist/esm/formatting/relative-string.js +49 -0
- package/dist/esm/formatting/simple-strings.d.ts +71 -0
- package/dist/esm/formatting/simple-strings.js +51 -0
- package/dist/esm/formatting/timestamp.d.ts +6 -0
- package/dist/esm/formatting/timestamp.js +16 -0
- package/dist/esm/index.d.ts +7 -3
- package/dist/esm/index.js +7 -3
- package/package.json +27 -23
- package/dist/cjs/augments/type.js +0 -2
- package/dist/cjs/full-date/primitive-conversions.js +0 -102
- package/dist/esm/augments/type.d.ts +0 -2
- package/dist/esm/augments/type.js +0 -1
- package/dist/esm/full-date/primitive-conversions.js +0 -94
- /package/dist/cjs/{full-date → formatting}/string-format-types.js +0 -0
- /package/dist/esm/{full-date → formatting}/string-format-types.d.ts +0 -0
- /package/dist/esm/{full-date → formatting}/string-format-types.js +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function hasDateProps(dateInput, keys) {
|
|
2
|
+
try {
|
|
3
|
+
assertHasDateProps(dateInput, keys);
|
|
4
|
+
return true;
|
|
5
|
+
}
|
|
6
|
+
catch (error) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function assertHasDateProps(dateInput, keys) {
|
|
11
|
+
const missingKeys = [];
|
|
12
|
+
keys.forEach((key) => {
|
|
13
|
+
if (dateInput[key] == undefined) {
|
|
14
|
+
missingKeys.push(key);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
if (missingKeys.length) {
|
|
18
|
+
throw new Error(`Missing required FullDate key(s): ${missingKeys.join(', ')}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
+
import { UtcIsoString } from '../formatting/string-format-types';
|
|
1
2
|
import { FullDate } from '../full-date/full-date-shape';
|
|
2
|
-
import { UtcIsoString } from '../full-date/string-format-types';
|
|
3
3
|
export declare function getNowInIsoString(): UtcIsoString;
|
|
4
4
|
export declare function getNowInUserTimezone(): FullDate;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { toIsoString } from '../formatting/timestamp';
|
|
1
2
|
import { getNowFullDate } from '../full-date/create-full-date';
|
|
2
|
-
import { toIsoString } from '../full-date/primitive-conversions';
|
|
3
3
|
import { userTimezone, utcTimezone } from '../timezone/timezones';
|
|
4
4
|
export function getNowInIsoString() {
|
|
5
5
|
/**
|
|
@@ -16,6 +16,6 @@ export declare const zeroTime: Pick<{
|
|
|
16
16
|
minute: 0;
|
|
17
17
|
second: 0;
|
|
18
18
|
millisecond: 0;
|
|
19
|
-
}, "
|
|
19
|
+
}, "millisecond" | "second" | "minute" | "hour">;
|
|
20
20
|
export declare function clearTime(inputFullDate: Readonly<FullDate>): FullDate;
|
|
21
21
|
export declare function clearParts(inputFullDate: Readonly<FullDate>, parts: ReadonlyArray<Exclude<keyof FullDate, 'timezone'>>): FullDate;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PartialAndUndefined } from '@augment-vir/common';
|
|
2
|
+
import { FullDate } from '../full-date/full-date-shape';
|
|
3
|
+
/** Converts the given FullDate into a string in the user's locale, or the given localeOverride. */
|
|
4
|
+
export declare function toLocaleString(fullDate: FullDate, formatOptions?: (Intl.DateTimeFormatOptions & PartialAndUndefined<{
|
|
5
|
+
locale: string;
|
|
6
|
+
}>) | undefined): string;
|
|
7
|
+
/**
|
|
8
|
+
* Provides arbitrary date formatting using Luxon. For full details on the options for the format
|
|
9
|
+
* string input, see https://moment.github.io/luxon/#/formatting?id=table-of-tokens
|
|
10
|
+
*
|
|
11
|
+
* You probably should **prefer toLocaleString** so your users see the format they expect. It
|
|
12
|
+
* already has many formatting options.
|
|
13
|
+
*/
|
|
14
|
+
export declare function toFormattedString(fullDate: FullDate, format: string, localeOverride?: string): string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { toLuxonDateTime } from '../full-date/luxon-date-time-conversion';
|
|
2
|
+
import { userLocale } from '../locales';
|
|
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.fromCharCode(8239), 'g'), ' ');
|
|
9
|
+
}
|
|
10
|
+
/** Converts the given FullDate into a string in the user's locale, or the given localeOverride. */
|
|
11
|
+
export function toLocaleString(fullDate, formatOptions) {
|
|
12
|
+
const localeString = toLuxonDateTime(fullDate).toLocaleString({
|
|
13
|
+
...formatOptions,
|
|
14
|
+
}, {
|
|
15
|
+
locale: formatOptions?.locale ?? userLocale,
|
|
16
|
+
});
|
|
17
|
+
return fixChromiumSpace(localeString);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Provides arbitrary date formatting using Luxon. For full details on the options for the format
|
|
21
|
+
* string input, see https://moment.github.io/luxon/#/formatting?id=table-of-tokens
|
|
22
|
+
*
|
|
23
|
+
* You probably should **prefer toLocaleString** so your users see the format they expect. It
|
|
24
|
+
* already has many formatting options.
|
|
25
|
+
*/
|
|
26
|
+
export function toFormattedString(fullDate, format, localeOverride = userLocale) {
|
|
27
|
+
const formattedString = toLuxonDateTime(fullDate).toFormat(format, { locale: localeOverride });
|
|
28
|
+
return fixChromiumSpace(formattedString);
|
|
29
|
+
}
|
|
@@ -1,22 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { DateTimeString, DateTimeWithSeconds, JustDateString, JustTimeString, JustTimeWithSecondsString, UtcIsoString } from './string-format-types';
|
|
4
|
-
/** Convert a FullDate into a unix timestamp with milliseconds. */
|
|
5
|
-
export declare function toTimestamp(fullDate: FullDate): number;
|
|
6
|
-
/** Convert a FullDate into an ISO string in UTC; always ends in Z. */
|
|
7
|
-
export declare function toIsoString(fullDate: FullDate): UtcIsoString;
|
|
8
|
-
/** Converts the given FullDate into a string in the user's locale, or the given localeOverride. */
|
|
9
|
-
export declare function toLocaleString(fullDate: FullDate, formatOptions?: (Intl.DateTimeFormatOptions & PartialAndUndefined<{
|
|
10
|
-
locale: string;
|
|
11
|
-
}>) | undefined): string;
|
|
12
|
-
/**
|
|
13
|
-
* Provides arbitrary date formatting using Luxon. For full details on the options for the format
|
|
14
|
-
* string input, see https://moment.github.io/luxon/#/formatting?id=table-of-tokens
|
|
15
|
-
*
|
|
16
|
-
* You probably should **prefer toLocaleString** so your users see the format they expect. It
|
|
17
|
-
* already has many formatting options.
|
|
18
|
-
*/
|
|
19
|
-
export declare function toFormattedString(fullDate: FullDate, format: string, localeOverride?: string): string;
|
|
1
|
+
import { FullDate, FullDatePartEnum, OnlyDatePart, OnlyHourMinutePart, OnlyHourMinuteSecondPart } from '../full-date/full-date-shape';
|
|
2
|
+
import { DateTimeString, DateTimeWithSeconds, JustDateString, JustTimeString, JustTimeWithSecondsString } from './string-format-types';
|
|
20
3
|
/**
|
|
21
4
|
* Converts a FullDate object into a string that is understood by type="date" or type="time"
|
|
22
5
|
* HTMLInputElement instances. Can optionally include seconds as well for type="time".
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { getEnumTypedValues } from '@augment-vir/common';
|
|
2
|
+
import { assertHasDateProps } from '../extra-utils/has-date-props';
|
|
3
|
+
import { FullDatePartEnum, } from '../full-date/full-date-shape';
|
|
4
|
+
import { toSimpleDatePartString, toSimpleTimePartString } from './simple-strings';
|
|
5
|
+
export function toHtmlInputString(fullDate, inputType, includeSeconds) {
|
|
6
|
+
const internalFullDate = fullDate;
|
|
7
|
+
if (inputType === FullDatePartEnum.Date) {
|
|
8
|
+
assertHasDateProps(internalFullDate, [
|
|
9
|
+
'year',
|
|
10
|
+
'month',
|
|
11
|
+
'day',
|
|
12
|
+
]);
|
|
13
|
+
return toSimpleDatePartString(internalFullDate);
|
|
14
|
+
}
|
|
15
|
+
else if (inputType === FullDatePartEnum.Time) {
|
|
16
|
+
if (includeSeconds && internalFullDate.second == undefined) {
|
|
17
|
+
throw new Error('Tried to include seconds in the time string but no seconds were provided.');
|
|
18
|
+
}
|
|
19
|
+
assertHasDateProps(internalFullDate, [
|
|
20
|
+
'hour',
|
|
21
|
+
'minute',
|
|
22
|
+
]);
|
|
23
|
+
return toSimpleTimePartString(internalFullDate, !!includeSeconds);
|
|
24
|
+
}
|
|
25
|
+
else if (inputType === FullDatePartEnum.DateTime) {
|
|
26
|
+
const datePart = toHtmlInputString(fullDate, FullDatePartEnum.Date);
|
|
27
|
+
const timePart = toHtmlInputString(fullDate, FullDatePartEnum.Time, includeSeconds);
|
|
28
|
+
return `${datePart}T${timePart}`;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
throw new Error(`Unexpected inputTyped: '${inputType}'. Expected usage of FullDatePartEnum or one of ${getEnumTypedValues(FullDatePartEnum).join(', ')}.`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { PartialAndUndefined } from '@augment-vir/common';
|
|
2
|
+
import { DurationUnit } from '../duration';
|
|
3
|
+
import { FullDate } from '../full-date/full-date-shape';
|
|
4
|
+
export type RelativeStringOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* The relative units that the relative string function is not allowed to use. By default, all
|
|
7
|
+
* units are allowed. Thus, you can use this to selectively disable some of them.
|
|
8
|
+
*/
|
|
9
|
+
blockedRelativeUnits: ReadonlyArray<DurationUnit>;
|
|
10
|
+
/**
|
|
11
|
+
* The number of digits to round the relative number value to. Defaults to 0, meaning there will
|
|
12
|
+
* be no decimal digits.
|
|
13
|
+
*
|
|
14
|
+
* Example output: {decimalDigitCount: 4} can result in values like 5.6789 whereas
|
|
15
|
+
* {decimalDigitCount: 0} will result in values like 6.
|
|
16
|
+
*/
|
|
17
|
+
decimalDigitCount: number;
|
|
18
|
+
/** Set this to true to block the 'just now' relative string. By default, that string is allowed. */
|
|
19
|
+
blockJustNow: true;
|
|
20
|
+
};
|
|
21
|
+
export declare function toRelativeString({ fullDate, relativeTo, options, }: {
|
|
22
|
+
fullDate: Readonly<FullDate>;
|
|
23
|
+
relativeTo: Readonly<FullDate>;
|
|
24
|
+
options?: PartialAndUndefined<RelativeStringOptions>;
|
|
25
|
+
}): string | undefined;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { mapObjectValues, round } from '@augment-vir/common';
|
|
2
|
+
import { diffDatesAllUnits } from '../date-operations/diff-dates';
|
|
3
|
+
import { DurationUnit, orderedDurationUnits, singularDurationUnitNames } from '../duration';
|
|
4
|
+
export function toRelativeString({ fullDate, relativeTo, options = {}, }) {
|
|
5
|
+
const roundingDigits = options.decimalDigitCount || 0;
|
|
6
|
+
const allUnitDiffs = diffDatesAllUnits({
|
|
7
|
+
start: fullDate,
|
|
8
|
+
end: relativeTo,
|
|
9
|
+
});
|
|
10
|
+
const unitsWithinBounds = mapObjectValues(allUnitDiffs, (durationUnit, duration) => {
|
|
11
|
+
const isAboveZero = Math.floor(Math.abs(round({ digits: 1, number: duration }))) > 0;
|
|
12
|
+
return isAboveZero;
|
|
13
|
+
});
|
|
14
|
+
const unitToUse = orderedDurationUnits.reduce((chosenUnit, currentUnit) => {
|
|
15
|
+
const isUnitAllowed = !options.blockedRelativeUnits?.includes(currentUnit);
|
|
16
|
+
if (isUnitAllowed && unitsWithinBounds[currentUnit]) {
|
|
17
|
+
return currentUnit;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
return chosenUnit;
|
|
21
|
+
}
|
|
22
|
+
}, undefined);
|
|
23
|
+
const shouldUseJustNow = options.blockJustNow
|
|
24
|
+
? false
|
|
25
|
+
: (unitToUse === DurationUnit.Minutes && allUnitDiffs.minutes < 2) ||
|
|
26
|
+
(unitToUse === DurationUnit.Seconds && allUnitDiffs.seconds < 11) ||
|
|
27
|
+
(unitToUse === DurationUnit.Milliseconds && allUnitDiffs.milliseconds < 710);
|
|
28
|
+
/** Some short circuits. */
|
|
29
|
+
if (unitToUse == undefined) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
else if (shouldUseJustNow) {
|
|
33
|
+
return 'just now';
|
|
34
|
+
}
|
|
35
|
+
const duration = allUnitDiffs[unitToUse];
|
|
36
|
+
const roundedAbsoluteDuration = Math.abs(round({ digits: roundingDigits, number: duration }));
|
|
37
|
+
const isDurationSingular = roundedAbsoluteDuration === 1;
|
|
38
|
+
const unitName = [
|
|
39
|
+
singularDurationUnitNames[unitToUse],
|
|
40
|
+
isDurationSingular ? '' : 's',
|
|
41
|
+
].join('');
|
|
42
|
+
const value = isDurationSingular ? 'a' : roundedAbsoluteDuration;
|
|
43
|
+
if (duration < 0) {
|
|
44
|
+
return `in ${value} ${unitName}`;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
return `${value} ${unitName} ago`;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { FullDate } from '../full-date/full-date-shape';
|
|
2
|
+
import { JustDateString, JustTimeString, JustTimeWithSecondsString } from './string-format-types';
|
|
3
|
+
/**
|
|
4
|
+
* Create a string based on just the date parts of a FullDate.
|
|
5
|
+
*
|
|
6
|
+
* CAUTION: this does not user locale setting and should therefore not be used for user-facing date
|
|
7
|
+
* formatting. Prefer using `toLocaleString` instead for user-facing strings.
|
|
8
|
+
*
|
|
9
|
+
* Example output: `'2023-12-05'`
|
|
10
|
+
*/
|
|
11
|
+
export declare function toSimpleDatePartString(fullDate: Pick<FullDate, 'year' | 'month' | 'day'>): JustDateString;
|
|
12
|
+
/**
|
|
13
|
+
* Creates a string based on just the time parts of a FullDate.
|
|
14
|
+
*
|
|
15
|
+
* CAUTION: this does not user locale setting and should therefore not be used for user-facing date
|
|
16
|
+
* formatting. Prefer using `toLocaleString` instead for user-facing strings.
|
|
17
|
+
*
|
|
18
|
+
* Example output: `'05:32:21'`
|
|
19
|
+
*/
|
|
20
|
+
export declare function toSimpleTimePartString(fullDate: Pick<FullDate, 'hour' | 'minute' | 'second'>, includeSeconds: true): JustTimeWithSecondsString;
|
|
21
|
+
export declare function toSimpleTimePartString(fullDate: Pick<FullDate, 'hour' | 'minute'>, includeSeconds: false): JustTimeString;
|
|
22
|
+
export declare function toSimpleTimePartString(fullDate: Pick<FullDate, 'hour' | 'minute' | 'second'> | Pick<FullDate, 'hour' | 'minute'>, includeSeconds: boolean): JustTimeWithSecondsString | JustTimeString;
|
|
23
|
+
export type FullDateForParts = Omit<FullDate, 'millisecond'>;
|
|
24
|
+
/**
|
|
25
|
+
* Splits a FullDate up into multiple formatted string representations.
|
|
26
|
+
*
|
|
27
|
+
* CAUTION: this does not user locale setting and should therefore not be used for user-facing date
|
|
28
|
+
* formatting. Prefer using `toLocaleString` instead for user-facing strings.
|
|
29
|
+
*
|
|
30
|
+
* This does not expand month names into the full names, it just uses numbers for everything. The
|
|
31
|
+
* output of this will look like:
|
|
32
|
+
*
|
|
33
|
+
* ```typescript
|
|
34
|
+
* {
|
|
35
|
+
* "date": "2012-12-05",
|
|
36
|
+
* "time": "05:32:21",
|
|
37
|
+
* "timezone": "UTC"
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function toSimplePartStrings(fullDate: FullDateForParts, options: {
|
|
42
|
+
includeSeconds: true;
|
|
43
|
+
}): {
|
|
44
|
+
date: JustDateString;
|
|
45
|
+
time: JustTimeWithSecondsString;
|
|
46
|
+
timezone: string;
|
|
47
|
+
};
|
|
48
|
+
export declare function toSimplePartStrings(fullDate: FullDateForParts, options: {
|
|
49
|
+
includeSeconds: false;
|
|
50
|
+
}): {
|
|
51
|
+
date: JustDateString;
|
|
52
|
+
time: JustTimeString;
|
|
53
|
+
timezone: string;
|
|
54
|
+
};
|
|
55
|
+
export declare function toSimplePartStrings(fullDate: FullDateForParts, options: {
|
|
56
|
+
includeSeconds: boolean;
|
|
57
|
+
}): {
|
|
58
|
+
date: JustDateString;
|
|
59
|
+
time: JustTimeWithSecondsString | JustTimeString;
|
|
60
|
+
timezone: string;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Converts a date into a simple, unambiguous date string.
|
|
64
|
+
*
|
|
65
|
+
* CAUTION: this does not user locale setting and should therefore not be used for user-facing date
|
|
66
|
+
* formatting. Prefer using `toLocaleString` instead for user-facing strings.
|
|
67
|
+
*/
|
|
68
|
+
export declare function toSimpleString(fullDate: FullDateForParts, options: {
|
|
69
|
+
includeSeconds: boolean;
|
|
70
|
+
includeTimezone: boolean;
|
|
71
|
+
}): string;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { isTruthy, typedHasProperty } from '@augment-vir/common';
|
|
2
|
+
/**
|
|
3
|
+
* Create a string based on just the date parts of a FullDate.
|
|
4
|
+
*
|
|
5
|
+
* CAUTION: this does not user locale setting and should therefore not be used for user-facing date
|
|
6
|
+
* formatting. Prefer using `toLocaleString` instead for user-facing strings.
|
|
7
|
+
*
|
|
8
|
+
* Example output: `'2023-12-05'`
|
|
9
|
+
*/
|
|
10
|
+
export function toSimpleDatePartString(fullDate) {
|
|
11
|
+
const dateParts = [
|
|
12
|
+
String(Math.abs(fullDate.year)).padStart(4, '0'),
|
|
13
|
+
String(Math.abs(fullDate.month)).padStart(2, '0'),
|
|
14
|
+
String(Math.abs(fullDate.day)).padStart(2, '0'),
|
|
15
|
+
];
|
|
16
|
+
const dateString = dateParts.join('-');
|
|
17
|
+
return dateString;
|
|
18
|
+
}
|
|
19
|
+
export function toSimpleTimePartString(fullDate, includeSeconds) {
|
|
20
|
+
const seconds = typedHasProperty(fullDate, 'second') && includeSeconds
|
|
21
|
+
? String(Math.abs(fullDate.second)).padStart(2, '0')
|
|
22
|
+
: undefined;
|
|
23
|
+
const timeParts = [
|
|
24
|
+
String(Math.abs(fullDate.hour)).padStart(2, '0'),
|
|
25
|
+
String(Math.abs(fullDate.minute)).padStart(2, '0'),
|
|
26
|
+
seconds,
|
|
27
|
+
].filter(isTruthy);
|
|
28
|
+
return timeParts.join(':');
|
|
29
|
+
}
|
|
30
|
+
export function toSimplePartStrings(fullDate, options) {
|
|
31
|
+
return {
|
|
32
|
+
date: toSimpleDatePartString(fullDate),
|
|
33
|
+
time: toSimpleTimePartString(fullDate, options.includeSeconds),
|
|
34
|
+
timezone: fullDate.timezone,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Converts a date into a simple, unambiguous date string.
|
|
39
|
+
*
|
|
40
|
+
* CAUTION: this does not user locale setting and should therefore not be used for user-facing date
|
|
41
|
+
* formatting. Prefer using `toLocaleString` instead for user-facing strings.
|
|
42
|
+
*/
|
|
43
|
+
export function toSimpleString(fullDate, options) {
|
|
44
|
+
const parts = toSimplePartStrings(fullDate, options);
|
|
45
|
+
const stringParts = [
|
|
46
|
+
parts.date,
|
|
47
|
+
parts.time,
|
|
48
|
+
options.includeTimezone && `(${parts.timezone})`,
|
|
49
|
+
].filter(isTruthy);
|
|
50
|
+
return stringParts.join(' ');
|
|
51
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { FullDate } from '../full-date/full-date-shape';
|
|
2
|
+
import { UtcIsoString } from './string-format-types';
|
|
3
|
+
/** Convert a FullDate into a unix timestamp with milliseconds. */
|
|
4
|
+
export declare function toTimestamp(fullDate: FullDate): number;
|
|
5
|
+
/** Convert a FullDate into an ISO string in UTC; always ends in Z. */
|
|
6
|
+
export declare function toIsoString(fullDate: FullDate): UtcIsoString;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { toLuxonDateTime } from '../full-date/luxon-date-time-conversion';
|
|
2
|
+
import { utcTimezone } from '../timezone/timezones';
|
|
3
|
+
/** Convert a FullDate into a unix timestamp with milliseconds. */
|
|
4
|
+
export function toTimestamp(fullDate) {
|
|
5
|
+
return toLuxonDateTime(fullDate).toMillis();
|
|
6
|
+
}
|
|
7
|
+
/** Convert a FullDate into an ISO string in UTC; always ends in Z. */
|
|
8
|
+
export function toIsoString(fullDate) {
|
|
9
|
+
const isoString = toLuxonDateTime(fullDate).setZone(utcTimezone).toISO();
|
|
10
|
+
/** Ignore this edge case in the types and idk how to trigger it. */
|
|
11
|
+
/* c8 ignore next 3 */
|
|
12
|
+
if (!isoString) {
|
|
13
|
+
throw new Error(`Unable to get ISO string for '${JSON.stringify(fullDate)}'`);
|
|
14
|
+
}
|
|
15
|
+
return isoString;
|
|
16
|
+
}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
export * from './augments/type';
|
|
2
1
|
export * from './date-operations/calculate-relative-date';
|
|
3
2
|
export * from './date-operations/combine-dates';
|
|
4
3
|
export * from './date-operations/diff-dates';
|
|
5
4
|
export * from './duration';
|
|
6
5
|
export * from './extra-utils/date-transforms';
|
|
6
|
+
export * from './extra-utils/has-date-props';
|
|
7
7
|
export * from './extra-utils/js-date-conversion';
|
|
8
8
|
export * from './extra-utils/now';
|
|
9
9
|
export * from './extra-utils/zero';
|
|
10
|
+
export * from './formatting/formatted-string';
|
|
11
|
+
export * from './formatting/html-input';
|
|
12
|
+
export * from './formatting/relative-string';
|
|
13
|
+
export * from './formatting/simple-strings';
|
|
14
|
+
export * from './formatting/string-format-types';
|
|
15
|
+
export * from './formatting/timestamp';
|
|
10
16
|
export * from './full-date/create-full-date';
|
|
11
17
|
export * from './full-date/date-like';
|
|
12
18
|
export * from './full-date/format-presets';
|
|
@@ -14,8 +20,6 @@ export * from './full-date/full-date-shape';
|
|
|
14
20
|
export * from './full-date/is-valid-full-date';
|
|
15
21
|
export * from './full-date/luxon-date-time-conversion';
|
|
16
22
|
export * from './full-date/parsing';
|
|
17
|
-
export * from './full-date/primitive-conversions';
|
|
18
|
-
export * from './full-date/string-format-types';
|
|
19
23
|
export * from './locales';
|
|
20
24
|
export * from './timezone/timezone-checks';
|
|
21
25
|
export * from './timezone/timezone-names';
|
package/dist/esm/index.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
export * from './augments/type';
|
|
2
1
|
export * from './date-operations/calculate-relative-date';
|
|
3
2
|
export * from './date-operations/combine-dates';
|
|
4
3
|
export * from './date-operations/diff-dates';
|
|
5
4
|
export * from './duration';
|
|
6
5
|
export * from './extra-utils/date-transforms';
|
|
6
|
+
export * from './extra-utils/has-date-props';
|
|
7
7
|
export * from './extra-utils/js-date-conversion';
|
|
8
8
|
export * from './extra-utils/now';
|
|
9
9
|
export * from './extra-utils/zero';
|
|
10
|
+
export * from './formatting/formatted-string';
|
|
11
|
+
export * from './formatting/html-input';
|
|
12
|
+
export * from './formatting/relative-string';
|
|
13
|
+
export * from './formatting/simple-strings';
|
|
14
|
+
export * from './formatting/string-format-types';
|
|
15
|
+
export * from './formatting/timestamp';
|
|
10
16
|
export * from './full-date/create-full-date';
|
|
11
17
|
export * from './full-date/date-like';
|
|
12
18
|
export * from './full-date/format-presets';
|
|
@@ -14,8 +20,6 @@ export * from './full-date/full-date-shape';
|
|
|
14
20
|
export * from './full-date/is-valid-full-date';
|
|
15
21
|
export * from './full-date/luxon-date-time-conversion';
|
|
16
22
|
export * from './full-date/parsing';
|
|
17
|
-
export * from './full-date/primitive-conversions';
|
|
18
|
-
export * from './full-date/string-format-types';
|
|
19
23
|
export * from './locales';
|
|
20
24
|
export * from './timezone/timezone-checks';
|
|
21
25
|
export * from './timezone/timezone-names';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "date-vir",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Easy and explicit dates and times",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"date",
|
|
@@ -41,41 +41,45 @@
|
|
|
41
41
|
"test:watch": "web-test-runner --watch --color --config configs/web-test-runner.config.mjs"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@augment-vir/common": "^21.
|
|
45
|
-
"@types/luxon": "^3.3.
|
|
46
|
-
"luxon": "^3.4.
|
|
47
|
-
"object-shape-tester": "^1.0.
|
|
48
|
-
"type-fest": "^4.
|
|
44
|
+
"@augment-vir/common": "^21.6.0",
|
|
45
|
+
"@types/luxon": "^3.3.4",
|
|
46
|
+
"luxon": "^3.4.4",
|
|
47
|
+
"object-shape-tester": "^1.0.1",
|
|
48
|
+
"type-fest": "^4.7.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@augment-vir/browser": "^21.
|
|
52
|
-
"@augment-vir/browser-testing": "^21.
|
|
53
|
-
"@open-wc/testing": "^
|
|
54
|
-
"@types/chai": "^4.3.
|
|
55
|
-
"@types/mocha": "^10.0.
|
|
56
|
-
"@web/dev-server-esbuild": "^0.
|
|
57
|
-
"@web/test-runner": "^0.
|
|
58
|
-
"@web/test-runner-commands": "^0.
|
|
59
|
-
"@web/test-runner-playwright": "^0.
|
|
60
|
-
"@web/test-runner-visual-regression": "^0.
|
|
61
|
-
"cspell": "^
|
|
62
|
-
"dependency-cruiser": "^15.
|
|
63
|
-
"element-vir": "^16.5.
|
|
51
|
+
"@augment-vir/browser": "^21.6.0",
|
|
52
|
+
"@augment-vir/browser-testing": "^21.6.0",
|
|
53
|
+
"@open-wc/testing": "^4.0.0",
|
|
54
|
+
"@types/chai": "^4.3.10",
|
|
55
|
+
"@types/mocha": "^10.0.4",
|
|
56
|
+
"@web/dev-server-esbuild": "^1.0.0",
|
|
57
|
+
"@web/test-runner": "^0.18.0",
|
|
58
|
+
"@web/test-runner-commands": "^0.9.0",
|
|
59
|
+
"@web/test-runner-playwright": "^0.11.0",
|
|
60
|
+
"@web/test-runner-visual-regression": "^0.9.0",
|
|
61
|
+
"cspell": "^8.0.0",
|
|
62
|
+
"dependency-cruiser": "^15.3.0",
|
|
63
|
+
"element-vir": "^16.5.2",
|
|
64
64
|
"esbuild": "^0.19.5",
|
|
65
65
|
"istanbul-smart-text-reporter": "^1.1.2",
|
|
66
66
|
"markdown-code-example-inserter": "^0.3.2",
|
|
67
67
|
"npm-check-updates": "~16.12.3",
|
|
68
|
-
"prettier": "^3.0
|
|
68
|
+
"prettier": "^3.1.0",
|
|
69
69
|
"prettier-plugin-interpolated-html-tags": "^1.0.2",
|
|
70
70
|
"prettier-plugin-jsdoc": "^1.1.1",
|
|
71
71
|
"prettier-plugin-multiline-arrays": "^3.0.0",
|
|
72
|
-
"prettier-plugin-organize-imports": "^3.2.
|
|
72
|
+
"prettier-plugin-organize-imports": "^3.2.4",
|
|
73
73
|
"prettier-plugin-packagejson": "^2.4.6",
|
|
74
74
|
"prettier-plugin-sort-json": "^3.1.0",
|
|
75
75
|
"prettier-plugin-toml": "^1.0.0",
|
|
76
76
|
"run-time-assertions": "^0.1.3",
|
|
77
|
-
"typedoc": "^0.25.
|
|
77
|
+
"typedoc": "^0.25.3",
|
|
78
78
|
"typescript": "^5.2.2",
|
|
79
|
-
"virmator": "^
|
|
79
|
+
"virmator": "^11.1.0"
|
|
80
|
+
},
|
|
81
|
+
"overrides": {
|
|
82
|
+
"@open-wc/scoped-elements": "2.2.3",
|
|
83
|
+
"@open-wc/testing-helpers": "2.3.1"
|
|
80
84
|
}
|
|
81
85
|
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toHtmlInputString = exports.toFormattedString = exports.toLocaleString = exports.toIsoString = exports.toTimestamp = void 0;
|
|
4
|
-
const common_1 = require("@augment-vir/common");
|
|
5
|
-
const locales_1 = require("../locales");
|
|
6
|
-
const timezones_1 = require("../timezone/timezones");
|
|
7
|
-
const full_date_shape_1 = require("./full-date-shape");
|
|
8
|
-
const luxon_date_time_conversion_1 = require("./luxon-date-time-conversion");
|
|
9
|
-
/** Convert a FullDate into a unix timestamp with milliseconds. */
|
|
10
|
-
function toTimestamp(fullDate) {
|
|
11
|
-
return (0, luxon_date_time_conversion_1.toLuxonDateTime)(fullDate).toMillis();
|
|
12
|
-
}
|
|
13
|
-
exports.toTimestamp = toTimestamp;
|
|
14
|
-
/** Convert a FullDate into an ISO string in UTC; always ends in Z. */
|
|
15
|
-
function toIsoString(fullDate) {
|
|
16
|
-
const isoString = (0, luxon_date_time_conversion_1.toLuxonDateTime)(fullDate).setZone(timezones_1.utcTimezone).toISO();
|
|
17
|
-
/** Ignore this edge case in the types and idk how to trigger it. */
|
|
18
|
-
/* c8 ignore next 3 */
|
|
19
|
-
if (!isoString) {
|
|
20
|
-
throw new Error(`Unable to get ISO string for '${JSON.stringify(fullDate)}'`);
|
|
21
|
-
}
|
|
22
|
-
return isoString;
|
|
23
|
-
}
|
|
24
|
-
exports.toIsoString = toIsoString;
|
|
25
|
-
/**
|
|
26
|
-
* Chromium has a weird behavior where the "NARROW NO-BREAK SPACE" character (code 8239) is used
|
|
27
|
-
* instead of a space (code 32) before AM/PM.
|
|
28
|
-
*/
|
|
29
|
-
function fixChromiumSpace(original) {
|
|
30
|
-
return original.replace(new RegExp(String.fromCharCode(8239), 'g'), ' ');
|
|
31
|
-
}
|
|
32
|
-
/** Converts the given FullDate into a string in the user's locale, or the given localeOverride. */
|
|
33
|
-
function toLocaleString(fullDate, formatOptions) {
|
|
34
|
-
const localeString = (0, luxon_date_time_conversion_1.toLuxonDateTime)(fullDate).toLocaleString({
|
|
35
|
-
...formatOptions,
|
|
36
|
-
}, {
|
|
37
|
-
locale: formatOptions?.locale ?? locales_1.userLocale,
|
|
38
|
-
});
|
|
39
|
-
return fixChromiumSpace(localeString);
|
|
40
|
-
}
|
|
41
|
-
exports.toLocaleString = toLocaleString;
|
|
42
|
-
/**
|
|
43
|
-
* Provides arbitrary date formatting using Luxon. For full details on the options for the format
|
|
44
|
-
* string input, see https://moment.github.io/luxon/#/formatting?id=table-of-tokens
|
|
45
|
-
*
|
|
46
|
-
* You probably should **prefer toLocaleString** so your users see the format they expect. It
|
|
47
|
-
* already has many formatting options.
|
|
48
|
-
*/
|
|
49
|
-
function toFormattedString(fullDate, format, localeOverride = locales_1.userLocale) {
|
|
50
|
-
const formattedString = (0, luxon_date_time_conversion_1.toLuxonDateTime)(fullDate).toFormat(format, { locale: localeOverride });
|
|
51
|
-
return fixChromiumSpace(formattedString);
|
|
52
|
-
}
|
|
53
|
-
exports.toFormattedString = toFormattedString;
|
|
54
|
-
function toHtmlInputString(fullDate, inputType, includeSeconds) {
|
|
55
|
-
const internalFullDate = fullDate;
|
|
56
|
-
if (inputType === full_date_shape_1.FullDatePartEnum.Date) {
|
|
57
|
-
if (internalFullDate.year == undefined) {
|
|
58
|
-
throw new Error(`Tried to create date string but no year was provided.`);
|
|
59
|
-
}
|
|
60
|
-
if (internalFullDate.month == undefined) {
|
|
61
|
-
throw new Error(`Tried to create date string but no month was provided.`);
|
|
62
|
-
}
|
|
63
|
-
if (internalFullDate.day == undefined) {
|
|
64
|
-
throw new Error(`Tried to create date string but no day was provided.`);
|
|
65
|
-
}
|
|
66
|
-
const dateParts = [
|
|
67
|
-
String(Math.abs(internalFullDate.year)).padStart(4, '0'),
|
|
68
|
-
String(Math.abs(internalFullDate.month)).padStart(2, '0'),
|
|
69
|
-
String(Math.abs(internalFullDate.day)).padStart(2, '0'),
|
|
70
|
-
];
|
|
71
|
-
return dateParts.join('-');
|
|
72
|
-
}
|
|
73
|
-
else if (inputType === full_date_shape_1.FullDatePartEnum.Time) {
|
|
74
|
-
const seconds = includeSeconds
|
|
75
|
-
? String(Math.abs(internalFullDate.second ?? 0)).padStart(2, '0')
|
|
76
|
-
: undefined;
|
|
77
|
-
if (includeSeconds && internalFullDate.second == undefined) {
|
|
78
|
-
throw new Error('Tried to include seconds in the time string but no seconds were provided.');
|
|
79
|
-
}
|
|
80
|
-
if (internalFullDate.hour == undefined) {
|
|
81
|
-
throw new Error(`Tried to create time string but no hour was provided.`);
|
|
82
|
-
}
|
|
83
|
-
if (internalFullDate.minute == undefined) {
|
|
84
|
-
throw new Error(`Tried to create time string but no minutes were provided.`);
|
|
85
|
-
}
|
|
86
|
-
const timeParts = [
|
|
87
|
-
String(Math.abs(internalFullDate.hour)).padStart(2, '0'),
|
|
88
|
-
String(Math.abs(internalFullDate.minute)).padStart(2, '0'),
|
|
89
|
-
seconds,
|
|
90
|
-
].filter((entry) => entry != undefined);
|
|
91
|
-
return timeParts.join(':');
|
|
92
|
-
}
|
|
93
|
-
else if (inputType === full_date_shape_1.FullDatePartEnum.DateTime) {
|
|
94
|
-
const datePart = toHtmlInputString(fullDate, full_date_shape_1.FullDatePartEnum.Date);
|
|
95
|
-
const timePart = toHtmlInputString(fullDate, full_date_shape_1.FullDatePartEnum.Time, includeSeconds);
|
|
96
|
-
return `${datePart}T${timePart}`;
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
throw new Error(`Unexpected inputTyped: '${inputType}'. Expected usage of FullDatePartEnum or one of ${(0, common_1.getEnumTypedValues)(full_date_shape_1.FullDatePartEnum).join(', ')}.`);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
exports.toHtmlInputString = toHtmlInputString;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|