@trackunit/date-and-time-utils 1.14.4-alpha-d0f54ff2967.0 → 1.14.6
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/index.cjs.js +116 -24
- package/index.esm.js +116 -24
- package/package.json +1 -1
- package/src/DateAndTimeUtils.d.ts +66 -7
package/index.cjs.js
CHANGED
|
@@ -14,7 +14,7 @@ const getTimeZone = (timeZoneId) => {
|
|
|
14
14
|
return {
|
|
15
15
|
id: tzId,
|
|
16
16
|
offset: offset,
|
|
17
|
-
name: `${tzId} ${offset.length > 0 ?
|
|
17
|
+
name: `${tzId} ${offset.length > 0 ? `(${offset})` : ""}`,
|
|
18
18
|
};
|
|
19
19
|
};
|
|
20
20
|
/**
|
|
@@ -911,6 +911,76 @@ const isEqualUtil = (from, to) => {
|
|
|
911
911
|
.round({ smallestUnit: "seconds" })
|
|
912
912
|
.equals(toZonedDateTimeUtil(to).round({ smallestUnit: "seconds" }));
|
|
913
913
|
};
|
|
914
|
+
const localeScriptCache = new Map();
|
|
915
|
+
const localeScript = (locale) => {
|
|
916
|
+
const key = locale ?? "";
|
|
917
|
+
if (localeScriptCache.has(key))
|
|
918
|
+
return localeScriptCache.get(key);
|
|
919
|
+
let script;
|
|
920
|
+
try {
|
|
921
|
+
script = new Intl.Locale(locale ?? new Intl.NumberFormat().resolvedOptions().locale).maximize().script;
|
|
922
|
+
}
|
|
923
|
+
catch {
|
|
924
|
+
script = undefined;
|
|
925
|
+
}
|
|
926
|
+
localeScriptCache.set(key, script);
|
|
927
|
+
return script;
|
|
928
|
+
};
|
|
929
|
+
/**
|
|
930
|
+
* True when `Intl.NumberFormat` narrow for `locale`/`unit` renders in Latin script on a
|
|
931
|
+
* non-Latin-script locale — the symptom of a missing `units-narrow` slot silently
|
|
932
|
+
* inheriting from CLDR `root`. Detected directly on the formatter's output; this avoids
|
|
933
|
+
* any dependency on the ECMA-402 `DefaultLocale`, which would be the case if we tried to
|
|
934
|
+
* address `root` through `Intl` (there is no way: `Intl.NumberFormat("root")` throws, and
|
|
935
|
+
* `Intl.NumberFormat("und")` resolves via `LookupMatcher` to the runtime's default
|
|
936
|
+
* locale, not to CLDR root).
|
|
937
|
+
*
|
|
938
|
+
* Latin-script locales short-circuit to `false`: even if their narrow slot is empty and
|
|
939
|
+
* inherits from root, the fallback is still in the right script, so the output is not
|
|
940
|
+
* meaningfully delocalised.
|
|
941
|
+
*/
|
|
942
|
+
const narrowUnitIsDelocalisedCache = new Map();
|
|
943
|
+
const narrowUnitIsDelocalised = (locale, unit) => {
|
|
944
|
+
const key = `${locale ?? ""}|${unit}`;
|
|
945
|
+
const cached = narrowUnitIsDelocalisedCache.get(key);
|
|
946
|
+
if (cached !== undefined)
|
|
947
|
+
return cached;
|
|
948
|
+
if (localeScript(locale) === "Latn") {
|
|
949
|
+
narrowUnitIsDelocalisedCache.set(key, false);
|
|
950
|
+
return false;
|
|
951
|
+
}
|
|
952
|
+
const out = new Intl.NumberFormat(locale, { style: "unit", unit, unitDisplay: "narrow" }).format(1);
|
|
953
|
+
const delocalised = /[A-Za-z]/.test(out);
|
|
954
|
+
narrowUnitIsDelocalisedCache.set(key, delocalised);
|
|
955
|
+
return delocalised;
|
|
956
|
+
};
|
|
957
|
+
/**
|
|
958
|
+
* Formats a signed unit value using the Trackunit style axis.
|
|
959
|
+
* - `narrow-compact` past values → `Intl.NumberFormat` unit narrow (no affix), but only if
|
|
960
|
+
* the locale actually has native narrow data (i.e. not a silent root/Latin fallback);
|
|
961
|
+
* otherwise routes through `Intl.RelativeTimeFormat` narrow to preserve script.
|
|
962
|
+
* - `narrow-compact` future values → `Intl.RelativeTimeFormat` narrow (retains the CLDR-native
|
|
963
|
+
* leading affix — the API has no way to strip it).
|
|
964
|
+
* - No style specified → `Intl.RelativeTimeFormat` long (the default).
|
|
965
|
+
*/
|
|
966
|
+
const formatRelativeUnit = (value, unit, locale, style) => {
|
|
967
|
+
if (style === "narrow-compact") {
|
|
968
|
+
if (value <= 0) {
|
|
969
|
+
const singularUnit = unit.endsWith("s") ? unit.slice(0, -1) : unit;
|
|
970
|
+
if (!narrowUnitIsDelocalised(locale, singularUnit)) {
|
|
971
|
+
return new Intl.NumberFormat(locale, {
|
|
972
|
+
style: "unit",
|
|
973
|
+
unit: singularUnit,
|
|
974
|
+
unitDisplay: "narrow",
|
|
975
|
+
}).format(Math.abs(value));
|
|
976
|
+
}
|
|
977
|
+
// Non-Latin script whose units-narrow output would render in Latin (CLDR root
|
|
978
|
+
// fallback) — route through `RelativeTimeFormat` narrow to preserve script.
|
|
979
|
+
}
|
|
980
|
+
return getRelativeTimeFormat(locale, "narrow").format(value, unit);
|
|
981
|
+
}
|
|
982
|
+
return getRelativeTimeFormat(locale).format(value, unit);
|
|
983
|
+
};
|
|
914
984
|
/**
|
|
915
985
|
* Calculates the time duration between two TemporalDate objects and returns a human-readable string representation of the duration.
|
|
916
986
|
*
|
|
@@ -918,6 +988,12 @@ const isEqualUtil = (from, to) => {
|
|
|
918
988
|
* @param {TemporalDate} to - The ending date.
|
|
919
989
|
* @param {string} [timeZone] - The time zone to use for the calculations. Defaults to the local time zone.
|
|
920
990
|
* @param {string} [locale] - The locale to use for formatting the duration. Defaults to the user's locale.
|
|
991
|
+
* @param {TuRelativeTimeStyle} [style] - Optional width override. Pass `"narrow-compact"` to render
|
|
992
|
+
* past values without any past-tense affix (`"2d"` in en, `"2j"` in fr) while future values retain
|
|
993
|
+
* the CLDR-native leading affix (`"in 2d"` in en). Non-Latin-script locales without native CLDR
|
|
994
|
+
* narrow data fall back to `RelativeTimeFormat` narrow to preserve script, which keeps the affix
|
|
995
|
+
* (`"2日前"` in ja) — see {@link TuRelativeTimeStyle} for the CLDR-table-sourcing details.
|
|
996
|
+
* Omit `style` to get the default long form (`"2 days ago"` in en, `"vor 2 Tagen"` in de).
|
|
921
997
|
* @returns {string|Error} - The formatted duration string or an Error object if the duration is not valid.
|
|
922
998
|
* @example
|
|
923
999
|
* const startDate = "2023-05-1010:30:00.000Z"
|
|
@@ -937,8 +1013,14 @@ const isEqualUtil = (from, to) => {
|
|
|
937
1013
|
*
|
|
938
1014
|
* const result = timeSinceAuto(startDate, endDate, 'America/New_York', 'en-US');
|
|
939
1015
|
* Output: "1 year ago"
|
|
1016
|
+
* @example
|
|
1017
|
+
* const startDate = "2023-05-10"
|
|
1018
|
+
* const endDate = "2023-05-18"
|
|
1019
|
+
*
|
|
1020
|
+
* const result = timeSinceAuto(startDate, endDate, 'America/New_York', 'en-US', 'narrow-compact');
|
|
1021
|
+
* Output: "8d"
|
|
940
1022
|
*/
|
|
941
|
-
const timeSinceAuto = (from, to, timeZone, locale) => {
|
|
1023
|
+
const timeSinceAuto = (from, to, timeZone, locale, style) => {
|
|
942
1024
|
let since;
|
|
943
1025
|
try {
|
|
944
1026
|
since = toZonedDateTimeUtil(from, timeZone)
|
|
@@ -955,25 +1037,25 @@ const timeSinceAuto = (from, to, timeZone, locale) => {
|
|
|
955
1037
|
}
|
|
956
1038
|
const duration = polyfill.Temporal.Duration.from(since);
|
|
957
1039
|
if (duration.blank) {
|
|
958
|
-
return
|
|
1040
|
+
return formatRelativeUnit(-1, "seconds", locale, style);
|
|
959
1041
|
}
|
|
960
1042
|
if (duration.years !== 0) {
|
|
961
|
-
return
|
|
1043
|
+
return formatRelativeUnit(duration.years, "years", locale, style);
|
|
962
1044
|
}
|
|
963
1045
|
if (duration.months !== 0) {
|
|
964
|
-
return
|
|
1046
|
+
return formatRelativeUnit(duration.months, "months", locale, style);
|
|
965
1047
|
}
|
|
966
1048
|
if (duration.days !== 0) {
|
|
967
|
-
return
|
|
1049
|
+
return formatRelativeUnit(duration.days, "days", locale, style);
|
|
968
1050
|
}
|
|
969
1051
|
if (duration.hours !== 0) {
|
|
970
|
-
return
|
|
1052
|
+
return formatRelativeUnit(duration.hours, "hours", locale, style);
|
|
971
1053
|
}
|
|
972
1054
|
if (duration.minutes !== 0) {
|
|
973
|
-
return
|
|
1055
|
+
return formatRelativeUnit(duration.minutes, "minutes", locale, style);
|
|
974
1056
|
}
|
|
975
1057
|
if (duration.seconds !== 0) {
|
|
976
|
-
return
|
|
1058
|
+
return formatRelativeUnit(duration.seconds, "seconds", locale, style);
|
|
977
1059
|
}
|
|
978
1060
|
// eslint-disable-next-line no-console
|
|
979
1061
|
console.warn(new Error("Not a valid duration", { cause: duration }));
|
|
@@ -994,7 +1076,7 @@ const timeSinceAuto = (from, to, timeZone, locale) => {
|
|
|
994
1076
|
* const result = timeSinceInSeconds(startDate, endDate, 'America/New_York', 'en-US');
|
|
995
1077
|
* Output: "480 seconds ago"
|
|
996
1078
|
*/
|
|
997
|
-
const timeSinceInSeconds = (from, to, timeZone, locale) => {
|
|
1079
|
+
const timeSinceInSeconds = (from, to, timeZone, locale, style) => {
|
|
998
1080
|
let since = new polyfill.Temporal.Duration();
|
|
999
1081
|
try {
|
|
1000
1082
|
since = toZonedDateTimeUtil(from, timeZone).since(toZonedDateTimeUtil(to, timeZone), {
|
|
@@ -1006,7 +1088,7 @@ const timeSinceInSeconds = (from, to, timeZone, locale) => {
|
|
|
1006
1088
|
console.warn("Error: ", error);
|
|
1007
1089
|
}
|
|
1008
1090
|
const duration = polyfill.Temporal.Duration.from(since);
|
|
1009
|
-
return
|
|
1091
|
+
return formatRelativeUnit(duration.seconds, "seconds", locale, style);
|
|
1010
1092
|
};
|
|
1011
1093
|
/**
|
|
1012
1094
|
* Calculates the time duration between two TemporalDate objects and returns the duration in minutes as a formatted string.
|
|
@@ -1023,7 +1105,7 @@ const timeSinceInSeconds = (from, to, timeZone, locale) => {
|
|
|
1023
1105
|
* const result = timeSinceInSeconds(startDate, endDate, 'America/New_York', 'en-US');
|
|
1024
1106
|
* Output: "8 minutes ago"
|
|
1025
1107
|
*/
|
|
1026
|
-
const timeSinceInMinutes = (from, to, timeZone, locale) => {
|
|
1108
|
+
const timeSinceInMinutes = (from, to, timeZone, locale, style) => {
|
|
1027
1109
|
let since = new polyfill.Temporal.Duration();
|
|
1028
1110
|
try {
|
|
1029
1111
|
since = toZonedDateTimeUtil(from, timeZone).since(toZonedDateTimeUtil(to, timeZone), {
|
|
@@ -1035,7 +1117,7 @@ const timeSinceInMinutes = (from, to, timeZone, locale) => {
|
|
|
1035
1117
|
console.warn("Error: ", error);
|
|
1036
1118
|
}
|
|
1037
1119
|
const duration = polyfill.Temporal.Duration.from(since);
|
|
1038
|
-
return
|
|
1120
|
+
return formatRelativeUnit(duration.minutes, "minutes", locale, style);
|
|
1039
1121
|
};
|
|
1040
1122
|
/**
|
|
1041
1123
|
* Calculates the time duration between two TemporalDate objects and returns the duration in hours as a formatted string.
|
|
@@ -1052,7 +1134,7 @@ const timeSinceInMinutes = (from, to, timeZone, locale) => {
|
|
|
1052
1134
|
* const result = timeSinceInHours(startDate, endDate);
|
|
1053
1135
|
* Output: "3 hours ago"
|
|
1054
1136
|
*/
|
|
1055
|
-
const timeSinceInHours = (from, to, timeZone, locale) => {
|
|
1137
|
+
const timeSinceInHours = (from, to, timeZone, locale, style) => {
|
|
1056
1138
|
let since = new polyfill.Temporal.Duration();
|
|
1057
1139
|
try {
|
|
1058
1140
|
since = toZonedDateTimeUtil(from, timeZone).since(toZonedDateTimeUtil(to, timeZone), {
|
|
@@ -1064,7 +1146,7 @@ const timeSinceInHours = (from, to, timeZone, locale) => {
|
|
|
1064
1146
|
console.warn("Error: ", error);
|
|
1065
1147
|
}
|
|
1066
1148
|
const duration = polyfill.Temporal.Duration.from(since);
|
|
1067
|
-
return
|
|
1149
|
+
return formatRelativeUnit(duration.hours, "hours", locale, style);
|
|
1068
1150
|
};
|
|
1069
1151
|
/**
|
|
1070
1152
|
* Calculates the time duration between two TemporalDate objects and returns the duration in days as a formatted string.
|
|
@@ -1087,7 +1169,7 @@ const timeSinceInHours = (from, to, timeZone, locale) => {
|
|
|
1087
1169
|
* const result = timeSinceInDays(startDate, endDate, 'America/New_York', 'en-US');
|
|
1088
1170
|
* Output: "6 days ago"
|
|
1089
1171
|
*/
|
|
1090
|
-
const timeSinceInDays = (from, to, timeZone, locale) => {
|
|
1172
|
+
const timeSinceInDays = (from, to, timeZone, locale, style) => {
|
|
1091
1173
|
let since = new polyfill.Temporal.Duration();
|
|
1092
1174
|
try {
|
|
1093
1175
|
since = toZonedDateTimeUtil(from, timeZone).since(toZonedDateTimeUtil(to, timeZone), {
|
|
@@ -1099,7 +1181,7 @@ const timeSinceInDays = (from, to, timeZone, locale) => {
|
|
|
1099
1181
|
console.warn("Error: ", error);
|
|
1100
1182
|
}
|
|
1101
1183
|
const duration = polyfill.Temporal.Duration.from(since);
|
|
1102
|
-
return
|
|
1184
|
+
return formatRelativeUnit(Math.ceil(duration.hours / 24.0), "days", locale, style);
|
|
1103
1185
|
};
|
|
1104
1186
|
/**
|
|
1105
1187
|
* Calculates the time duration between two TemporalDate objects and returns the duration in months as a formatted string.
|
|
@@ -1109,6 +1191,11 @@ const timeSinceInDays = (from, to, timeZone, locale) => {
|
|
|
1109
1191
|
* @param {string} [timeZone] - The time zone to use for the calculations. Defaults to the local time zone.
|
|
1110
1192
|
* @param {string} [locale] - The locale to use for formatting the duration. Defaults to the user's locale.
|
|
1111
1193
|
* @returns {string} - The formatted duration in months.
|
|
1194
|
+
* @remarks When both `from` and `to` fall in a leap year, the function falls back to
|
|
1195
|
+
* `timeSinceInDays` and returns the raw day count for the whole span. Callers relying on a
|
|
1196
|
+
* specific unit — especially with `style="narrow-compact"`, where the unit is visible —
|
|
1197
|
+
* should be aware that the output can be an arbitrarily large day count (e.g. `"60d"` for a
|
|
1198
|
+
* two-month gap) instead of months on those inputs.
|
|
1112
1199
|
* @example
|
|
1113
1200
|
* const startDate = "2023-05-10"
|
|
1114
1201
|
* const endDate = "2023-07-11"
|
|
@@ -1116,10 +1203,10 @@ const timeSinceInDays = (from, to, timeZone, locale) => {
|
|
|
1116
1203
|
* const result = timeSinceInMonths(startDate, endDate, 'America/New_York', 'en-US');
|
|
1117
1204
|
* Output: "2 months ago"
|
|
1118
1205
|
*/
|
|
1119
|
-
const timeSinceInMonths = (from, to, timeZone, locale) => {
|
|
1206
|
+
const timeSinceInMonths = (from, to, timeZone, locale, style) => {
|
|
1120
1207
|
const isLeapYear = toZonedDateTimeUtil(from, timeZone).inLeapYear && toZonedDateTimeUtil(to, timeZone).inLeapYear;
|
|
1121
1208
|
if (isLeapYear) {
|
|
1122
|
-
return timeSinceInDays(from, to, timeZone, locale);
|
|
1209
|
+
return timeSinceInDays(from, to, timeZone, locale, style);
|
|
1123
1210
|
}
|
|
1124
1211
|
let since = new polyfill.Temporal.Duration();
|
|
1125
1212
|
try {
|
|
@@ -1132,7 +1219,7 @@ const timeSinceInMonths = (from, to, timeZone, locale) => {
|
|
|
1132
1219
|
console.warn("Error: ", error);
|
|
1133
1220
|
}
|
|
1134
1221
|
const duration = polyfill.Temporal.Duration.from(since);
|
|
1135
|
-
return
|
|
1222
|
+
return formatRelativeUnit(duration.months, "months", locale, style);
|
|
1136
1223
|
};
|
|
1137
1224
|
/**
|
|
1138
1225
|
* Calculates the time duration between two TemporalDate objects and returns the duration in years as a formatted string.
|
|
@@ -1142,6 +1229,11 @@ const timeSinceInMonths = (from, to, timeZone, locale) => {
|
|
|
1142
1229
|
* @param {string} [timeZone] - The time zone to use for the calculations. Defaults to the local time zone.
|
|
1143
1230
|
* @param {string} [locale] - The locale to use for formatting the duration. Defaults to the user's locale.
|
|
1144
1231
|
* @returns {string} - The formatted duration in years.
|
|
1232
|
+
* @remarks When both `from` and `to` fall in a leap year, the function falls back to
|
|
1233
|
+
* `timeSinceInDays` and returns the raw day count for the whole span. Callers relying on a
|
|
1234
|
+
* specific unit — especially with `style="narrow-compact"`, where the unit is visible —
|
|
1235
|
+
* should be aware that the output can be an arbitrarily large day count (e.g. `"1462d"` for
|
|
1236
|
+
* a ~4-year gap between two leap-year endpoints) instead of years on those inputs.
|
|
1145
1237
|
* @example
|
|
1146
1238
|
* const startDate = "2023-05-10"
|
|
1147
1239
|
* const endDate = "2024-05-11"
|
|
@@ -1149,10 +1241,10 @@ const timeSinceInMonths = (from, to, timeZone, locale) => {
|
|
|
1149
1241
|
* const result = timeSinceInYears(startDate, endDate, 'America/New_York', 'en-US');
|
|
1150
1242
|
* Output: "1 year ago"
|
|
1151
1243
|
*/
|
|
1152
|
-
const timeSinceInYears = (from, to, timeZone, locale) => {
|
|
1244
|
+
const timeSinceInYears = (from, to, timeZone, locale, style) => {
|
|
1153
1245
|
const isLeapYear = toZonedDateTimeUtil(from, timeZone).inLeapYear && toZonedDateTimeUtil(to, timeZone).inLeapYear;
|
|
1154
1246
|
if (isLeapYear) {
|
|
1155
|
-
return timeSinceInDays(from, to, timeZone, locale);
|
|
1247
|
+
return timeSinceInDays(from, to, timeZone, locale, style);
|
|
1156
1248
|
}
|
|
1157
1249
|
let since = new polyfill.Temporal.Duration();
|
|
1158
1250
|
try {
|
|
@@ -1165,9 +1257,9 @@ const timeSinceInYears = (from, to, timeZone, locale) => {
|
|
|
1165
1257
|
console.warn("Error: ", error);
|
|
1166
1258
|
}
|
|
1167
1259
|
const duration = polyfill.Temporal.Duration.from(since);
|
|
1168
|
-
return
|
|
1260
|
+
return formatRelativeUnit(duration.years, "years", locale, style);
|
|
1169
1261
|
};
|
|
1170
|
-
const getRelativeTimeFormat = (locale) => new Intl.RelativeTimeFormat(locale, { style
|
|
1262
|
+
const getRelativeTimeFormat = (locale, style = "long") => new Intl.RelativeTimeFormat(locale, { style, numeric: "always" });
|
|
1171
1263
|
/**
|
|
1172
1264
|
* Get duration in human-readable form
|
|
1173
1265
|
*
|
package/index.esm.js
CHANGED
|
@@ -13,7 +13,7 @@ const getTimeZone = (timeZoneId) => {
|
|
|
13
13
|
return {
|
|
14
14
|
id: tzId,
|
|
15
15
|
offset: offset,
|
|
16
|
-
name: `${tzId} ${offset.length > 0 ?
|
|
16
|
+
name: `${tzId} ${offset.length > 0 ? `(${offset})` : ""}`,
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
@@ -910,6 +910,76 @@ const isEqualUtil = (from, to) => {
|
|
|
910
910
|
.round({ smallestUnit: "seconds" })
|
|
911
911
|
.equals(toZonedDateTimeUtil(to).round({ smallestUnit: "seconds" }));
|
|
912
912
|
};
|
|
913
|
+
const localeScriptCache = new Map();
|
|
914
|
+
const localeScript = (locale) => {
|
|
915
|
+
const key = locale ?? "";
|
|
916
|
+
if (localeScriptCache.has(key))
|
|
917
|
+
return localeScriptCache.get(key);
|
|
918
|
+
let script;
|
|
919
|
+
try {
|
|
920
|
+
script = new Intl.Locale(locale ?? new Intl.NumberFormat().resolvedOptions().locale).maximize().script;
|
|
921
|
+
}
|
|
922
|
+
catch {
|
|
923
|
+
script = undefined;
|
|
924
|
+
}
|
|
925
|
+
localeScriptCache.set(key, script);
|
|
926
|
+
return script;
|
|
927
|
+
};
|
|
928
|
+
/**
|
|
929
|
+
* True when `Intl.NumberFormat` narrow for `locale`/`unit` renders in Latin script on a
|
|
930
|
+
* non-Latin-script locale — the symptom of a missing `units-narrow` slot silently
|
|
931
|
+
* inheriting from CLDR `root`. Detected directly on the formatter's output; this avoids
|
|
932
|
+
* any dependency on the ECMA-402 `DefaultLocale`, which would be the case if we tried to
|
|
933
|
+
* address `root` through `Intl` (there is no way: `Intl.NumberFormat("root")` throws, and
|
|
934
|
+
* `Intl.NumberFormat("und")` resolves via `LookupMatcher` to the runtime's default
|
|
935
|
+
* locale, not to CLDR root).
|
|
936
|
+
*
|
|
937
|
+
* Latin-script locales short-circuit to `false`: even if their narrow slot is empty and
|
|
938
|
+
* inherits from root, the fallback is still in the right script, so the output is not
|
|
939
|
+
* meaningfully delocalised.
|
|
940
|
+
*/
|
|
941
|
+
const narrowUnitIsDelocalisedCache = new Map();
|
|
942
|
+
const narrowUnitIsDelocalised = (locale, unit) => {
|
|
943
|
+
const key = `${locale ?? ""}|${unit}`;
|
|
944
|
+
const cached = narrowUnitIsDelocalisedCache.get(key);
|
|
945
|
+
if (cached !== undefined)
|
|
946
|
+
return cached;
|
|
947
|
+
if (localeScript(locale) === "Latn") {
|
|
948
|
+
narrowUnitIsDelocalisedCache.set(key, false);
|
|
949
|
+
return false;
|
|
950
|
+
}
|
|
951
|
+
const out = new Intl.NumberFormat(locale, { style: "unit", unit, unitDisplay: "narrow" }).format(1);
|
|
952
|
+
const delocalised = /[A-Za-z]/.test(out);
|
|
953
|
+
narrowUnitIsDelocalisedCache.set(key, delocalised);
|
|
954
|
+
return delocalised;
|
|
955
|
+
};
|
|
956
|
+
/**
|
|
957
|
+
* Formats a signed unit value using the Trackunit style axis.
|
|
958
|
+
* - `narrow-compact` past values → `Intl.NumberFormat` unit narrow (no affix), but only if
|
|
959
|
+
* the locale actually has native narrow data (i.e. not a silent root/Latin fallback);
|
|
960
|
+
* otherwise routes through `Intl.RelativeTimeFormat` narrow to preserve script.
|
|
961
|
+
* - `narrow-compact` future values → `Intl.RelativeTimeFormat` narrow (retains the CLDR-native
|
|
962
|
+
* leading affix — the API has no way to strip it).
|
|
963
|
+
* - No style specified → `Intl.RelativeTimeFormat` long (the default).
|
|
964
|
+
*/
|
|
965
|
+
const formatRelativeUnit = (value, unit, locale, style) => {
|
|
966
|
+
if (style === "narrow-compact") {
|
|
967
|
+
if (value <= 0) {
|
|
968
|
+
const singularUnit = unit.endsWith("s") ? unit.slice(0, -1) : unit;
|
|
969
|
+
if (!narrowUnitIsDelocalised(locale, singularUnit)) {
|
|
970
|
+
return new Intl.NumberFormat(locale, {
|
|
971
|
+
style: "unit",
|
|
972
|
+
unit: singularUnit,
|
|
973
|
+
unitDisplay: "narrow",
|
|
974
|
+
}).format(Math.abs(value));
|
|
975
|
+
}
|
|
976
|
+
// Non-Latin script whose units-narrow output would render in Latin (CLDR root
|
|
977
|
+
// fallback) — route through `RelativeTimeFormat` narrow to preserve script.
|
|
978
|
+
}
|
|
979
|
+
return getRelativeTimeFormat(locale, "narrow").format(value, unit);
|
|
980
|
+
}
|
|
981
|
+
return getRelativeTimeFormat(locale).format(value, unit);
|
|
982
|
+
};
|
|
913
983
|
/**
|
|
914
984
|
* Calculates the time duration between two TemporalDate objects and returns a human-readable string representation of the duration.
|
|
915
985
|
*
|
|
@@ -917,6 +987,12 @@ const isEqualUtil = (from, to) => {
|
|
|
917
987
|
* @param {TemporalDate} to - The ending date.
|
|
918
988
|
* @param {string} [timeZone] - The time zone to use for the calculations. Defaults to the local time zone.
|
|
919
989
|
* @param {string} [locale] - The locale to use for formatting the duration. Defaults to the user's locale.
|
|
990
|
+
* @param {TuRelativeTimeStyle} [style] - Optional width override. Pass `"narrow-compact"` to render
|
|
991
|
+
* past values without any past-tense affix (`"2d"` in en, `"2j"` in fr) while future values retain
|
|
992
|
+
* the CLDR-native leading affix (`"in 2d"` in en). Non-Latin-script locales without native CLDR
|
|
993
|
+
* narrow data fall back to `RelativeTimeFormat` narrow to preserve script, which keeps the affix
|
|
994
|
+
* (`"2日前"` in ja) — see {@link TuRelativeTimeStyle} for the CLDR-table-sourcing details.
|
|
995
|
+
* Omit `style` to get the default long form (`"2 days ago"` in en, `"vor 2 Tagen"` in de).
|
|
920
996
|
* @returns {string|Error} - The formatted duration string or an Error object if the duration is not valid.
|
|
921
997
|
* @example
|
|
922
998
|
* const startDate = "2023-05-1010:30:00.000Z"
|
|
@@ -936,8 +1012,14 @@ const isEqualUtil = (from, to) => {
|
|
|
936
1012
|
*
|
|
937
1013
|
* const result = timeSinceAuto(startDate, endDate, 'America/New_York', 'en-US');
|
|
938
1014
|
* Output: "1 year ago"
|
|
1015
|
+
* @example
|
|
1016
|
+
* const startDate = "2023-05-10"
|
|
1017
|
+
* const endDate = "2023-05-18"
|
|
1018
|
+
*
|
|
1019
|
+
* const result = timeSinceAuto(startDate, endDate, 'America/New_York', 'en-US', 'narrow-compact');
|
|
1020
|
+
* Output: "8d"
|
|
939
1021
|
*/
|
|
940
|
-
const timeSinceAuto = (from, to, timeZone, locale) => {
|
|
1022
|
+
const timeSinceAuto = (from, to, timeZone, locale, style) => {
|
|
941
1023
|
let since;
|
|
942
1024
|
try {
|
|
943
1025
|
since = toZonedDateTimeUtil(from, timeZone)
|
|
@@ -954,25 +1036,25 @@ const timeSinceAuto = (from, to, timeZone, locale) => {
|
|
|
954
1036
|
}
|
|
955
1037
|
const duration = Temporal.Duration.from(since);
|
|
956
1038
|
if (duration.blank) {
|
|
957
|
-
return
|
|
1039
|
+
return formatRelativeUnit(-1, "seconds", locale, style);
|
|
958
1040
|
}
|
|
959
1041
|
if (duration.years !== 0) {
|
|
960
|
-
return
|
|
1042
|
+
return formatRelativeUnit(duration.years, "years", locale, style);
|
|
961
1043
|
}
|
|
962
1044
|
if (duration.months !== 0) {
|
|
963
|
-
return
|
|
1045
|
+
return formatRelativeUnit(duration.months, "months", locale, style);
|
|
964
1046
|
}
|
|
965
1047
|
if (duration.days !== 0) {
|
|
966
|
-
return
|
|
1048
|
+
return formatRelativeUnit(duration.days, "days", locale, style);
|
|
967
1049
|
}
|
|
968
1050
|
if (duration.hours !== 0) {
|
|
969
|
-
return
|
|
1051
|
+
return formatRelativeUnit(duration.hours, "hours", locale, style);
|
|
970
1052
|
}
|
|
971
1053
|
if (duration.minutes !== 0) {
|
|
972
|
-
return
|
|
1054
|
+
return formatRelativeUnit(duration.minutes, "minutes", locale, style);
|
|
973
1055
|
}
|
|
974
1056
|
if (duration.seconds !== 0) {
|
|
975
|
-
return
|
|
1057
|
+
return formatRelativeUnit(duration.seconds, "seconds", locale, style);
|
|
976
1058
|
}
|
|
977
1059
|
// eslint-disable-next-line no-console
|
|
978
1060
|
console.warn(new Error("Not a valid duration", { cause: duration }));
|
|
@@ -993,7 +1075,7 @@ const timeSinceAuto = (from, to, timeZone, locale) => {
|
|
|
993
1075
|
* const result = timeSinceInSeconds(startDate, endDate, 'America/New_York', 'en-US');
|
|
994
1076
|
* Output: "480 seconds ago"
|
|
995
1077
|
*/
|
|
996
|
-
const timeSinceInSeconds = (from, to, timeZone, locale) => {
|
|
1078
|
+
const timeSinceInSeconds = (from, to, timeZone, locale, style) => {
|
|
997
1079
|
let since = new Temporal.Duration();
|
|
998
1080
|
try {
|
|
999
1081
|
since = toZonedDateTimeUtil(from, timeZone).since(toZonedDateTimeUtil(to, timeZone), {
|
|
@@ -1005,7 +1087,7 @@ const timeSinceInSeconds = (from, to, timeZone, locale) => {
|
|
|
1005
1087
|
console.warn("Error: ", error);
|
|
1006
1088
|
}
|
|
1007
1089
|
const duration = Temporal.Duration.from(since);
|
|
1008
|
-
return
|
|
1090
|
+
return formatRelativeUnit(duration.seconds, "seconds", locale, style);
|
|
1009
1091
|
};
|
|
1010
1092
|
/**
|
|
1011
1093
|
* Calculates the time duration between two TemporalDate objects and returns the duration in minutes as a formatted string.
|
|
@@ -1022,7 +1104,7 @@ const timeSinceInSeconds = (from, to, timeZone, locale) => {
|
|
|
1022
1104
|
* const result = timeSinceInSeconds(startDate, endDate, 'America/New_York', 'en-US');
|
|
1023
1105
|
* Output: "8 minutes ago"
|
|
1024
1106
|
*/
|
|
1025
|
-
const timeSinceInMinutes = (from, to, timeZone, locale) => {
|
|
1107
|
+
const timeSinceInMinutes = (from, to, timeZone, locale, style) => {
|
|
1026
1108
|
let since = new Temporal.Duration();
|
|
1027
1109
|
try {
|
|
1028
1110
|
since = toZonedDateTimeUtil(from, timeZone).since(toZonedDateTimeUtil(to, timeZone), {
|
|
@@ -1034,7 +1116,7 @@ const timeSinceInMinutes = (from, to, timeZone, locale) => {
|
|
|
1034
1116
|
console.warn("Error: ", error);
|
|
1035
1117
|
}
|
|
1036
1118
|
const duration = Temporal.Duration.from(since);
|
|
1037
|
-
return
|
|
1119
|
+
return formatRelativeUnit(duration.minutes, "minutes", locale, style);
|
|
1038
1120
|
};
|
|
1039
1121
|
/**
|
|
1040
1122
|
* Calculates the time duration between two TemporalDate objects and returns the duration in hours as a formatted string.
|
|
@@ -1051,7 +1133,7 @@ const timeSinceInMinutes = (from, to, timeZone, locale) => {
|
|
|
1051
1133
|
* const result = timeSinceInHours(startDate, endDate);
|
|
1052
1134
|
* Output: "3 hours ago"
|
|
1053
1135
|
*/
|
|
1054
|
-
const timeSinceInHours = (from, to, timeZone, locale) => {
|
|
1136
|
+
const timeSinceInHours = (from, to, timeZone, locale, style) => {
|
|
1055
1137
|
let since = new Temporal.Duration();
|
|
1056
1138
|
try {
|
|
1057
1139
|
since = toZonedDateTimeUtil(from, timeZone).since(toZonedDateTimeUtil(to, timeZone), {
|
|
@@ -1063,7 +1145,7 @@ const timeSinceInHours = (from, to, timeZone, locale) => {
|
|
|
1063
1145
|
console.warn("Error: ", error);
|
|
1064
1146
|
}
|
|
1065
1147
|
const duration = Temporal.Duration.from(since);
|
|
1066
|
-
return
|
|
1148
|
+
return formatRelativeUnit(duration.hours, "hours", locale, style);
|
|
1067
1149
|
};
|
|
1068
1150
|
/**
|
|
1069
1151
|
* Calculates the time duration between two TemporalDate objects and returns the duration in days as a formatted string.
|
|
@@ -1086,7 +1168,7 @@ const timeSinceInHours = (from, to, timeZone, locale) => {
|
|
|
1086
1168
|
* const result = timeSinceInDays(startDate, endDate, 'America/New_York', 'en-US');
|
|
1087
1169
|
* Output: "6 days ago"
|
|
1088
1170
|
*/
|
|
1089
|
-
const timeSinceInDays = (from, to, timeZone, locale) => {
|
|
1171
|
+
const timeSinceInDays = (from, to, timeZone, locale, style) => {
|
|
1090
1172
|
let since = new Temporal.Duration();
|
|
1091
1173
|
try {
|
|
1092
1174
|
since = toZonedDateTimeUtil(from, timeZone).since(toZonedDateTimeUtil(to, timeZone), {
|
|
@@ -1098,7 +1180,7 @@ const timeSinceInDays = (from, to, timeZone, locale) => {
|
|
|
1098
1180
|
console.warn("Error: ", error);
|
|
1099
1181
|
}
|
|
1100
1182
|
const duration = Temporal.Duration.from(since);
|
|
1101
|
-
return
|
|
1183
|
+
return formatRelativeUnit(Math.ceil(duration.hours / 24.0), "days", locale, style);
|
|
1102
1184
|
};
|
|
1103
1185
|
/**
|
|
1104
1186
|
* Calculates the time duration between two TemporalDate objects and returns the duration in months as a formatted string.
|
|
@@ -1108,6 +1190,11 @@ const timeSinceInDays = (from, to, timeZone, locale) => {
|
|
|
1108
1190
|
* @param {string} [timeZone] - The time zone to use for the calculations. Defaults to the local time zone.
|
|
1109
1191
|
* @param {string} [locale] - The locale to use for formatting the duration. Defaults to the user's locale.
|
|
1110
1192
|
* @returns {string} - The formatted duration in months.
|
|
1193
|
+
* @remarks When both `from` and `to` fall in a leap year, the function falls back to
|
|
1194
|
+
* `timeSinceInDays` and returns the raw day count for the whole span. Callers relying on a
|
|
1195
|
+
* specific unit — especially with `style="narrow-compact"`, where the unit is visible —
|
|
1196
|
+
* should be aware that the output can be an arbitrarily large day count (e.g. `"60d"` for a
|
|
1197
|
+
* two-month gap) instead of months on those inputs.
|
|
1111
1198
|
* @example
|
|
1112
1199
|
* const startDate = "2023-05-10"
|
|
1113
1200
|
* const endDate = "2023-07-11"
|
|
@@ -1115,10 +1202,10 @@ const timeSinceInDays = (from, to, timeZone, locale) => {
|
|
|
1115
1202
|
* const result = timeSinceInMonths(startDate, endDate, 'America/New_York', 'en-US');
|
|
1116
1203
|
* Output: "2 months ago"
|
|
1117
1204
|
*/
|
|
1118
|
-
const timeSinceInMonths = (from, to, timeZone, locale) => {
|
|
1205
|
+
const timeSinceInMonths = (from, to, timeZone, locale, style) => {
|
|
1119
1206
|
const isLeapYear = toZonedDateTimeUtil(from, timeZone).inLeapYear && toZonedDateTimeUtil(to, timeZone).inLeapYear;
|
|
1120
1207
|
if (isLeapYear) {
|
|
1121
|
-
return timeSinceInDays(from, to, timeZone, locale);
|
|
1208
|
+
return timeSinceInDays(from, to, timeZone, locale, style);
|
|
1122
1209
|
}
|
|
1123
1210
|
let since = new Temporal.Duration();
|
|
1124
1211
|
try {
|
|
@@ -1131,7 +1218,7 @@ const timeSinceInMonths = (from, to, timeZone, locale) => {
|
|
|
1131
1218
|
console.warn("Error: ", error);
|
|
1132
1219
|
}
|
|
1133
1220
|
const duration = Temporal.Duration.from(since);
|
|
1134
|
-
return
|
|
1221
|
+
return formatRelativeUnit(duration.months, "months", locale, style);
|
|
1135
1222
|
};
|
|
1136
1223
|
/**
|
|
1137
1224
|
* Calculates the time duration between two TemporalDate objects and returns the duration in years as a formatted string.
|
|
@@ -1141,6 +1228,11 @@ const timeSinceInMonths = (from, to, timeZone, locale) => {
|
|
|
1141
1228
|
* @param {string} [timeZone] - The time zone to use for the calculations. Defaults to the local time zone.
|
|
1142
1229
|
* @param {string} [locale] - The locale to use for formatting the duration. Defaults to the user's locale.
|
|
1143
1230
|
* @returns {string} - The formatted duration in years.
|
|
1231
|
+
* @remarks When both `from` and `to` fall in a leap year, the function falls back to
|
|
1232
|
+
* `timeSinceInDays` and returns the raw day count for the whole span. Callers relying on a
|
|
1233
|
+
* specific unit — especially with `style="narrow-compact"`, where the unit is visible —
|
|
1234
|
+
* should be aware that the output can be an arbitrarily large day count (e.g. `"1462d"` for
|
|
1235
|
+
* a ~4-year gap between two leap-year endpoints) instead of years on those inputs.
|
|
1144
1236
|
* @example
|
|
1145
1237
|
* const startDate = "2023-05-10"
|
|
1146
1238
|
* const endDate = "2024-05-11"
|
|
@@ -1148,10 +1240,10 @@ const timeSinceInMonths = (from, to, timeZone, locale) => {
|
|
|
1148
1240
|
* const result = timeSinceInYears(startDate, endDate, 'America/New_York', 'en-US');
|
|
1149
1241
|
* Output: "1 year ago"
|
|
1150
1242
|
*/
|
|
1151
|
-
const timeSinceInYears = (from, to, timeZone, locale) => {
|
|
1243
|
+
const timeSinceInYears = (from, to, timeZone, locale, style) => {
|
|
1152
1244
|
const isLeapYear = toZonedDateTimeUtil(from, timeZone).inLeapYear && toZonedDateTimeUtil(to, timeZone).inLeapYear;
|
|
1153
1245
|
if (isLeapYear) {
|
|
1154
|
-
return timeSinceInDays(from, to, timeZone, locale);
|
|
1246
|
+
return timeSinceInDays(from, to, timeZone, locale, style);
|
|
1155
1247
|
}
|
|
1156
1248
|
let since = new Temporal.Duration();
|
|
1157
1249
|
try {
|
|
@@ -1164,9 +1256,9 @@ const timeSinceInYears = (from, to, timeZone, locale) => {
|
|
|
1164
1256
|
console.warn("Error: ", error);
|
|
1165
1257
|
}
|
|
1166
1258
|
const duration = Temporal.Duration.from(since);
|
|
1167
|
-
return
|
|
1259
|
+
return formatRelativeUnit(duration.years, "years", locale, style);
|
|
1168
1260
|
};
|
|
1169
|
-
const getRelativeTimeFormat = (locale) => new Intl.RelativeTimeFormat(locale, { style
|
|
1261
|
+
const getRelativeTimeFormat = (locale, style = "long") => new Intl.RelativeTimeFormat(locale, { style, numeric: "always" });
|
|
1170
1262
|
/**
|
|
1171
1263
|
* Get duration in human-readable form
|
|
1172
1264
|
*
|
package/package.json
CHANGED
|
@@ -683,6 +683,43 @@ export declare const isSameYearUtil: (date: TemporalDate) => boolean;
|
|
|
683
683
|
* Output: true
|
|
684
684
|
*/
|
|
685
685
|
export declare const isEqualUtil: (from: TemporalDate, to: TemporalDate) => boolean;
|
|
686
|
+
/**
|
|
687
|
+
* Trackunit-owned relative-time style axis. The single supported value is `"narrow-compact"` —
|
|
688
|
+
* the shortest possible locale-native output for past durations. When `style` is omitted, the
|
|
689
|
+
* default `Intl.RelativeTimeFormat` long output is used (e.g. `"2 days ago"` in en).
|
|
690
|
+
*
|
|
691
|
+
* Past values are pulled from CLDR's `units-narrow` table via `Intl.NumberFormat`
|
|
692
|
+
* `style: "unit"`, which omits any past-tense affix by design (it's a measurement-quantity
|
|
693
|
+
* API — "5 kg", "12 mi"). Future values continue to come from `Intl.RelativeTimeFormat`
|
|
694
|
+
* narrow, which retains the future affix ("in") because CLDR treats it as grammar rather
|
|
695
|
+
* than an appendable string.
|
|
696
|
+
*
|
|
697
|
+
* ### Cross-locale fallback
|
|
698
|
+
* CLDR does not populate `units-narrow` for every locale — notably Japanese (`ja`) has no
|
|
699
|
+
* narrow entries at all, and several other locales lack entries for some units (e.g.
|
|
700
|
+
* Spanish `day`/`month`, Swedish and Norwegian `day`/`minute`/…). Missing slots inherit
|
|
701
|
+
* from CLDR `root`, which renders in Latin (`"2d"`, `"2y"`, …). For Latin-script locales
|
|
702
|
+
* that's cosmetic — the fallback is still in the right script — but for non-Latin locales
|
|
703
|
+
* it silently delocalises the output. To avoid that, when the target locale's script is
|
|
704
|
+
* non-Latin *and* the `NumberFormat` narrow output actually contains Latin letters, this
|
|
705
|
+
* style transparently falls through to `RelativeTimeFormat` narrow for that (locale, unit)
|
|
706
|
+
* combination. That path keeps the past-tense affix, which is unavoidable there, but the
|
|
707
|
+
* affix is short in the affected locales (e.g. Japanese `"2日前"`) and correct localization
|
|
708
|
+
* beats aggressive compaction.
|
|
709
|
+
*
|
|
710
|
+
* ### Known CLDR quirks
|
|
711
|
+
* Because past/future paths read from *different* CLDR tables, the symbol for a given unit
|
|
712
|
+
* may differ between them in a given locale (e.g. English past-month renders as `"3m"` from
|
|
713
|
+
* `units-narrow`, while future-month renders as `"in 3mo"` from `dateFields-narrow`, which
|
|
714
|
+
* CLDR disambiguates against `minute`). Both are the source-of-truth CLDR narrow displays
|
|
715
|
+
* for their respective APIs — this is by design in CLDR, not something we rewrite in JS.
|
|
716
|
+
*
|
|
717
|
+
* ### When to use `"narrow-compact"`
|
|
718
|
+
* When the surrounding UI already makes "past" obvious for negative durations — for example
|
|
719
|
+
* a "last seen" icon or a hover title that repeats the phrase in full. Otherwise omit `style`
|
|
720
|
+
* so the default long form is used, which is unambiguous in isolation.
|
|
721
|
+
*/
|
|
722
|
+
export type TuRelativeTimeStyle = "narrow-compact";
|
|
686
723
|
/**
|
|
687
724
|
* Calculates the time duration between two TemporalDate objects and returns a human-readable string representation of the duration.
|
|
688
725
|
*
|
|
@@ -690,6 +727,12 @@ export declare const isEqualUtil: (from: TemporalDate, to: TemporalDate) => bool
|
|
|
690
727
|
* @param {TemporalDate} to - The ending date.
|
|
691
728
|
* @param {string} [timeZone] - The time zone to use for the calculations. Defaults to the local time zone.
|
|
692
729
|
* @param {string} [locale] - The locale to use for formatting the duration. Defaults to the user's locale.
|
|
730
|
+
* @param {TuRelativeTimeStyle} [style] - Optional width override. Pass `"narrow-compact"` to render
|
|
731
|
+
* past values without any past-tense affix (`"2d"` in en, `"2j"` in fr) while future values retain
|
|
732
|
+
* the CLDR-native leading affix (`"in 2d"` in en). Non-Latin-script locales without native CLDR
|
|
733
|
+
* narrow data fall back to `RelativeTimeFormat` narrow to preserve script, which keeps the affix
|
|
734
|
+
* (`"2日前"` in ja) — see {@link TuRelativeTimeStyle} for the CLDR-table-sourcing details.
|
|
735
|
+
* Omit `style` to get the default long form (`"2 days ago"` in en, `"vor 2 Tagen"` in de).
|
|
693
736
|
* @returns {string|Error} - The formatted duration string or an Error object if the duration is not valid.
|
|
694
737
|
* @example
|
|
695
738
|
* const startDate = "2023-05-1010:30:00.000Z"
|
|
@@ -709,8 +752,14 @@ export declare const isEqualUtil: (from: TemporalDate, to: TemporalDate) => bool
|
|
|
709
752
|
*
|
|
710
753
|
* const result = timeSinceAuto(startDate, endDate, 'America/New_York', 'en-US');
|
|
711
754
|
* Output: "1 year ago"
|
|
755
|
+
* @example
|
|
756
|
+
* const startDate = "2023-05-10"
|
|
757
|
+
* const endDate = "2023-05-18"
|
|
758
|
+
*
|
|
759
|
+
* const result = timeSinceAuto(startDate, endDate, 'America/New_York', 'en-US', 'narrow-compact');
|
|
760
|
+
* Output: "8d"
|
|
712
761
|
*/
|
|
713
|
-
export declare const timeSinceAuto: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string) => string;
|
|
762
|
+
export declare const timeSinceAuto: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string, style?: TuRelativeTimeStyle) => string;
|
|
714
763
|
/**
|
|
715
764
|
* Calculates the time duration between two TemporalDate objects and returns the duration in seconds as a formatted string.
|
|
716
765
|
*
|
|
@@ -726,7 +775,7 @@ export declare const timeSinceAuto: (from: TemporalDate, to: TemporalDate, timeZ
|
|
|
726
775
|
* const result = timeSinceInSeconds(startDate, endDate, 'America/New_York', 'en-US');
|
|
727
776
|
* Output: "480 seconds ago"
|
|
728
777
|
*/
|
|
729
|
-
export declare const timeSinceInSeconds: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string) => string;
|
|
778
|
+
export declare const timeSinceInSeconds: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string, style?: TuRelativeTimeStyle) => string;
|
|
730
779
|
/**
|
|
731
780
|
* Calculates the time duration between two TemporalDate objects and returns the duration in minutes as a formatted string.
|
|
732
781
|
*
|
|
@@ -742,7 +791,7 @@ export declare const timeSinceInSeconds: (from: TemporalDate, to: TemporalDate,
|
|
|
742
791
|
* const result = timeSinceInSeconds(startDate, endDate, 'America/New_York', 'en-US');
|
|
743
792
|
* Output: "8 minutes ago"
|
|
744
793
|
*/
|
|
745
|
-
export declare const timeSinceInMinutes: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string) => string;
|
|
794
|
+
export declare const timeSinceInMinutes: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string, style?: TuRelativeTimeStyle) => string;
|
|
746
795
|
/**
|
|
747
796
|
* Calculates the time duration between two TemporalDate objects and returns the duration in hours as a formatted string.
|
|
748
797
|
*
|
|
@@ -758,7 +807,7 @@ export declare const timeSinceInMinutes: (from: TemporalDate, to: TemporalDate,
|
|
|
758
807
|
* const result = timeSinceInHours(startDate, endDate);
|
|
759
808
|
* Output: "3 hours ago"
|
|
760
809
|
*/
|
|
761
|
-
export declare const timeSinceInHours: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string) => string;
|
|
810
|
+
export declare const timeSinceInHours: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string, style?: TuRelativeTimeStyle) => string;
|
|
762
811
|
/**
|
|
763
812
|
* Calculates the time duration between two TemporalDate objects and returns the duration in days as a formatted string.
|
|
764
813
|
*
|
|
@@ -780,7 +829,7 @@ export declare const timeSinceInHours: (from: TemporalDate, to: TemporalDate, ti
|
|
|
780
829
|
* const result = timeSinceInDays(startDate, endDate, 'America/New_York', 'en-US');
|
|
781
830
|
* Output: "6 days ago"
|
|
782
831
|
*/
|
|
783
|
-
export declare const timeSinceInDays: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string) => string;
|
|
832
|
+
export declare const timeSinceInDays: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string, style?: TuRelativeTimeStyle) => string;
|
|
784
833
|
/**
|
|
785
834
|
* Calculates the time duration between two TemporalDate objects and returns the duration in months as a formatted string.
|
|
786
835
|
*
|
|
@@ -789,6 +838,11 @@ export declare const timeSinceInDays: (from: TemporalDate, to: TemporalDate, tim
|
|
|
789
838
|
* @param {string} [timeZone] - The time zone to use for the calculations. Defaults to the local time zone.
|
|
790
839
|
* @param {string} [locale] - The locale to use for formatting the duration. Defaults to the user's locale.
|
|
791
840
|
* @returns {string} - The formatted duration in months.
|
|
841
|
+
* @remarks When both `from` and `to` fall in a leap year, the function falls back to
|
|
842
|
+
* `timeSinceInDays` and returns the raw day count for the whole span. Callers relying on a
|
|
843
|
+
* specific unit — especially with `style="narrow-compact"`, where the unit is visible —
|
|
844
|
+
* should be aware that the output can be an arbitrarily large day count (e.g. `"60d"` for a
|
|
845
|
+
* two-month gap) instead of months on those inputs.
|
|
792
846
|
* @example
|
|
793
847
|
* const startDate = "2023-05-10"
|
|
794
848
|
* const endDate = "2023-07-11"
|
|
@@ -796,7 +850,7 @@ export declare const timeSinceInDays: (from: TemporalDate, to: TemporalDate, tim
|
|
|
796
850
|
* const result = timeSinceInMonths(startDate, endDate, 'America/New_York', 'en-US');
|
|
797
851
|
* Output: "2 months ago"
|
|
798
852
|
*/
|
|
799
|
-
export declare const timeSinceInMonths: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string) => string;
|
|
853
|
+
export declare const timeSinceInMonths: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string, style?: TuRelativeTimeStyle) => string;
|
|
800
854
|
/**
|
|
801
855
|
* Calculates the time duration between two TemporalDate objects and returns the duration in years as a formatted string.
|
|
802
856
|
*
|
|
@@ -805,6 +859,11 @@ export declare const timeSinceInMonths: (from: TemporalDate, to: TemporalDate, t
|
|
|
805
859
|
* @param {string} [timeZone] - The time zone to use for the calculations. Defaults to the local time zone.
|
|
806
860
|
* @param {string} [locale] - The locale to use for formatting the duration. Defaults to the user's locale.
|
|
807
861
|
* @returns {string} - The formatted duration in years.
|
|
862
|
+
* @remarks When both `from` and `to` fall in a leap year, the function falls back to
|
|
863
|
+
* `timeSinceInDays` and returns the raw day count for the whole span. Callers relying on a
|
|
864
|
+
* specific unit — especially with `style="narrow-compact"`, where the unit is visible —
|
|
865
|
+
* should be aware that the output can be an arbitrarily large day count (e.g. `"1462d"` for
|
|
866
|
+
* a ~4-year gap between two leap-year endpoints) instead of years on those inputs.
|
|
808
867
|
* @example
|
|
809
868
|
* const startDate = "2023-05-10"
|
|
810
869
|
* const endDate = "2024-05-11"
|
|
@@ -812,7 +871,7 @@ export declare const timeSinceInMonths: (from: TemporalDate, to: TemporalDate, t
|
|
|
812
871
|
* const result = timeSinceInYears(startDate, endDate, 'America/New_York', 'en-US');
|
|
813
872
|
* Output: "1 year ago"
|
|
814
873
|
*/
|
|
815
|
-
export declare const timeSinceInYears: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string) => string;
|
|
874
|
+
export declare const timeSinceInYears: (from: TemporalDate, to: TemporalDate, timeZone?: string, locale?: string, style?: TuRelativeTimeStyle) => string;
|
|
816
875
|
/**
|
|
817
876
|
* Get duration in human-readable form
|
|
818
877
|
*
|