@bereasoftware/time-guard 2.5.1 → 2.5.3
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/README.en.md +7 -4
- package/README.md +7 -4
- package/dist/calendars/index.es.js +1 -1
- package/dist/plugins/advanced-format.cjs +1 -1
- package/dist/plugins/advanced-format.cjs.map +1 -1
- package/dist/plugins/advanced-format.es.js +1 -53
- package/dist/plugins/advanced-format.es.js.map +1 -1
- package/dist/plugins/duration.cjs.map +1 -1
- package/dist/plugins/duration.es.js +1 -1
- package/dist/plugins/duration.es.js.map +1 -1
- package/dist/plugins/relative-time.cjs.map +1 -1
- package/dist/plugins/relative-time.es.js +1 -1
- package/dist/plugins/relative-time.es.js.map +1 -1
- package/dist/time-guard.cjs +3 -1
- package/dist/time-guard.cjs.map +1 -1
- package/dist/time-guard.es.js +11014 -3948
- package/dist/time-guard.es.js.map +1 -1
- package/dist/time-guard.iife.js +3 -1
- package/dist/time-guard.iife.js.map +1 -1
- package/dist/time-guard.umd.js +3 -1
- package/dist/time-guard.umd.js.map +1 -1
- package/dist/types/calendars/index.d.ts +1 -81
- package/dist/types/index.d.ts +1 -20
- package/dist/types/locales/index.d.ts +1 -17
- package/dist/types/plugins/advanced-format.d.ts +1 -0
- package/dist/types/plugins/duration.d.ts +1 -0
- package/dist/types/plugins/relative-time.d.ts +1 -0
- package/package.json +6 -7
- package/dist/types/adapters/temporal.adapter.d.ts +0 -66
- package/dist/types/calendars/calendar.manager.d.ts +0 -52
- package/dist/types/formatters/date.formatter.d.ts +0 -21
- package/dist/types/locales/additional.locale.d.ts +0 -5
- package/dist/types/locales/asian.locale.d.ts +0 -9
- package/dist/types/locales/english.locale.d.ts +0 -6
- package/dist/types/locales/european.locale.d.ts +0 -9
- package/dist/types/locales/locale.manager.d.ts +0 -42
- package/dist/types/locales/locales-data.d.ts +0 -17
- package/dist/types/locales/middle-eastern.locale.d.ts +0 -5
- package/dist/types/locales/nordic.locale.d.ts +0 -6
- package/dist/types/locales/romance.locale.d.ts +0 -7
- package/dist/types/locales/slavic.locale.d.ts +0 -6
- package/dist/types/locales/spanish.locale.d.ts +0 -5
- package/dist/types/plugins/advanced-format/index.d.ts +0 -47
- package/dist/types/plugins/duration/index.d.ts +0 -107
- package/dist/types/plugins/duration/types.d.ts +0 -85
- package/dist/types/plugins/index.d.ts +0 -10
- package/dist/types/plugins/manager.d.ts +0 -58
- package/dist/types/plugins/relative-time/index.d.ts +0 -39
- package/dist/types/plugins/relative-time/types.d.ts +0 -27
- package/dist/types/polyfill-loader.d.ts +0 -6
- package/dist/types/time-guard.d.ts +0 -426
- package/dist/types/types/index.d.ts +0 -578
- package/dist/types/utils/duration-locale.d.ts +0 -33
package/README.en.md
CHANGED
|
@@ -894,8 +894,10 @@ console.log(formatUserDate(date, "ja")); // 水曜日、2024年3月13日 14:30
|
|
|
894
894
|
#### Getting Available Locales Programmatically
|
|
895
895
|
|
|
896
896
|
```typescript
|
|
897
|
+
import { getAvailableLocales } from "@bereasoftware/time-guard";
|
|
898
|
+
|
|
897
899
|
// Get all available locales
|
|
898
|
-
const locales =
|
|
900
|
+
const locales = getAvailableLocales();
|
|
899
901
|
// Returns: ['en', 'en-au', 'en-gb', 'en-ca', 'es', 'es-mx', 'es-us', ...]
|
|
900
902
|
|
|
901
903
|
// Filter by prefix
|
|
@@ -907,7 +909,7 @@ const asianLocales = locales.filter((l) =>
|
|
|
907
909
|
|
|
908
910
|
// Create locale selector UI
|
|
909
911
|
function createLocaleSelector() {
|
|
910
|
-
const locales =
|
|
912
|
+
const locales = getAvailableLocales();
|
|
911
913
|
return locales.map((locale) => ({
|
|
912
914
|
code: locale,
|
|
913
915
|
label: new Intl.DisplayNames("en", { type: "language" }).of(locale),
|
|
@@ -1357,7 +1359,8 @@ inNYC.format("YYYY-MM-DD HH:mm:ss Z"); // 2024-03-13 10:30:00 -04:00
|
|
|
1357
1359
|
inTokyo.format("YYYY-MM-DD HH:mm:ss Z"); // 2024-03-13 23:30:00 +09:00
|
|
1358
1360
|
|
|
1359
1361
|
// Get all available locales
|
|
1360
|
-
|
|
1362
|
+
import { getAvailableLocales } from "@bereasoftware/time-guard";
|
|
1363
|
+
getAvailableLocales(); // Array of 40+ locale codes
|
|
1361
1364
|
```
|
|
1362
1365
|
|
|
1363
1366
|
### 🎨 Format Patterns
|
|
@@ -1521,7 +1524,7 @@ time-guard/
|
|
|
1521
1524
|
├── src/
|
|
1522
1525
|
│ ├── index.ts # Lightweight core (~5KB gzip, EN/ES)
|
|
1523
1526
|
│ ├── polyfill-loader.ts # Temporal polyfill loader
|
|
1524
|
-
│ ├──
|
|
1527
|
+
│ ├── index.ts # Main class and entry point
|
|
1525
1528
|
│ ├── adapters/
|
|
1526
1529
|
│ │ └── temporal.adapter.ts # Temporal API wrapper
|
|
1527
1530
|
│ ├── calendars/ # 6 calendar systems
|
package/README.md
CHANGED
|
@@ -957,8 +957,10 @@ console.log(formatUserDate(date, 'ja')); // 水曜日、2024年3月13日 14:30
|
|
|
957
957
|
#### Obtener Locales Disponibles Programáticamente
|
|
958
958
|
|
|
959
959
|
```typescript
|
|
960
|
+
import { getAvailableLocales } from "@bereasoftware/time-guard";
|
|
961
|
+
|
|
960
962
|
// Get all available locales
|
|
961
|
-
const locales =
|
|
963
|
+
const locales = getAvailableLocales();
|
|
962
964
|
// Returns: ['en', 'en-au', 'en-gb', 'en-ca', 'es', 'es-mx', 'es-us', ...]
|
|
963
965
|
|
|
964
966
|
// Filter by prefix
|
|
@@ -970,7 +972,7 @@ const asianLocales = locales.filter((l) =>
|
|
|
970
972
|
|
|
971
973
|
// Create locale selector UI
|
|
972
974
|
function createLocaleSelector() {
|
|
973
|
-
const locales =
|
|
975
|
+
const locales = getAvailableLocales();
|
|
974
976
|
return locales.map((locale) => ({
|
|
975
977
|
code: locale,
|
|
976
978
|
label: new Intl.DisplayNames('en', { type: 'language' }).of(locale),
|
|
@@ -1440,7 +1442,8 @@ inNYC.format('YYYY-MM-DD HH:mm:ss Z'); // 2024-03-13 10:30:00 -04:00
|
|
|
1440
1442
|
inTokyo.format('YYYY-MM-DD HH:mm:ss Z'); // 2024-03-13 23:30:00 +09:00
|
|
1441
1443
|
|
|
1442
1444
|
// Get all available locales
|
|
1443
|
-
|
|
1445
|
+
import { getAvailableLocales } from "@bereasoftware/time-guard";
|
|
1446
|
+
getAvailableLocales(); // Array of 40+ locale codes
|
|
1444
1447
|
```
|
|
1445
1448
|
|
|
1446
1449
|
### 🎨 Format Patterns
|
|
@@ -1705,7 +1708,7 @@ time-guard/
|
|
|
1705
1708
|
├── src/
|
|
1706
1709
|
│ ├── index.ts # Core ligero (~5KB gzip, EN/ES)
|
|
1707
1710
|
│ ├── polyfill-loader.ts # Cargador del polyfill Temporal
|
|
1708
|
-
│ ├──
|
|
1711
|
+
│ ├── index.ts # Clase principal y punto de entrada
|
|
1709
1712
|
│ ├── adapters/
|
|
1710
1713
|
│ │ └── temporal.adapter.ts # Wrapper del API Temporal
|
|
1711
1714
|
│ ├── calendars/ # 6 sistemas de calendario
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! time-guard v2.5.
|
|
1
|
+
/*! time-guard v2.5.3 | (c) 2026 Berea-Soft | MIT License | https://github.com/Berea-Soft/time-guard */
|
|
2
2
|
//#region src/calendars/index.ts
|
|
3
3
|
var e = class {
|
|
4
4
|
id = "islamic";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var e=class{name=`advanced-format`;version=`1.0.0`;install(e){let t=e.prototype.format;e.prototype.format=function(e){if(!e||typeof e!=`string`||!/Q|Do|w|W|gggg|GGGG|k{1,2}|X|x|zzz?/.test(e))return t.call(this,e);let n=this.toTemporal(),r=`toPlainDateTime`in n?n.toPlainDateTime():n,i=e=>{let t=[`th`,`st`,`nd`,`rd`],n=e%100;return e+(t[(n-20)%10]||t[n]||t[0])},a=(e,t)=>String(e).padStart(t,`0`),o=e=>{let t=new Date(e.year,0,4),n=new Date(t);n.setDate(t.getDate()-t.getDay()+(t.getDay()===0?-6:1));let r=new Date(e.year,e.month-1,e.day),i=Math.floor((r.getTime()-n.getTime())/(10080*60*1e3))+1;return Math.max(1,i)},s=e=>{let t=Math.ceil((e.day+new Date(e.year,e.month-1,1).getDay())/7);return Math.max(1,t)},c=e=>{let t=new Date(e.year,e.month-1,e.day),n=t.getTime()<new Date(e.year,0,1).getTime()?-1:+(t.getTime()>=new Date(e.year+1,0,1).getTime());return e.year+n},l=e=>{let t=e.month===1&&e.day<4?-1:+(e.month===12&&e.day>28);return e.year+t},u=e.replace(/Q|Do|w|W|gggg|GGGG|k{1,2}|X|x|zzz?/g,e=>{let t=``;switch(e){case`Q`:t=String(Math.ceil(r.month/3));break;case`Do`:t=i(r.day);break;case`W`:case`WW`:t=a(o(r),e===`W`?1:2);break;case`w`:case`ww`:t=a(s(r),e===`w`?1:2);break;case`GGGG`:t=String(c(r));break;case`gggg`:t=String(l(r));break;case`k`:case`kk`:t=a(r.hour===0?24:r.hour,e===`k`?1:2);break;case`X`:t=String(Math.floor(this.valueOf()/1e3));break;case`x`:t=String(this.valueOf());break;case`z`:t=`${this.getTimezoneOffset()}`;break;case`zzz`:t=`${this.getTimezoneOffsetLong()}`;break;default:return e}return`[${t}]`});return t.call(this,u)}}
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var e=class{name=`advanced-format`;version=`1.0.0`;install(e){let t=e.prototype.format;e.prototype.format=function(e){if(!e||typeof e!=`string`||!/Q|Do|w|W|gggg|GGGG|k{1,2}|X|x|zzz?/.test(e))return t.call(this,e);let n=this.toTemporal(),r=`toPlainDateTime`in n?n.toPlainDateTime():n,i=e=>{let t=[`th`,`st`,`nd`,`rd`],n=e%100;return e+(t[(n-20)%10]||t[n]||t[0])},a=(e,t)=>String(e).padStart(t,`0`),o=e=>{let t=new Date(e.year,0,4),n=new Date(t);n.setDate(t.getDate()-t.getDay()+(t.getDay()===0?-6:1));let r=new Date(e.year,e.month-1,e.day),i=Math.floor((r.getTime()-n.getTime())/(10080*60*1e3))+1;return Math.max(1,i)},s=e=>{let t=Math.ceil((e.day+new Date(e.year,e.month-1,1).getDay())/7);return Math.max(1,t)},c=e=>{let t=new Date(e.year,e.month-1,e.day),n=t.getTime()<new Date(e.year,0,1).getTime()?-1:+(t.getTime()>=new Date(e.year+1,0,1).getTime());return e.year+n},l=e=>{let t=e.month===1&&e.day<4?-1:+(e.month===12&&e.day>28);return e.year+t},u=e.replace(/Q|Do|w|W|gggg|GGGG|k{1,2}|X|x|zzz?/g,e=>{let t=``;switch(e){case`Q`:t=String(Math.ceil(r.month/3));break;case`Do`:t=i(r.day);break;case`W`:case`WW`:t=a(o(r),e===`W`?1:2);break;case`w`:case`ww`:t=a(s(r),e===`w`?1:2);break;case`GGGG`:t=String(c(r));break;case`gggg`:t=String(l(r));break;case`k`:case`kk`:t=a(r.hour===0?24:r.hour,e===`k`?1:2);break;case`X`:t=String(Math.floor(this.valueOf()/1e3));break;case`x`:t=String(this.valueOf());break;case`z`:t=`${this.getTimezoneOffset()}`;break;case`zzz`:t=`${this.getTimezoneOffsetLong()}`;break;default:return e}return`[${t}]`});return t.call(this,u)}}},t=new e;exports.AdvancedFormatPlugin=e,exports.default=t;
|
|
2
2
|
//# sourceMappingURL=advanced-format.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"advanced-format.cjs","names":[],"sources":["../../src/plugins/advanced-format/index.ts"],"sourcesContent":["/**\r\n * TimeGuard Advanced Format Plugin\r\n * Adds advanced format tokens: Q (quarter), Do (ordinal), w (week), etc.\r\n * Follows SOLID principles and extends core formatting capabilities\r\n */\r\n\r\nimport type { ITimeGuardPlugin } from '../../types';\r\nimport type { TimeGuard } from '../../time-guard';\r\nimport type { Temporal } from '@js-temporal/polyfill';\r\n\r\nexport class AdvancedFormatPlugin implements ITimeGuardPlugin {\r\n name = 'advanced-format';\r\n version = '1.0.0';\r\n\r\n /**\r\n * Install plugin into TimeGuard\r\n */\r\n install(TimeGuardClass: typeof TimeGuard): void {\r\n // Store original format method\r\n const originalFormat = TimeGuardClass.prototype.format;\r\n\r\n /**\r\n * Extended format method with advanced tokens\r\n */\r\n (TimeGuardClass.prototype as any).format = function (pattern: string) {\r\n if (!pattern || typeof pattern !== 'string') {\r\n return originalFormat.call(this, pattern);\r\n }\r\n\r\n // Check if pattern contains advanced tokens\r\n if (!/Q|Do|w|W|gggg|GGGG|k{1,2}|X|x|zzz?/.test(pattern)) {\r\n return originalFormat.call(this, pattern);\r\n }\r\n\r\n // Get the underlying Temporal object\r\n const temporal = this.toTemporal();\r\n const temporal_dt =\r\n 'toPlainDateTime' in temporal\r\n ? (temporal as any).toPlainDateTime()\r\n : (temporal as Temporal.PlainDateTime);\r\n \r\n const ordinalFn = (n: number) => {\r\n const suffixes = ['th', 'st', 'nd', 'rd'];\r\n const v = n % 100;\r\n return n + (suffixes[(v - 20) % 10] || suffixes[v] || suffixes[0]);\r\n };\r\n const padFn = (n: number, length: number) => String(n).padStart(length, '0');\r\n const getISOWeek = (temporal: any) => {\r\n const jan4 = new Date(temporal.year, 0, 4);\r\n const week1Start = new Date(jan4);\r\n week1Start.setDate(jan4.getDate() - jan4.getDay() + (jan4.getDay() === 0 ? -6 : 1));\r\n const currentDate = new Date(temporal.year, temporal.month - 1, temporal.day);\r\n const weekNum = Math.floor((currentDate.getTime() - week1Start.getTime()) / (7 * 24 * 60 * 60 * 1000)) + 1;\r\n return Math.max(1, weekNum);\r\n };\r\n const getWeekOfYear = (temporal: any) => {\r\n const weekNum = Math.ceil(((temporal.day + new Date(temporal.year, temporal.month - 1, 1).getDay()) / 7));\r\n return Math.max(1, weekNum);\r\n };\r\n const getISOWeekYear = (temporal: any) => {\r\n const currentDate = new Date(temporal.year, temporal.month - 1, temporal.day);\r\n const yearAdjust = currentDate.getTime() < new Date(temporal.year, 0, 1).getTime() ? -1 : currentDate.getTime() >= new Date(temporal.year + 1, 0, 1).getTime() ? 1 : 0;\r\n return temporal.year + yearAdjust;\r\n };\r\n const getWeekYear = (temporal: any) => {\r\n const yearAdjust = temporal.month === 1 && temporal.day < 4 ? -1 : temporal.month === 12 && temporal.day > 28 ? 1 : 0;\r\n return temporal.year + yearAdjust;\r\n };\r\n\r\n // Replace advanced tokens - wrap results in brackets to protect from standard formatter\r\n let result = pattern.replace(\r\n /Q|Do|w|W|gggg|GGGG|k{1,2}|X|x|zzz?/g,\r\n (match) => {\r\n let replacement = '';\r\n switch (match) {\r\n // Quarter\r\n case 'Q':\r\n replacement = String(Math.ceil((temporal_dt.month) / 3));\r\n break;\r\n\r\n // Ordinal day\r\n case 'Do':\r\n replacement = ordinalFn(temporal_dt.day);\r\n break;\r\n\r\n // Week of year (ISO)\r\n case 'W':\r\n case 'WW':\r\n replacement = padFn(getISOWeek(temporal_dt), match === 'W' ? 1 : 2);\r\n break;\r\n\r\n // Week of year (locale)\r\n case 'w':\r\n case 'ww':\r\n replacement = padFn(getWeekOfYear(temporal_dt), match === 'w' ? 1 : 2);\r\n break;\r\n\r\n // ISO week year\r\n case 'GGGG':\r\n replacement = String(getISOWeekYear(temporal_dt));\r\n break;\r\n\r\n // Week year\r\n case 'gggg':\r\n replacement = String(getWeekYear(temporal_dt));\r\n break;\r\n\r\n // Hour (1-24)\r\n case 'k':\r\n case 'kk':\r\n const hour = temporal_dt.hour === 0 ? 24 : temporal_dt.hour;\r\n replacement = padFn(hour, match === 'k' ? 1 : 2);\r\n break;\r\n\r\n // Unix seconds timestamp\r\n case 'X':\r\n replacement = String(Math.floor(this.valueOf() / 1000));\r\n break;\r\n\r\n // Unix milliseconds timestamp\r\n case 'x':\r\n replacement = String(this.valueOf());\r\n break;\r\n\r\n // Timezone offset\r\n case 'z':\r\n replacement = `${this.getTimezoneOffset()}`;\r\n break;\r\n\r\n case 'zzz':\r\n replacement = `${this.getTimezoneOffsetLong()}`;\r\n break;\r\n\r\n default:\r\n return match;\r\n }\r\n // Wrap in brackets to protect from standard formatter\r\n return `[${replacement}]`;\r\n },\r\n );\r\n\r\n // Apply standard format to the result\r\n return originalFormat.call(this, result);\r\n };\r\n }\r\n\r\n /**\r\n * Get ordinal suffix (1st, 2nd, 3rd, etc.)\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getOrdinal(n: number): string {\r\n const suffixes = ['th', 'st', 'nd', 'rd'];\r\n const v = n % 100;\r\n return n + (suffixes[(v - 20) % 10] || suffixes[v] || suffixes[0]);\r\n }\r\n\r\n /**\r\n * Pad number with leading zeros\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private padNumber(n: number, length: number): string {\r\n return String(n).padStart(length, '0');\r\n }\r\n\r\n /**\r\n * Get ISO week number\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getISOWeek(temporal: Temporal.PlainDateTime): number {\r\n // Simple ISO week calculation\r\n const jan4 = new Date(temporal.year, 0, 4);\r\n const week1Start = new Date(jan4);\r\n week1Start.setDate(jan4.getDate() - jan4.getDay() + (jan4.getDay() === 0 ? -6 : 1));\r\n\r\n const currentDate = new Date(temporal.year, temporal.month - 1, temporal.day);\r\n const weekNum = Math.floor(\r\n (currentDate.getTime() - week1Start.getTime()) / (7 * 24 * 60 * 60 * 1000),\r\n ) + 1;\r\n\r\n return Math.max(1, weekNum);\r\n }\r\n\r\n /**\r\n * Get week of year (locale-based)\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getWeekOfYear(temporal: Temporal.PlainDateTime): number {\r\n const weekNum = Math.ceil(\r\n ((temporal.day + new Date(temporal.year, temporal.month - 1, 1).getDay()) / 7),\r\n );\r\n return Math.max(1, weekNum);\r\n }\r\n\r\n /**\r\n * Get ISO week year\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getISOWeekYear(temporal: Temporal.PlainDateTime): number {\r\n const currentDate = new Date(temporal.year, temporal.month - 1, temporal.day);\r\n const yearAdjust =\r\n currentDate.getTime() < new Date(temporal.year, 0, 1).getTime()\r\n ? -1\r\n : currentDate.getTime() >= new Date(temporal.year + 1, 0, 1).getTime()\r\n ? 1\r\n : 0;\r\n\r\n return temporal.year + yearAdjust;\r\n }\r\n\r\n /**\r\n * Get week year\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getWeekYear(temporal: Temporal.PlainDateTime): number {\r\n const yearAdjust =\r\n temporal.month === 1 && temporal.day < 4\r\n ? -1\r\n : temporal.month === 12 && temporal.day > 28\r\n ? 1\r\n : 0;\r\n return temporal.year + yearAdjust;\r\n }\r\n\r\n /**\r\n * Get timezone offset short form\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getTimezoneOffset(): string {\r\n try {\r\n const now = new Date();\r\n const formatter = new Intl.DateTimeFormat('en-US', {\r\n timeZone: 'UTC',\r\n timeZoneName: 'short',\r\n });\r\n return formatter.formatToParts(now).find(p => p.type === 'timeZoneName')?.value || 'UTC';\r\n } catch {\r\n return 'UTC';\r\n }\r\n }\r\n\r\n /**\r\n * Get timezone offset long form\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getTimezoneOffsetLong(): string {\r\n try {\r\n const now = new Date();\r\n const formatter = new Intl.DateTimeFormat('en-US', {\r\n timeZone: 'UTC',\r\n timeZoneName: 'long',\r\n });\r\n return formatter.formatToParts(now).find(p => p.type === 'timeZoneName')?.value || 'Coordinated Universal Time';\r\n } catch {\r\n return 'Coordinated Universal Time';\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Create and export default instance\r\n */\r\nexport default new AdvancedFormatPlugin();\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"advanced-format.cjs","names":[],"sources":["../../src/plugins/advanced-format/index.ts"],"sourcesContent":["/**\r\n * TimeGuard Advanced Format Plugin\r\n * Adds advanced format tokens: Q (quarter), Do (ordinal), w (week), etc.\r\n * Follows SOLID principles and extends core formatting capabilities\r\n */\r\n\r\nimport type { ITimeGuardPlugin } from '../../types';\r\nimport type { TimeGuard } from '../../index';\r\nimport { Temporal } from '@js-temporal/polyfill';\r\n\r\nexport class AdvancedFormatPlugin implements ITimeGuardPlugin {\r\n name = 'advanced-format';\r\n version = '1.0.0';\r\n\r\n /**\r\n * Install plugin into TimeGuard\r\n */\r\n install(TimeGuardClass: typeof TimeGuard): void {\r\n // Store original format method\r\n const originalFormat = TimeGuardClass.prototype.format;\r\n\r\n /**\r\n * Extended format method with advanced tokens\r\n */\r\n (TimeGuardClass.prototype as any).format = function (pattern: string) {\r\n if (!pattern || typeof pattern !== 'string') {\r\n return originalFormat.call(this, pattern);\r\n }\r\n\r\n // Check if pattern contains advanced tokens\r\n if (!/Q|Do|w|W|gggg|GGGG|k{1,2}|X|x|zzz?/.test(pattern)) {\r\n return originalFormat.call(this, pattern);\r\n }\r\n\r\n // Get the underlying Temporal object\r\n const temporal = this.toTemporal();\r\n const temporal_dt =\r\n 'toPlainDateTime' in temporal\r\n ? (temporal as any).toPlainDateTime()\r\n : (temporal as Temporal.PlainDateTime);\r\n \r\n const ordinalFn = (n: number) => {\r\n const suffixes = ['th', 'st', 'nd', 'rd'];\r\n const v = n % 100;\r\n return n + (suffixes[(v - 20) % 10] || suffixes[v] || suffixes[0]);\r\n };\r\n const padFn = (n: number, length: number) => String(n).padStart(length, '0');\r\n const getISOWeek = (temporal: any) => {\r\n const jan4 = new Date(temporal.year, 0, 4);\r\n const week1Start = new Date(jan4);\r\n week1Start.setDate(jan4.getDate() - jan4.getDay() + (jan4.getDay() === 0 ? -6 : 1));\r\n const currentDate = new Date(temporal.year, temporal.month - 1, temporal.day);\r\n const weekNum = Math.floor((currentDate.getTime() - week1Start.getTime()) / (7 * 24 * 60 * 60 * 1000)) + 1;\r\n return Math.max(1, weekNum);\r\n };\r\n const getWeekOfYear = (temporal: any) => {\r\n const weekNum = Math.ceil(((temporal.day + new Date(temporal.year, temporal.month - 1, 1).getDay()) / 7));\r\n return Math.max(1, weekNum);\r\n };\r\n const getISOWeekYear = (temporal: any) => {\r\n const currentDate = new Date(temporal.year, temporal.month - 1, temporal.day);\r\n const yearAdjust = currentDate.getTime() < new Date(temporal.year, 0, 1).getTime() ? -1 : currentDate.getTime() >= new Date(temporal.year + 1, 0, 1).getTime() ? 1 : 0;\r\n return temporal.year + yearAdjust;\r\n };\r\n const getWeekYear = (temporal: any) => {\r\n const yearAdjust = temporal.month === 1 && temporal.day < 4 ? -1 : temporal.month === 12 && temporal.day > 28 ? 1 : 0;\r\n return temporal.year + yearAdjust;\r\n };\r\n\r\n // Replace advanced tokens - wrap results in brackets to protect from standard formatter\r\n let result = pattern.replace(\r\n /Q|Do|w|W|gggg|GGGG|k{1,2}|X|x|zzz?/g,\r\n (match) => {\r\n let replacement = '';\r\n switch (match) {\r\n // Quarter\r\n case 'Q':\r\n replacement = String(Math.ceil((temporal_dt.month) / 3));\r\n break;\r\n\r\n // Ordinal day\r\n case 'Do':\r\n replacement = ordinalFn(temporal_dt.day);\r\n break;\r\n\r\n // Week of year (ISO)\r\n case 'W':\r\n case 'WW':\r\n replacement = padFn(getISOWeek(temporal_dt), match === 'W' ? 1 : 2);\r\n break;\r\n\r\n // Week of year (locale)\r\n case 'w':\r\n case 'ww':\r\n replacement = padFn(getWeekOfYear(temporal_dt), match === 'w' ? 1 : 2);\r\n break;\r\n\r\n // ISO week year\r\n case 'GGGG':\r\n replacement = String(getISOWeekYear(temporal_dt));\r\n break;\r\n\r\n // Week year\r\n case 'gggg':\r\n replacement = String(getWeekYear(temporal_dt));\r\n break;\r\n\r\n // Hour (1-24)\r\n case 'k':\r\n case 'kk':\r\n const hour = temporal_dt.hour === 0 ? 24 : temporal_dt.hour;\r\n replacement = padFn(hour, match === 'k' ? 1 : 2);\r\n break;\r\n\r\n // Unix seconds timestamp\r\n case 'X':\r\n replacement = String(Math.floor(this.valueOf() / 1000));\r\n break;\r\n\r\n // Unix milliseconds timestamp\r\n case 'x':\r\n replacement = String(this.valueOf());\r\n break;\r\n\r\n // Timezone offset\r\n case 'z':\r\n replacement = `${this.getTimezoneOffset()}`;\r\n break;\r\n\r\n case 'zzz':\r\n replacement = `${this.getTimezoneOffsetLong()}`;\r\n break;\r\n\r\n default:\r\n return match;\r\n }\r\n // Wrap in brackets to protect from standard formatter\r\n return `[${replacement}]`;\r\n },\r\n );\r\n\r\n // Apply standard format to the result\r\n return originalFormat.call(this, result);\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Create and export default instance\r\n */\r\nexport default new AdvancedFormatPlugin();\r\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! time-guard v2.5.
|
|
1
|
+
/*! time-guard v2.5.3 | (c) 2026 Berea-Soft | MIT License | https://github.com/Berea-Soft/time-guard */
|
|
2
2
|
//#region src/plugins/advanced-format/index.ts
|
|
3
3
|
var e = class {
|
|
4
4
|
name = "advanced-format";
|
|
@@ -75,58 +75,6 @@ var e = class {
|
|
|
75
75
|
return t.call(this, u);
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
|
-
getOrdinal(e) {
|
|
79
|
-
let t = [
|
|
80
|
-
"th",
|
|
81
|
-
"st",
|
|
82
|
-
"nd",
|
|
83
|
-
"rd"
|
|
84
|
-
], n = e % 100;
|
|
85
|
-
return e + (t[(n - 20) % 10] || t[n] || t[0]);
|
|
86
|
-
}
|
|
87
|
-
padNumber(e, t) {
|
|
88
|
-
return String(e).padStart(t, "0");
|
|
89
|
-
}
|
|
90
|
-
getISOWeek(e) {
|
|
91
|
-
let t = new Date(e.year, 0, 4), n = new Date(t);
|
|
92
|
-
n.setDate(t.getDate() - t.getDay() + (t.getDay() === 0 ? -6 : 1));
|
|
93
|
-
let r = new Date(e.year, e.month - 1, e.day), i = Math.floor((r.getTime() - n.getTime()) / (10080 * 60 * 1e3)) + 1;
|
|
94
|
-
return Math.max(1, i);
|
|
95
|
-
}
|
|
96
|
-
getWeekOfYear(e) {
|
|
97
|
-
let t = Math.ceil((e.day + new Date(e.year, e.month - 1, 1).getDay()) / 7);
|
|
98
|
-
return Math.max(1, t);
|
|
99
|
-
}
|
|
100
|
-
getISOWeekYear(e) {
|
|
101
|
-
let t = new Date(e.year, e.month - 1, e.day), n = t.getTime() < new Date(e.year, 0, 1).getTime() ? -1 : +(t.getTime() >= new Date(e.year + 1, 0, 1).getTime());
|
|
102
|
-
return e.year + n;
|
|
103
|
-
}
|
|
104
|
-
getWeekYear(e) {
|
|
105
|
-
let t = e.month === 1 && e.day < 4 ? -1 : +(e.month === 12 && e.day > 28);
|
|
106
|
-
return e.year + t;
|
|
107
|
-
}
|
|
108
|
-
getTimezoneOffset() {
|
|
109
|
-
try {
|
|
110
|
-
let e = /* @__PURE__ */ new Date();
|
|
111
|
-
return new Intl.DateTimeFormat("en-US", {
|
|
112
|
-
timeZone: "UTC",
|
|
113
|
-
timeZoneName: "short"
|
|
114
|
-
}).formatToParts(e).find((e) => e.type === "timeZoneName")?.value || "UTC";
|
|
115
|
-
} catch {
|
|
116
|
-
return "UTC";
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
getTimezoneOffsetLong() {
|
|
120
|
-
try {
|
|
121
|
-
let e = /* @__PURE__ */ new Date();
|
|
122
|
-
return new Intl.DateTimeFormat("en-US", {
|
|
123
|
-
timeZone: "UTC",
|
|
124
|
-
timeZoneName: "long"
|
|
125
|
-
}).formatToParts(e).find((e) => e.type === "timeZoneName")?.value || "Coordinated Universal Time";
|
|
126
|
-
} catch {
|
|
127
|
-
return "Coordinated Universal Time";
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
78
|
}, t = new e();
|
|
131
79
|
//#endregion
|
|
132
80
|
export { e as AdvancedFormatPlugin, t as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"advanced-format.es.js","names":[],"sources":["../../src/plugins/advanced-format/index.ts"],"sourcesContent":["/**\r\n * TimeGuard Advanced Format Plugin\r\n * Adds advanced format tokens: Q (quarter), Do (ordinal), w (week), etc.\r\n * Follows SOLID principles and extends core formatting capabilities\r\n */\r\n\r\nimport type { ITimeGuardPlugin } from '../../types';\r\nimport type { TimeGuard } from '../../time-guard';\r\nimport type { Temporal } from '@js-temporal/polyfill';\r\n\r\nexport class AdvancedFormatPlugin implements ITimeGuardPlugin {\r\n name = 'advanced-format';\r\n version = '1.0.0';\r\n\r\n /**\r\n * Install plugin into TimeGuard\r\n */\r\n install(TimeGuardClass: typeof TimeGuard): void {\r\n // Store original format method\r\n const originalFormat = TimeGuardClass.prototype.format;\r\n\r\n /**\r\n * Extended format method with advanced tokens\r\n */\r\n (TimeGuardClass.prototype as any).format = function (pattern: string) {\r\n if (!pattern || typeof pattern !== 'string') {\r\n return originalFormat.call(this, pattern);\r\n }\r\n\r\n // Check if pattern contains advanced tokens\r\n if (!/Q|Do|w|W|gggg|GGGG|k{1,2}|X|x|zzz?/.test(pattern)) {\r\n return originalFormat.call(this, pattern);\r\n }\r\n\r\n // Get the underlying Temporal object\r\n const temporal = this.toTemporal();\r\n const temporal_dt =\r\n 'toPlainDateTime' in temporal\r\n ? (temporal as any).toPlainDateTime()\r\n : (temporal as Temporal.PlainDateTime);\r\n \r\n const ordinalFn = (n: number) => {\r\n const suffixes = ['th', 'st', 'nd', 'rd'];\r\n const v = n % 100;\r\n return n + (suffixes[(v - 20) % 10] || suffixes[v] || suffixes[0]);\r\n };\r\n const padFn = (n: number, length: number) => String(n).padStart(length, '0');\r\n const getISOWeek = (temporal: any) => {\r\n const jan4 = new Date(temporal.year, 0, 4);\r\n const week1Start = new Date(jan4);\r\n week1Start.setDate(jan4.getDate() - jan4.getDay() + (jan4.getDay() === 0 ? -6 : 1));\r\n const currentDate = new Date(temporal.year, temporal.month - 1, temporal.day);\r\n const weekNum = Math.floor((currentDate.getTime() - week1Start.getTime()) / (7 * 24 * 60 * 60 * 1000)) + 1;\r\n return Math.max(1, weekNum);\r\n };\r\n const getWeekOfYear = (temporal: any) => {\r\n const weekNum = Math.ceil(((temporal.day + new Date(temporal.year, temporal.month - 1, 1).getDay()) / 7));\r\n return Math.max(1, weekNum);\r\n };\r\n const getISOWeekYear = (temporal: any) => {\r\n const currentDate = new Date(temporal.year, temporal.month - 1, temporal.day);\r\n const yearAdjust = currentDate.getTime() < new Date(temporal.year, 0, 1).getTime() ? -1 : currentDate.getTime() >= new Date(temporal.year + 1, 0, 1).getTime() ? 1 : 0;\r\n return temporal.year + yearAdjust;\r\n };\r\n const getWeekYear = (temporal: any) => {\r\n const yearAdjust = temporal.month === 1 && temporal.day < 4 ? -1 : temporal.month === 12 && temporal.day > 28 ? 1 : 0;\r\n return temporal.year + yearAdjust;\r\n };\r\n\r\n // Replace advanced tokens - wrap results in brackets to protect from standard formatter\r\n let result = pattern.replace(\r\n /Q|Do|w|W|gggg|GGGG|k{1,2}|X|x|zzz?/g,\r\n (match) => {\r\n let replacement = '';\r\n switch (match) {\r\n // Quarter\r\n case 'Q':\r\n replacement = String(Math.ceil((temporal_dt.month) / 3));\r\n break;\r\n\r\n // Ordinal day\r\n case 'Do':\r\n replacement = ordinalFn(temporal_dt.day);\r\n break;\r\n\r\n // Week of year (ISO)\r\n case 'W':\r\n case 'WW':\r\n replacement = padFn(getISOWeek(temporal_dt), match === 'W' ? 1 : 2);\r\n break;\r\n\r\n // Week of year (locale)\r\n case 'w':\r\n case 'ww':\r\n replacement = padFn(getWeekOfYear(temporal_dt), match === 'w' ? 1 : 2);\r\n break;\r\n\r\n // ISO week year\r\n case 'GGGG':\r\n replacement = String(getISOWeekYear(temporal_dt));\r\n break;\r\n\r\n // Week year\r\n case 'gggg':\r\n replacement = String(getWeekYear(temporal_dt));\r\n break;\r\n\r\n // Hour (1-24)\r\n case 'k':\r\n case 'kk':\r\n const hour = temporal_dt.hour === 0 ? 24 : temporal_dt.hour;\r\n replacement = padFn(hour, match === 'k' ? 1 : 2);\r\n break;\r\n\r\n // Unix seconds timestamp\r\n case 'X':\r\n replacement = String(Math.floor(this.valueOf() / 1000));\r\n break;\r\n\r\n // Unix milliseconds timestamp\r\n case 'x':\r\n replacement = String(this.valueOf());\r\n break;\r\n\r\n // Timezone offset\r\n case 'z':\r\n replacement = `${this.getTimezoneOffset()}`;\r\n break;\r\n\r\n case 'zzz':\r\n replacement = `${this.getTimezoneOffsetLong()}`;\r\n break;\r\n\r\n default:\r\n return match;\r\n }\r\n // Wrap in brackets to protect from standard formatter\r\n return `[${replacement}]`;\r\n },\r\n );\r\n\r\n // Apply standard format to the result\r\n return originalFormat.call(this, result);\r\n };\r\n }\r\n\r\n /**\r\n * Get ordinal suffix (1st, 2nd, 3rd, etc.)\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getOrdinal(n: number): string {\r\n const suffixes = ['th', 'st', 'nd', 'rd'];\r\n const v = n % 100;\r\n return n + (suffixes[(v - 20) % 10] || suffixes[v] || suffixes[0]);\r\n }\r\n\r\n /**\r\n * Pad number with leading zeros\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private padNumber(n: number, length: number): string {\r\n return String(n).padStart(length, '0');\r\n }\r\n\r\n /**\r\n * Get ISO week number\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getISOWeek(temporal: Temporal.PlainDateTime): number {\r\n // Simple ISO week calculation\r\n const jan4 = new Date(temporal.year, 0, 4);\r\n const week1Start = new Date(jan4);\r\n week1Start.setDate(jan4.getDate() - jan4.getDay() + (jan4.getDay() === 0 ? -6 : 1));\r\n\r\n const currentDate = new Date(temporal.year, temporal.month - 1, temporal.day);\r\n const weekNum = Math.floor(\r\n (currentDate.getTime() - week1Start.getTime()) / (7 * 24 * 60 * 60 * 1000),\r\n ) + 1;\r\n\r\n return Math.max(1, weekNum);\r\n }\r\n\r\n /**\r\n * Get week of year (locale-based)\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getWeekOfYear(temporal: Temporal.PlainDateTime): number {\r\n const weekNum = Math.ceil(\r\n ((temporal.day + new Date(temporal.year, temporal.month - 1, 1).getDay()) / 7),\r\n );\r\n return Math.max(1, weekNum);\r\n }\r\n\r\n /**\r\n * Get ISO week year\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getISOWeekYear(temporal: Temporal.PlainDateTime): number {\r\n const currentDate = new Date(temporal.year, temporal.month - 1, temporal.day);\r\n const yearAdjust =\r\n currentDate.getTime() < new Date(temporal.year, 0, 1).getTime()\r\n ? -1\r\n : currentDate.getTime() >= new Date(temporal.year + 1, 0, 1).getTime()\r\n ? 1\r\n : 0;\r\n\r\n return temporal.year + yearAdjust;\r\n }\r\n\r\n /**\r\n * Get week year\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getWeekYear(temporal: Temporal.PlainDateTime): number {\r\n const yearAdjust =\r\n temporal.month === 1 && temporal.day < 4\r\n ? -1\r\n : temporal.month === 12 && temporal.day > 28\r\n ? 1\r\n : 0;\r\n return temporal.year + yearAdjust;\r\n }\r\n\r\n /**\r\n * Get timezone offset short form\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getTimezoneOffset(): string {\r\n try {\r\n const now = new Date();\r\n const formatter = new Intl.DateTimeFormat('en-US', {\r\n timeZone: 'UTC',\r\n timeZoneName: 'short',\r\n });\r\n return formatter.formatToParts(now).find(p => p.type === 'timeZoneName')?.value || 'UTC';\r\n } catch {\r\n return 'UTC';\r\n }\r\n }\r\n\r\n /**\r\n * Get timezone offset long form\r\n */\r\n // @ts-expect-error - Method called dynamically within replace callback\r\n private getTimezoneOffsetLong(): string {\r\n try {\r\n const now = new Date();\r\n const formatter = new Intl.DateTimeFormat('en-US', {\r\n timeZone: 'UTC',\r\n timeZoneName: 'long',\r\n });\r\n return formatter.formatToParts(now).find(p => p.type === 'timeZoneName')?.value || 'Coordinated Universal Time';\r\n } catch {\r\n return 'Coordinated Universal Time';\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Create and export default instance\r\n */\r\nexport default new AdvancedFormatPlugin();\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"advanced-format.es.js","names":[],"sources":["../../src/plugins/advanced-format/index.ts"],"sourcesContent":["/**\r\n * TimeGuard Advanced Format Plugin\r\n * Adds advanced format tokens: Q (quarter), Do (ordinal), w (week), etc.\r\n * Follows SOLID principles and extends core formatting capabilities\r\n */\r\n\r\nimport type { ITimeGuardPlugin } from '../../types';\r\nimport type { TimeGuard } from '../../index';\r\nimport { Temporal } from '@js-temporal/polyfill';\r\n\r\nexport class AdvancedFormatPlugin implements ITimeGuardPlugin {\r\n name = 'advanced-format';\r\n version = '1.0.0';\r\n\r\n /**\r\n * Install plugin into TimeGuard\r\n */\r\n install(TimeGuardClass: typeof TimeGuard): void {\r\n // Store original format method\r\n const originalFormat = TimeGuardClass.prototype.format;\r\n\r\n /**\r\n * Extended format method with advanced tokens\r\n */\r\n (TimeGuardClass.prototype as any).format = function (pattern: string) {\r\n if (!pattern || typeof pattern !== 'string') {\r\n return originalFormat.call(this, pattern);\r\n }\r\n\r\n // Check if pattern contains advanced tokens\r\n if (!/Q|Do|w|W|gggg|GGGG|k{1,2}|X|x|zzz?/.test(pattern)) {\r\n return originalFormat.call(this, pattern);\r\n }\r\n\r\n // Get the underlying Temporal object\r\n const temporal = this.toTemporal();\r\n const temporal_dt =\r\n 'toPlainDateTime' in temporal\r\n ? (temporal as any).toPlainDateTime()\r\n : (temporal as Temporal.PlainDateTime);\r\n \r\n const ordinalFn = (n: number) => {\r\n const suffixes = ['th', 'st', 'nd', 'rd'];\r\n const v = n % 100;\r\n return n + (suffixes[(v - 20) % 10] || suffixes[v] || suffixes[0]);\r\n };\r\n const padFn = (n: number, length: number) => String(n).padStart(length, '0');\r\n const getISOWeek = (temporal: any) => {\r\n const jan4 = new Date(temporal.year, 0, 4);\r\n const week1Start = new Date(jan4);\r\n week1Start.setDate(jan4.getDate() - jan4.getDay() + (jan4.getDay() === 0 ? -6 : 1));\r\n const currentDate = new Date(temporal.year, temporal.month - 1, temporal.day);\r\n const weekNum = Math.floor((currentDate.getTime() - week1Start.getTime()) / (7 * 24 * 60 * 60 * 1000)) + 1;\r\n return Math.max(1, weekNum);\r\n };\r\n const getWeekOfYear = (temporal: any) => {\r\n const weekNum = Math.ceil(((temporal.day + new Date(temporal.year, temporal.month - 1, 1).getDay()) / 7));\r\n return Math.max(1, weekNum);\r\n };\r\n const getISOWeekYear = (temporal: any) => {\r\n const currentDate = new Date(temporal.year, temporal.month - 1, temporal.day);\r\n const yearAdjust = currentDate.getTime() < new Date(temporal.year, 0, 1).getTime() ? -1 : currentDate.getTime() >= new Date(temporal.year + 1, 0, 1).getTime() ? 1 : 0;\r\n return temporal.year + yearAdjust;\r\n };\r\n const getWeekYear = (temporal: any) => {\r\n const yearAdjust = temporal.month === 1 && temporal.day < 4 ? -1 : temporal.month === 12 && temporal.day > 28 ? 1 : 0;\r\n return temporal.year + yearAdjust;\r\n };\r\n\r\n // Replace advanced tokens - wrap results in brackets to protect from standard formatter\r\n let result = pattern.replace(\r\n /Q|Do|w|W|gggg|GGGG|k{1,2}|X|x|zzz?/g,\r\n (match) => {\r\n let replacement = '';\r\n switch (match) {\r\n // Quarter\r\n case 'Q':\r\n replacement = String(Math.ceil((temporal_dt.month) / 3));\r\n break;\r\n\r\n // Ordinal day\r\n case 'Do':\r\n replacement = ordinalFn(temporal_dt.day);\r\n break;\r\n\r\n // Week of year (ISO)\r\n case 'W':\r\n case 'WW':\r\n replacement = padFn(getISOWeek(temporal_dt), match === 'W' ? 1 : 2);\r\n break;\r\n\r\n // Week of year (locale)\r\n case 'w':\r\n case 'ww':\r\n replacement = padFn(getWeekOfYear(temporal_dt), match === 'w' ? 1 : 2);\r\n break;\r\n\r\n // ISO week year\r\n case 'GGGG':\r\n replacement = String(getISOWeekYear(temporal_dt));\r\n break;\r\n\r\n // Week year\r\n case 'gggg':\r\n replacement = String(getWeekYear(temporal_dt));\r\n break;\r\n\r\n // Hour (1-24)\r\n case 'k':\r\n case 'kk':\r\n const hour = temporal_dt.hour === 0 ? 24 : temporal_dt.hour;\r\n replacement = padFn(hour, match === 'k' ? 1 : 2);\r\n break;\r\n\r\n // Unix seconds timestamp\r\n case 'X':\r\n replacement = String(Math.floor(this.valueOf() / 1000));\r\n break;\r\n\r\n // Unix milliseconds timestamp\r\n case 'x':\r\n replacement = String(this.valueOf());\r\n break;\r\n\r\n // Timezone offset\r\n case 'z':\r\n replacement = `${this.getTimezoneOffset()}`;\r\n break;\r\n\r\n case 'zzz':\r\n replacement = `${this.getTimezoneOffsetLong()}`;\r\n break;\r\n\r\n default:\r\n return match;\r\n }\r\n // Wrap in brackets to protect from standard formatter\r\n return `[${replacement}]`;\r\n },\r\n );\r\n\r\n // Apply standard format to the result\r\n return originalFormat.call(this, result);\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Create and export default instance\r\n */\r\nexport default new AdvancedFormatPlugin();\r\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"duration.cjs","names":[],"sources":["../../src/plugins/duration/index.ts"],"sourcesContent":["/**\r\n * TimeGuard Duration Plugin\r\n * Implements ISO 8601 duration support and time calculations\r\n * Follows SOLID principles and enables advanced duration operations\r\n */\r\n\r\nimport type { ITimeGuardPlugin } from '../../types';\r\nimport type { TimeGuard } from '../../time-guard';\r\nimport type { DurationInput, DurationObject, DurationUnit, IDuration } from './types';\r\n\r\n/**\r\n * Duration class - represents time span following ISO 8601 standard\r\n */\r\nexport class Duration implements IDuration {\r\n private years: number = 0;\r\n private months: number = 0;\r\n private weeks: number = 0;\r\n private days: number = 0;\r\n private hours: number = 0;\r\n private minutes: number = 0;\r\n private seconds: number = 0;\r\n private milliseconds: number = 0;\r\n\r\n constructor(input: DurationInput) {\r\n this.years = input.years || 0;\r\n this.months = input.months || 0;\r\n this.weeks = input.weeks || 0;\r\n this.days = input.days || 0;\r\n this.hours = input.hours || 0;\r\n this.minutes = input.minutes || 0;\r\n this.seconds = input.seconds || 0;\r\n this.milliseconds = input.milliseconds || 0;\r\n }\r\n\r\n /**\r\n * Create Duration from ISO 8601 string\r\n * @example Duration.fromISO(\"P3Y6M4DT12H30M5S\")\r\n */\r\n static fromISO(iso: string): Duration {\r\n const isoRegex = /^(-)?P(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)W)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:([\\d.]+)S)?)?$/;\r\n const match = iso.match(isoRegex);\r\n\r\n if (!match) {\r\n throw new Error(`Invalid ISO 8601 duration: ${iso}`);\r\n }\r\n\r\n const [, negative, years, months, , days, hours, minutes, seconds] = match;\r\n const multiplier = negative ? -1 : 1;\r\n\r\n return new Duration({\r\n years: parseInt(years || '0', 10) * multiplier,\r\n months: parseInt(months || '0', 10) * multiplier,\r\n days: parseInt(days || '0', 10) * multiplier,\r\n hours: parseInt(hours || '0', 10) * multiplier,\r\n minutes: parseInt(minutes || '0', 10) * multiplier,\r\n seconds: parseFloat(seconds || '0') * multiplier,\r\n });\r\n }\r\n\r\n /**\r\n * Create a Duration between this date and another\r\n */\r\n static between(from: TimeGuard, to: TimeGuard): Duration {\r\n // Calculate (to - from) using since() for proper duration\r\n const fromDT = (from as any).toTemporal();\r\n const toDT = (to as any).toTemporal();\r\n const duration = (toDT as any).since(fromDT);\r\n \r\n return new Duration({\r\n years: duration.years || 0,\r\n months: duration.months || 0,\r\n weeks: 0,\r\n days: duration.days || 0,\r\n hours: duration.hours || 0,\r\n minutes: duration.minutes || 0,\r\n seconds: duration.seconds || 0,\r\n milliseconds: duration.milliseconds || 0,\r\n });\r\n }\r\n\r\n /**\r\n * Create Duration from milliseconds\r\n */\r\n static fromMilliseconds(ms: number): Duration {\r\n const isNegative = ms < 0;\r\n const absMilhs = Math.abs(ms);\r\n\r\n const years = Math.floor(absMilhs / (1000 * 60 * 60 * 24 * 365));\r\n const months = Math.floor((absMilhs % (1000 * 60 * 60 * 24 * 365)) / (1000 * 60 * 60 * 24 * 30));\r\n const days = Math.floor((absMilhs % (1000 * 60 * 60 * 24 * 30)) / (1000 * 60 * 60 * 24));\r\n const hours = Math.floor((absMilhs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));\r\n const minutes = Math.floor((absMilhs % (1000 * 60 * 60)) / (1000 * 60));\r\n const seconds = Math.floor((absMilhs % (1000 * 60)) / 1000);\r\n const milliseconds = Math.floor(absMilhs % 1000);\r\n\r\n const multiplier = isNegative ? -1 : 1;\r\n\r\n return new Duration({\r\n years: years * multiplier,\r\n months: months * multiplier,\r\n days: days * multiplier,\r\n hours: hours * multiplier,\r\n minutes: minutes * multiplier,\r\n seconds: seconds * multiplier,\r\n milliseconds: milliseconds * multiplier,\r\n });\r\n }\r\n\r\n /**\r\n * Get duration in specific unit\r\n */\r\n as(unit: DurationUnit): number {\r\n const ms = this.asMilliseconds();\r\n\r\n const conversions: Record<DurationUnit, number> = {\r\n milliseconds: 1,\r\n seconds: 1000,\r\n minutes: 1000 * 60,\r\n hours: 1000 * 60 * 60,\r\n days: 1000 * 60 * 60 * 24,\r\n weeks: 1000 * 60 * 60 * 24 * 7,\r\n months: 1000 * 60 * 60 * 24 * 30,\r\n years: 1000 * 60 * 60 * 24 * 365,\r\n };\r\n\r\n return ms / conversions[unit];\r\n }\r\n\r\n /**\r\n * Get duration as milliseconds\r\n */\r\n asMilliseconds(): number {\r\n return (\r\n this.years * 1000 * 60 * 60 * 24 * 365 +\r\n this.months * 1000 * 60 * 60 * 24 * 30 +\r\n this.weeks * 1000 * 60 * 60 * 24 * 7 +\r\n this.days * 1000 * 60 * 60 * 24 +\r\n this.hours * 1000 * 60 * 60 +\r\n this.minutes * 1000 * 60 +\r\n this.seconds * 1000 +\r\n this.milliseconds\r\n );\r\n }\r\n\r\n /**\r\n * Get duration as seconds\r\n */\r\n asSeconds(): number {\r\n return this.asMilliseconds() / 1000;\r\n }\r\n\r\n /**\r\n * Get duration as minutes\r\n */\r\n asMinutes(): number {\r\n return this.asSeconds() / 60;\r\n }\r\n\r\n /**\r\n * Get duration as hours\r\n */\r\n asHours(): number {\r\n return this.asMinutes() / 60;\r\n }\r\n\r\n /**\r\n * Get duration as days\r\n */\r\n asDays(): number {\r\n return this.asHours() / 24;\r\n }\r\n\r\n /**\r\n * Get duration as weeks\r\n */\r\n asWeeks(): number {\r\n return this.asDays() / 7;\r\n }\r\n\r\n /**\r\n * Get duration as months\r\n */\r\n asMonths(): number {\r\n return this.asDays() / 30;\r\n }\r\n\r\n /**\r\n * Get duration as years\r\n */\r\n asYears(): number {\r\n return this.asDays() / 365;\r\n }\r\n\r\n /**\r\n * Get all components\r\n */\r\n toObject(): DurationObject {\r\n return {\r\n years: this.years,\r\n months: this.months,\r\n weeks: this.weeks,\r\n days: this.days,\r\n hours: this.hours,\r\n minutes: this.minutes,\r\n seconds: this.seconds,\r\n milliseconds: this.milliseconds,\r\n };\r\n }\r\n\r\n /**\r\n * Get ISO 8601 string representation\r\n * @example \"P3Y6M4DT12H30M5S\"\r\n */\r\n toISO(): string {\r\n\r\n // Date part\r\n let datePart = '';\r\n if (this.years) datePart += `${this.years}Y`;\r\n if (this.months) datePart += `${this.months}M`;\r\n if (this.weeks || this.days) datePart += `${this.weeks * 7 + this.days}D`;\r\n\r\n // Time part\r\n let timePart = '';\r\n if (this.hours) timePart += `${this.hours}H`;\r\n if (this.minutes) timePart += `${this.minutes}M`;\r\n if (this.seconds || this.milliseconds) {\r\n timePart += `${this.seconds + this.milliseconds / 1000}S`;\r\n }\r\n\r\n const sign = this.isNegative() ? '-' : '';\r\n return `${sign}P${datePart}${timePart ? `T${timePart}` : ''}`;\r\n }\r\n\r\n /**\r\n * Get human-readable string\r\n */\r\n humanize(): string {\r\n const parts: string[] = [];\r\n\r\n if (this.years) parts.push(`${Math.abs(this.years)} year${Math.abs(this.years) !== 1 ? 's' : ''}`);\r\n if (this.months) parts.push(`${Math.abs(this.months)} month${Math.abs(this.months) !== 1 ? 's' : ''}`);\r\n if (this.weeks) parts.push(`${Math.abs(this.weeks)} week${Math.abs(this.weeks) !== 1 ? 's' : ''}`);\r\n if (this.days) parts.push(`${Math.abs(this.days)} day${Math.abs(this.days) !== 1 ? 's' : ''}`);\r\n if (this.hours) parts.push(`${Math.abs(this.hours)} hour${Math.abs(this.hours) !== 1 ? 's' : ''}`);\r\n if (this.minutes) parts.push(`${Math.abs(this.minutes)} minute${Math.abs(this.minutes) !== 1 ? 's' : ''}`);\r\n if (this.seconds) parts.push(`${Math.abs(this.seconds)} second${Math.abs(this.seconds) !== 1 ? 's' : ''}`);\r\n if (this.milliseconds) parts.push(`${Math.abs(this.milliseconds)} ms`);\r\n\r\n if (parts.length === 0) return '0 seconds';\r\n\r\n const text = parts.join(', ');\r\n return this.isNegative() ? `-${text}` : text;\r\n }\r\n\r\n /**\r\n * Check if duration is negative\r\n */\r\n isNegative(): boolean {\r\n return (\r\n this.years < 0 ||\r\n this.months < 0 ||\r\n this.weeks < 0 ||\r\n this.days < 0 ||\r\n this.hours < 0 ||\r\n this.minutes < 0 ||\r\n this.seconds < 0 ||\r\n this.milliseconds < 0\r\n );\r\n }\r\n\r\n /**\r\n * Get absolute duration\r\n */\r\n abs(): Duration {\r\n return new Duration({\r\n years: Math.abs(this.years),\r\n months: Math.abs(this.months),\r\n weeks: Math.abs(this.weeks),\r\n days: Math.abs(this.days),\r\n hours: Math.abs(this.hours),\r\n minutes: Math.abs(this.minutes),\r\n seconds: Math.abs(this.seconds),\r\n milliseconds: Math.abs(this.milliseconds),\r\n });\r\n }\r\n\r\n /**\r\n * String representation\r\n */\r\n toString(): string {\r\n return this.toISO();\r\n }\r\n}\r\n\r\n/**\r\n * Duration Plugin\r\n */\r\nexport class DurationPlugin implements ITimeGuardPlugin {\r\n name = 'duration';\r\n version = '1.0.0';\r\n\r\n /**\r\n * Install plugin into TimeGuard\r\n */\r\n install(TimeGuardClass: typeof TimeGuard): void {\r\n /**\r\n * Create a Duration between this date and another\r\n */\r\n (TimeGuardClass.prototype as any).duration = function (other: TimeGuard): Duration {\r\n return Duration.between(this, other);\r\n };\r\n\r\n /**\r\n * Get Duration class for creating custom durations\r\n */\r\n (TimeGuardClass as any).Duration = Duration;\r\n\r\n /**\r\n * Create Duration from ISO 8601 string\r\n */\r\n (TimeGuardClass as any).duration = {\r\n fromISO: (iso: string): Duration => Duration.fromISO(iso),\r\n between: (from: TimeGuard, to: TimeGuard): Duration => Duration.between(from, to),\r\n fromMilliseconds: (ms: number): Duration => Duration.fromMilliseconds(ms),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Create and export default instance\r\n */\r\nexport const durationPlugin = new DurationPlugin();\r\n\r\nexport default durationPlugin;\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"duration.cjs","names":[],"sources":["../../src/plugins/duration/index.ts"],"sourcesContent":["/**\r\n * TimeGuard Duration Plugin\r\n * Implements ISO 8601 duration support and time calculations\r\n * Follows SOLID principles and enables advanced duration operations\r\n */\r\n\r\nimport type { ITimeGuardPlugin } from '../../types';\r\nimport type { TimeGuard } from '../../index';\r\nimport type { DurationInput, DurationObject, DurationUnit, IDuration } from './types';\r\n\r\n/**\r\n * Duration class - represents time span following ISO 8601 standard\r\n */\r\nexport class Duration implements IDuration {\r\n private years: number = 0;\r\n private months: number = 0;\r\n private weeks: number = 0;\r\n private days: number = 0;\r\n private hours: number = 0;\r\n private minutes: number = 0;\r\n private seconds: number = 0;\r\n private milliseconds: number = 0;\r\n\r\n constructor(input: DurationInput) {\r\n this.years = input.years || 0;\r\n this.months = input.months || 0;\r\n this.weeks = input.weeks || 0;\r\n this.days = input.days || 0;\r\n this.hours = input.hours || 0;\r\n this.minutes = input.minutes || 0;\r\n this.seconds = input.seconds || 0;\r\n this.milliseconds = input.milliseconds || 0;\r\n }\r\n\r\n /**\r\n * Create Duration from ISO 8601 string\r\n * @example Duration.fromISO(\"P3Y6M4DT12H30M5S\")\r\n */\r\n static fromISO(iso: string): Duration {\r\n const isoRegex = /^(-)?P(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)W)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:([\\d.]+)S)?)?$/;\r\n const match = iso.match(isoRegex);\r\n\r\n if (!match) {\r\n throw new Error(`Invalid ISO 8601 duration: ${iso}`);\r\n }\r\n\r\n const [, negative, years, months, , days, hours, minutes, seconds] = match;\r\n const multiplier = negative ? -1 : 1;\r\n\r\n return new Duration({\r\n years: parseInt(years || '0', 10) * multiplier,\r\n months: parseInt(months || '0', 10) * multiplier,\r\n days: parseInt(days || '0', 10) * multiplier,\r\n hours: parseInt(hours || '0', 10) * multiplier,\r\n minutes: parseInt(minutes || '0', 10) * multiplier,\r\n seconds: parseFloat(seconds || '0') * multiplier,\r\n });\r\n }\r\n\r\n /**\r\n * Create a Duration between this date and another\r\n */\r\n static between(from: TimeGuard, to: TimeGuard): Duration {\r\n // Calculate (to - from) using since() for proper duration\r\n const fromDT = (from as any).toTemporal();\r\n const toDT = (to as any).toTemporal();\r\n const duration = (toDT as any).since(fromDT);\r\n \r\n return new Duration({\r\n years: duration.years || 0,\r\n months: duration.months || 0,\r\n weeks: 0,\r\n days: duration.days || 0,\r\n hours: duration.hours || 0,\r\n minutes: duration.minutes || 0,\r\n seconds: duration.seconds || 0,\r\n milliseconds: duration.milliseconds || 0,\r\n });\r\n }\r\n\r\n /**\r\n * Create Duration from milliseconds\r\n */\r\n static fromMilliseconds(ms: number): Duration {\r\n const isNegative = ms < 0;\r\n const absMilhs = Math.abs(ms);\r\n\r\n const years = Math.floor(absMilhs / (1000 * 60 * 60 * 24 * 365));\r\n const months = Math.floor((absMilhs % (1000 * 60 * 60 * 24 * 365)) / (1000 * 60 * 60 * 24 * 30));\r\n const days = Math.floor((absMilhs % (1000 * 60 * 60 * 24 * 30)) / (1000 * 60 * 60 * 24));\r\n const hours = Math.floor((absMilhs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));\r\n const minutes = Math.floor((absMilhs % (1000 * 60 * 60)) / (1000 * 60));\r\n const seconds = Math.floor((absMilhs % (1000 * 60)) / 1000);\r\n const milliseconds = Math.floor(absMilhs % 1000);\r\n\r\n const multiplier = isNegative ? -1 : 1;\r\n\r\n return new Duration({\r\n years: years * multiplier,\r\n months: months * multiplier,\r\n days: days * multiplier,\r\n hours: hours * multiplier,\r\n minutes: minutes * multiplier,\r\n seconds: seconds * multiplier,\r\n milliseconds: milliseconds * multiplier,\r\n });\r\n }\r\n\r\n /**\r\n * Get duration in specific unit\r\n */\r\n as(unit: DurationUnit): number {\r\n const ms = this.asMilliseconds();\r\n\r\n const conversions: Record<DurationUnit, number> = {\r\n milliseconds: 1,\r\n seconds: 1000,\r\n minutes: 1000 * 60,\r\n hours: 1000 * 60 * 60,\r\n days: 1000 * 60 * 60 * 24,\r\n weeks: 1000 * 60 * 60 * 24 * 7,\r\n months: 1000 * 60 * 60 * 24 * 30,\r\n years: 1000 * 60 * 60 * 24 * 365,\r\n };\r\n\r\n return ms / conversions[unit];\r\n }\r\n\r\n /**\r\n * Get duration as milliseconds\r\n */\r\n asMilliseconds(): number {\r\n return (\r\n this.years * 1000 * 60 * 60 * 24 * 365 +\r\n this.months * 1000 * 60 * 60 * 24 * 30 +\r\n this.weeks * 1000 * 60 * 60 * 24 * 7 +\r\n this.days * 1000 * 60 * 60 * 24 +\r\n this.hours * 1000 * 60 * 60 +\r\n this.minutes * 1000 * 60 +\r\n this.seconds * 1000 +\r\n this.milliseconds\r\n );\r\n }\r\n\r\n /**\r\n * Get duration as seconds\r\n */\r\n asSeconds(): number {\r\n return this.asMilliseconds() / 1000;\r\n }\r\n\r\n /**\r\n * Get duration as minutes\r\n */\r\n asMinutes(): number {\r\n return this.asSeconds() / 60;\r\n }\r\n\r\n /**\r\n * Get duration as hours\r\n */\r\n asHours(): number {\r\n return this.asMinutes() / 60;\r\n }\r\n\r\n /**\r\n * Get duration as days\r\n */\r\n asDays(): number {\r\n return this.asHours() / 24;\r\n }\r\n\r\n /**\r\n * Get duration as weeks\r\n */\r\n asWeeks(): number {\r\n return this.asDays() / 7;\r\n }\r\n\r\n /**\r\n * Get duration as months\r\n */\r\n asMonths(): number {\r\n return this.asDays() / 30;\r\n }\r\n\r\n /**\r\n * Get duration as years\r\n */\r\n asYears(): number {\r\n return this.asDays() / 365;\r\n }\r\n\r\n /**\r\n * Get all components\r\n */\r\n toObject(): DurationObject {\r\n return {\r\n years: this.years,\r\n months: this.months,\r\n weeks: this.weeks,\r\n days: this.days,\r\n hours: this.hours,\r\n minutes: this.minutes,\r\n seconds: this.seconds,\r\n milliseconds: this.milliseconds,\r\n };\r\n }\r\n\r\n /**\r\n * Get ISO 8601 string representation\r\n * @example \"P3Y6M4DT12H30M5S\"\r\n */\r\n toISO(): string {\r\n\r\n // Date part\r\n let datePart = '';\r\n if (this.years) datePart += `${this.years}Y`;\r\n if (this.months) datePart += `${this.months}M`;\r\n if (this.weeks || this.days) datePart += `${this.weeks * 7 + this.days}D`;\r\n\r\n // Time part\r\n let timePart = '';\r\n if (this.hours) timePart += `${this.hours}H`;\r\n if (this.minutes) timePart += `${this.minutes}M`;\r\n if (this.seconds || this.milliseconds) {\r\n timePart += `${this.seconds + this.milliseconds / 1000}S`;\r\n }\r\n\r\n const sign = this.isNegative() ? '-' : '';\r\n return `${sign}P${datePart}${timePart ? `T${timePart}` : ''}`;\r\n }\r\n\r\n /**\r\n * Get human-readable string\r\n */\r\n humanize(): string {\r\n const parts: string[] = [];\r\n\r\n if (this.years) parts.push(`${Math.abs(this.years)} year${Math.abs(this.years) !== 1 ? 's' : ''}`);\r\n if (this.months) parts.push(`${Math.abs(this.months)} month${Math.abs(this.months) !== 1 ? 's' : ''}`);\r\n if (this.weeks) parts.push(`${Math.abs(this.weeks)} week${Math.abs(this.weeks) !== 1 ? 's' : ''}`);\r\n if (this.days) parts.push(`${Math.abs(this.days)} day${Math.abs(this.days) !== 1 ? 's' : ''}`);\r\n if (this.hours) parts.push(`${Math.abs(this.hours)} hour${Math.abs(this.hours) !== 1 ? 's' : ''}`);\r\n if (this.minutes) parts.push(`${Math.abs(this.minutes)} minute${Math.abs(this.minutes) !== 1 ? 's' : ''}`);\r\n if (this.seconds) parts.push(`${Math.abs(this.seconds)} second${Math.abs(this.seconds) !== 1 ? 's' : ''}`);\r\n if (this.milliseconds) parts.push(`${Math.abs(this.milliseconds)} ms`);\r\n\r\n if (parts.length === 0) return '0 seconds';\r\n\r\n const text = parts.join(', ');\r\n return this.isNegative() ? `-${text}` : text;\r\n }\r\n\r\n /**\r\n * Check if duration is negative\r\n */\r\n isNegative(): boolean {\r\n return (\r\n this.years < 0 ||\r\n this.months < 0 ||\r\n this.weeks < 0 ||\r\n this.days < 0 ||\r\n this.hours < 0 ||\r\n this.minutes < 0 ||\r\n this.seconds < 0 ||\r\n this.milliseconds < 0\r\n );\r\n }\r\n\r\n /**\r\n * Get absolute duration\r\n */\r\n abs(): Duration {\r\n return new Duration({\r\n years: Math.abs(this.years),\r\n months: Math.abs(this.months),\r\n weeks: Math.abs(this.weeks),\r\n days: Math.abs(this.days),\r\n hours: Math.abs(this.hours),\r\n minutes: Math.abs(this.minutes),\r\n seconds: Math.abs(this.seconds),\r\n milliseconds: Math.abs(this.milliseconds),\r\n });\r\n }\r\n\r\n /**\r\n * String representation\r\n */\r\n toString(): string {\r\n return this.toISO();\r\n }\r\n}\r\n\r\n/**\r\n * Duration Plugin\r\n */\r\nexport class DurationPlugin implements ITimeGuardPlugin {\r\n name = 'duration';\r\n version = '1.0.0';\r\n\r\n /**\r\n * Install plugin into TimeGuard\r\n */\r\n install(TimeGuardClass: typeof TimeGuard): void {\r\n /**\r\n * Create a Duration between this date and another\r\n */\r\n (TimeGuardClass.prototype as any).duration = function (other: TimeGuard): Duration {\r\n return Duration.between(this, other);\r\n };\r\n\r\n /**\r\n * Get Duration class for creating custom durations\r\n */\r\n (TimeGuardClass as any).Duration = Duration;\r\n\r\n /**\r\n * Create Duration from ISO 8601 string\r\n */\r\n (TimeGuardClass as any).duration = {\r\n fromISO: (iso: string): Duration => Duration.fromISO(iso),\r\n between: (from: TimeGuard, to: TimeGuard): Duration => Duration.between(from, to),\r\n fromMilliseconds: (ms: number): Duration => Duration.fromMilliseconds(ms),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Create and export default instance\r\n */\r\nexport const durationPlugin = new DurationPlugin();\r\n\r\nexport default durationPlugin;\r\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! time-guard v2.5.
|
|
1
|
+
/*! time-guard v2.5.3 | (c) 2026 Berea-Soft | MIT License | https://github.com/Berea-Soft/time-guard */
|
|
2
2
|
//#region src/plugins/duration/index.ts
|
|
3
3
|
var e = class e {
|
|
4
4
|
years = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"duration.es.js","names":[],"sources":["../../src/plugins/duration/index.ts"],"sourcesContent":["/**\r\n * TimeGuard Duration Plugin\r\n * Implements ISO 8601 duration support and time calculations\r\n * Follows SOLID principles and enables advanced duration operations\r\n */\r\n\r\nimport type { ITimeGuardPlugin } from '../../types';\r\nimport type { TimeGuard } from '../../time-guard';\r\nimport type { DurationInput, DurationObject, DurationUnit, IDuration } from './types';\r\n\r\n/**\r\n * Duration class - represents time span following ISO 8601 standard\r\n */\r\nexport class Duration implements IDuration {\r\n private years: number = 0;\r\n private months: number = 0;\r\n private weeks: number = 0;\r\n private days: number = 0;\r\n private hours: number = 0;\r\n private minutes: number = 0;\r\n private seconds: number = 0;\r\n private milliseconds: number = 0;\r\n\r\n constructor(input: DurationInput) {\r\n this.years = input.years || 0;\r\n this.months = input.months || 0;\r\n this.weeks = input.weeks || 0;\r\n this.days = input.days || 0;\r\n this.hours = input.hours || 0;\r\n this.minutes = input.minutes || 0;\r\n this.seconds = input.seconds || 0;\r\n this.milliseconds = input.milliseconds || 0;\r\n }\r\n\r\n /**\r\n * Create Duration from ISO 8601 string\r\n * @example Duration.fromISO(\"P3Y6M4DT12H30M5S\")\r\n */\r\n static fromISO(iso: string): Duration {\r\n const isoRegex = /^(-)?P(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)W)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:([\\d.]+)S)?)?$/;\r\n const match = iso.match(isoRegex);\r\n\r\n if (!match) {\r\n throw new Error(`Invalid ISO 8601 duration: ${iso}`);\r\n }\r\n\r\n const [, negative, years, months, , days, hours, minutes, seconds] = match;\r\n const multiplier = negative ? -1 : 1;\r\n\r\n return new Duration({\r\n years: parseInt(years || '0', 10) * multiplier,\r\n months: parseInt(months || '0', 10) * multiplier,\r\n days: parseInt(days || '0', 10) * multiplier,\r\n hours: parseInt(hours || '0', 10) * multiplier,\r\n minutes: parseInt(minutes || '0', 10) * multiplier,\r\n seconds: parseFloat(seconds || '0') * multiplier,\r\n });\r\n }\r\n\r\n /**\r\n * Create a Duration between this date and another\r\n */\r\n static between(from: TimeGuard, to: TimeGuard): Duration {\r\n // Calculate (to - from) using since() for proper duration\r\n const fromDT = (from as any).toTemporal();\r\n const toDT = (to as any).toTemporal();\r\n const duration = (toDT as any).since(fromDT);\r\n \r\n return new Duration({\r\n years: duration.years || 0,\r\n months: duration.months || 0,\r\n weeks: 0,\r\n days: duration.days || 0,\r\n hours: duration.hours || 0,\r\n minutes: duration.minutes || 0,\r\n seconds: duration.seconds || 0,\r\n milliseconds: duration.milliseconds || 0,\r\n });\r\n }\r\n\r\n /**\r\n * Create Duration from milliseconds\r\n */\r\n static fromMilliseconds(ms: number): Duration {\r\n const isNegative = ms < 0;\r\n const absMilhs = Math.abs(ms);\r\n\r\n const years = Math.floor(absMilhs / (1000 * 60 * 60 * 24 * 365));\r\n const months = Math.floor((absMilhs % (1000 * 60 * 60 * 24 * 365)) / (1000 * 60 * 60 * 24 * 30));\r\n const days = Math.floor((absMilhs % (1000 * 60 * 60 * 24 * 30)) / (1000 * 60 * 60 * 24));\r\n const hours = Math.floor((absMilhs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));\r\n const minutes = Math.floor((absMilhs % (1000 * 60 * 60)) / (1000 * 60));\r\n const seconds = Math.floor((absMilhs % (1000 * 60)) / 1000);\r\n const milliseconds = Math.floor(absMilhs % 1000);\r\n\r\n const multiplier = isNegative ? -1 : 1;\r\n\r\n return new Duration({\r\n years: years * multiplier,\r\n months: months * multiplier,\r\n days: days * multiplier,\r\n hours: hours * multiplier,\r\n minutes: minutes * multiplier,\r\n seconds: seconds * multiplier,\r\n milliseconds: milliseconds * multiplier,\r\n });\r\n }\r\n\r\n /**\r\n * Get duration in specific unit\r\n */\r\n as(unit: DurationUnit): number {\r\n const ms = this.asMilliseconds();\r\n\r\n const conversions: Record<DurationUnit, number> = {\r\n milliseconds: 1,\r\n seconds: 1000,\r\n minutes: 1000 * 60,\r\n hours: 1000 * 60 * 60,\r\n days: 1000 * 60 * 60 * 24,\r\n weeks: 1000 * 60 * 60 * 24 * 7,\r\n months: 1000 * 60 * 60 * 24 * 30,\r\n years: 1000 * 60 * 60 * 24 * 365,\r\n };\r\n\r\n return ms / conversions[unit];\r\n }\r\n\r\n /**\r\n * Get duration as milliseconds\r\n */\r\n asMilliseconds(): number {\r\n return (\r\n this.years * 1000 * 60 * 60 * 24 * 365 +\r\n this.months * 1000 * 60 * 60 * 24 * 30 +\r\n this.weeks * 1000 * 60 * 60 * 24 * 7 +\r\n this.days * 1000 * 60 * 60 * 24 +\r\n this.hours * 1000 * 60 * 60 +\r\n this.minutes * 1000 * 60 +\r\n this.seconds * 1000 +\r\n this.milliseconds\r\n );\r\n }\r\n\r\n /**\r\n * Get duration as seconds\r\n */\r\n asSeconds(): number {\r\n return this.asMilliseconds() / 1000;\r\n }\r\n\r\n /**\r\n * Get duration as minutes\r\n */\r\n asMinutes(): number {\r\n return this.asSeconds() / 60;\r\n }\r\n\r\n /**\r\n * Get duration as hours\r\n */\r\n asHours(): number {\r\n return this.asMinutes() / 60;\r\n }\r\n\r\n /**\r\n * Get duration as days\r\n */\r\n asDays(): number {\r\n return this.asHours() / 24;\r\n }\r\n\r\n /**\r\n * Get duration as weeks\r\n */\r\n asWeeks(): number {\r\n return this.asDays() / 7;\r\n }\r\n\r\n /**\r\n * Get duration as months\r\n */\r\n asMonths(): number {\r\n return this.asDays() / 30;\r\n }\r\n\r\n /**\r\n * Get duration as years\r\n */\r\n asYears(): number {\r\n return this.asDays() / 365;\r\n }\r\n\r\n /**\r\n * Get all components\r\n */\r\n toObject(): DurationObject {\r\n return {\r\n years: this.years,\r\n months: this.months,\r\n weeks: this.weeks,\r\n days: this.days,\r\n hours: this.hours,\r\n minutes: this.minutes,\r\n seconds: this.seconds,\r\n milliseconds: this.milliseconds,\r\n };\r\n }\r\n\r\n /**\r\n * Get ISO 8601 string representation\r\n * @example \"P3Y6M4DT12H30M5S\"\r\n */\r\n toISO(): string {\r\n\r\n // Date part\r\n let datePart = '';\r\n if (this.years) datePart += `${this.years}Y`;\r\n if (this.months) datePart += `${this.months}M`;\r\n if (this.weeks || this.days) datePart += `${this.weeks * 7 + this.days}D`;\r\n\r\n // Time part\r\n let timePart = '';\r\n if (this.hours) timePart += `${this.hours}H`;\r\n if (this.minutes) timePart += `${this.minutes}M`;\r\n if (this.seconds || this.milliseconds) {\r\n timePart += `${this.seconds + this.milliseconds / 1000}S`;\r\n }\r\n\r\n const sign = this.isNegative() ? '-' : '';\r\n return `${sign}P${datePart}${timePart ? `T${timePart}` : ''}`;\r\n }\r\n\r\n /**\r\n * Get human-readable string\r\n */\r\n humanize(): string {\r\n const parts: string[] = [];\r\n\r\n if (this.years) parts.push(`${Math.abs(this.years)} year${Math.abs(this.years) !== 1 ? 's' : ''}`);\r\n if (this.months) parts.push(`${Math.abs(this.months)} month${Math.abs(this.months) !== 1 ? 's' : ''}`);\r\n if (this.weeks) parts.push(`${Math.abs(this.weeks)} week${Math.abs(this.weeks) !== 1 ? 's' : ''}`);\r\n if (this.days) parts.push(`${Math.abs(this.days)} day${Math.abs(this.days) !== 1 ? 's' : ''}`);\r\n if (this.hours) parts.push(`${Math.abs(this.hours)} hour${Math.abs(this.hours) !== 1 ? 's' : ''}`);\r\n if (this.minutes) parts.push(`${Math.abs(this.minutes)} minute${Math.abs(this.minutes) !== 1 ? 's' : ''}`);\r\n if (this.seconds) parts.push(`${Math.abs(this.seconds)} second${Math.abs(this.seconds) !== 1 ? 's' : ''}`);\r\n if (this.milliseconds) parts.push(`${Math.abs(this.milliseconds)} ms`);\r\n\r\n if (parts.length === 0) return '0 seconds';\r\n\r\n const text = parts.join(', ');\r\n return this.isNegative() ? `-${text}` : text;\r\n }\r\n\r\n /**\r\n * Check if duration is negative\r\n */\r\n isNegative(): boolean {\r\n return (\r\n this.years < 0 ||\r\n this.months < 0 ||\r\n this.weeks < 0 ||\r\n this.days < 0 ||\r\n this.hours < 0 ||\r\n this.minutes < 0 ||\r\n this.seconds < 0 ||\r\n this.milliseconds < 0\r\n );\r\n }\r\n\r\n /**\r\n * Get absolute duration\r\n */\r\n abs(): Duration {\r\n return new Duration({\r\n years: Math.abs(this.years),\r\n months: Math.abs(this.months),\r\n weeks: Math.abs(this.weeks),\r\n days: Math.abs(this.days),\r\n hours: Math.abs(this.hours),\r\n minutes: Math.abs(this.minutes),\r\n seconds: Math.abs(this.seconds),\r\n milliseconds: Math.abs(this.milliseconds),\r\n });\r\n }\r\n\r\n /**\r\n * String representation\r\n */\r\n toString(): string {\r\n return this.toISO();\r\n }\r\n}\r\n\r\n/**\r\n * Duration Plugin\r\n */\r\nexport class DurationPlugin implements ITimeGuardPlugin {\r\n name = 'duration';\r\n version = '1.0.0';\r\n\r\n /**\r\n * Install plugin into TimeGuard\r\n */\r\n install(TimeGuardClass: typeof TimeGuard): void {\r\n /**\r\n * Create a Duration between this date and another\r\n */\r\n (TimeGuardClass.prototype as any).duration = function (other: TimeGuard): Duration {\r\n return Duration.between(this, other);\r\n };\r\n\r\n /**\r\n * Get Duration class for creating custom durations\r\n */\r\n (TimeGuardClass as any).Duration = Duration;\r\n\r\n /**\r\n * Create Duration from ISO 8601 string\r\n */\r\n (TimeGuardClass as any).duration = {\r\n fromISO: (iso: string): Duration => Duration.fromISO(iso),\r\n between: (from: TimeGuard, to: TimeGuard): Duration => Duration.between(from, to),\r\n fromMilliseconds: (ms: number): Duration => Duration.fromMilliseconds(ms),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Create and export default instance\r\n */\r\nexport const durationPlugin = new DurationPlugin();\r\n\r\nexport default durationPlugin;\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"duration.es.js","names":[],"sources":["../../src/plugins/duration/index.ts"],"sourcesContent":["/**\r\n * TimeGuard Duration Plugin\r\n * Implements ISO 8601 duration support and time calculations\r\n * Follows SOLID principles and enables advanced duration operations\r\n */\r\n\r\nimport type { ITimeGuardPlugin } from '../../types';\r\nimport type { TimeGuard } from '../../index';\r\nimport type { DurationInput, DurationObject, DurationUnit, IDuration } from './types';\r\n\r\n/**\r\n * Duration class - represents time span following ISO 8601 standard\r\n */\r\nexport class Duration implements IDuration {\r\n private years: number = 0;\r\n private months: number = 0;\r\n private weeks: number = 0;\r\n private days: number = 0;\r\n private hours: number = 0;\r\n private minutes: number = 0;\r\n private seconds: number = 0;\r\n private milliseconds: number = 0;\r\n\r\n constructor(input: DurationInput) {\r\n this.years = input.years || 0;\r\n this.months = input.months || 0;\r\n this.weeks = input.weeks || 0;\r\n this.days = input.days || 0;\r\n this.hours = input.hours || 0;\r\n this.minutes = input.minutes || 0;\r\n this.seconds = input.seconds || 0;\r\n this.milliseconds = input.milliseconds || 0;\r\n }\r\n\r\n /**\r\n * Create Duration from ISO 8601 string\r\n * @example Duration.fromISO(\"P3Y6M4DT12H30M5S\")\r\n */\r\n static fromISO(iso: string): Duration {\r\n const isoRegex = /^(-)?P(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)W)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:([\\d.]+)S)?)?$/;\r\n const match = iso.match(isoRegex);\r\n\r\n if (!match) {\r\n throw new Error(`Invalid ISO 8601 duration: ${iso}`);\r\n }\r\n\r\n const [, negative, years, months, , days, hours, minutes, seconds] = match;\r\n const multiplier = negative ? -1 : 1;\r\n\r\n return new Duration({\r\n years: parseInt(years || '0', 10) * multiplier,\r\n months: parseInt(months || '0', 10) * multiplier,\r\n days: parseInt(days || '0', 10) * multiplier,\r\n hours: parseInt(hours || '0', 10) * multiplier,\r\n minutes: parseInt(minutes || '0', 10) * multiplier,\r\n seconds: parseFloat(seconds || '0') * multiplier,\r\n });\r\n }\r\n\r\n /**\r\n * Create a Duration between this date and another\r\n */\r\n static between(from: TimeGuard, to: TimeGuard): Duration {\r\n // Calculate (to - from) using since() for proper duration\r\n const fromDT = (from as any).toTemporal();\r\n const toDT = (to as any).toTemporal();\r\n const duration = (toDT as any).since(fromDT);\r\n \r\n return new Duration({\r\n years: duration.years || 0,\r\n months: duration.months || 0,\r\n weeks: 0,\r\n days: duration.days || 0,\r\n hours: duration.hours || 0,\r\n minutes: duration.minutes || 0,\r\n seconds: duration.seconds || 0,\r\n milliseconds: duration.milliseconds || 0,\r\n });\r\n }\r\n\r\n /**\r\n * Create Duration from milliseconds\r\n */\r\n static fromMilliseconds(ms: number): Duration {\r\n const isNegative = ms < 0;\r\n const absMilhs = Math.abs(ms);\r\n\r\n const years = Math.floor(absMilhs / (1000 * 60 * 60 * 24 * 365));\r\n const months = Math.floor((absMilhs % (1000 * 60 * 60 * 24 * 365)) / (1000 * 60 * 60 * 24 * 30));\r\n const days = Math.floor((absMilhs % (1000 * 60 * 60 * 24 * 30)) / (1000 * 60 * 60 * 24));\r\n const hours = Math.floor((absMilhs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));\r\n const minutes = Math.floor((absMilhs % (1000 * 60 * 60)) / (1000 * 60));\r\n const seconds = Math.floor((absMilhs % (1000 * 60)) / 1000);\r\n const milliseconds = Math.floor(absMilhs % 1000);\r\n\r\n const multiplier = isNegative ? -1 : 1;\r\n\r\n return new Duration({\r\n years: years * multiplier,\r\n months: months * multiplier,\r\n days: days * multiplier,\r\n hours: hours * multiplier,\r\n minutes: minutes * multiplier,\r\n seconds: seconds * multiplier,\r\n milliseconds: milliseconds * multiplier,\r\n });\r\n }\r\n\r\n /**\r\n * Get duration in specific unit\r\n */\r\n as(unit: DurationUnit): number {\r\n const ms = this.asMilliseconds();\r\n\r\n const conversions: Record<DurationUnit, number> = {\r\n milliseconds: 1,\r\n seconds: 1000,\r\n minutes: 1000 * 60,\r\n hours: 1000 * 60 * 60,\r\n days: 1000 * 60 * 60 * 24,\r\n weeks: 1000 * 60 * 60 * 24 * 7,\r\n months: 1000 * 60 * 60 * 24 * 30,\r\n years: 1000 * 60 * 60 * 24 * 365,\r\n };\r\n\r\n return ms / conversions[unit];\r\n }\r\n\r\n /**\r\n * Get duration as milliseconds\r\n */\r\n asMilliseconds(): number {\r\n return (\r\n this.years * 1000 * 60 * 60 * 24 * 365 +\r\n this.months * 1000 * 60 * 60 * 24 * 30 +\r\n this.weeks * 1000 * 60 * 60 * 24 * 7 +\r\n this.days * 1000 * 60 * 60 * 24 +\r\n this.hours * 1000 * 60 * 60 +\r\n this.minutes * 1000 * 60 +\r\n this.seconds * 1000 +\r\n this.milliseconds\r\n );\r\n }\r\n\r\n /**\r\n * Get duration as seconds\r\n */\r\n asSeconds(): number {\r\n return this.asMilliseconds() / 1000;\r\n }\r\n\r\n /**\r\n * Get duration as minutes\r\n */\r\n asMinutes(): number {\r\n return this.asSeconds() / 60;\r\n }\r\n\r\n /**\r\n * Get duration as hours\r\n */\r\n asHours(): number {\r\n return this.asMinutes() / 60;\r\n }\r\n\r\n /**\r\n * Get duration as days\r\n */\r\n asDays(): number {\r\n return this.asHours() / 24;\r\n }\r\n\r\n /**\r\n * Get duration as weeks\r\n */\r\n asWeeks(): number {\r\n return this.asDays() / 7;\r\n }\r\n\r\n /**\r\n * Get duration as months\r\n */\r\n asMonths(): number {\r\n return this.asDays() / 30;\r\n }\r\n\r\n /**\r\n * Get duration as years\r\n */\r\n asYears(): number {\r\n return this.asDays() / 365;\r\n }\r\n\r\n /**\r\n * Get all components\r\n */\r\n toObject(): DurationObject {\r\n return {\r\n years: this.years,\r\n months: this.months,\r\n weeks: this.weeks,\r\n days: this.days,\r\n hours: this.hours,\r\n minutes: this.minutes,\r\n seconds: this.seconds,\r\n milliseconds: this.milliseconds,\r\n };\r\n }\r\n\r\n /**\r\n * Get ISO 8601 string representation\r\n * @example \"P3Y6M4DT12H30M5S\"\r\n */\r\n toISO(): string {\r\n\r\n // Date part\r\n let datePart = '';\r\n if (this.years) datePart += `${this.years}Y`;\r\n if (this.months) datePart += `${this.months}M`;\r\n if (this.weeks || this.days) datePart += `${this.weeks * 7 + this.days}D`;\r\n\r\n // Time part\r\n let timePart = '';\r\n if (this.hours) timePart += `${this.hours}H`;\r\n if (this.minutes) timePart += `${this.minutes}M`;\r\n if (this.seconds || this.milliseconds) {\r\n timePart += `${this.seconds + this.milliseconds / 1000}S`;\r\n }\r\n\r\n const sign = this.isNegative() ? '-' : '';\r\n return `${sign}P${datePart}${timePart ? `T${timePart}` : ''}`;\r\n }\r\n\r\n /**\r\n * Get human-readable string\r\n */\r\n humanize(): string {\r\n const parts: string[] = [];\r\n\r\n if (this.years) parts.push(`${Math.abs(this.years)} year${Math.abs(this.years) !== 1 ? 's' : ''}`);\r\n if (this.months) parts.push(`${Math.abs(this.months)} month${Math.abs(this.months) !== 1 ? 's' : ''}`);\r\n if (this.weeks) parts.push(`${Math.abs(this.weeks)} week${Math.abs(this.weeks) !== 1 ? 's' : ''}`);\r\n if (this.days) parts.push(`${Math.abs(this.days)} day${Math.abs(this.days) !== 1 ? 's' : ''}`);\r\n if (this.hours) parts.push(`${Math.abs(this.hours)} hour${Math.abs(this.hours) !== 1 ? 's' : ''}`);\r\n if (this.minutes) parts.push(`${Math.abs(this.minutes)} minute${Math.abs(this.minutes) !== 1 ? 's' : ''}`);\r\n if (this.seconds) parts.push(`${Math.abs(this.seconds)} second${Math.abs(this.seconds) !== 1 ? 's' : ''}`);\r\n if (this.milliseconds) parts.push(`${Math.abs(this.milliseconds)} ms`);\r\n\r\n if (parts.length === 0) return '0 seconds';\r\n\r\n const text = parts.join(', ');\r\n return this.isNegative() ? `-${text}` : text;\r\n }\r\n\r\n /**\r\n * Check if duration is negative\r\n */\r\n isNegative(): boolean {\r\n return (\r\n this.years < 0 ||\r\n this.months < 0 ||\r\n this.weeks < 0 ||\r\n this.days < 0 ||\r\n this.hours < 0 ||\r\n this.minutes < 0 ||\r\n this.seconds < 0 ||\r\n this.milliseconds < 0\r\n );\r\n }\r\n\r\n /**\r\n * Get absolute duration\r\n */\r\n abs(): Duration {\r\n return new Duration({\r\n years: Math.abs(this.years),\r\n months: Math.abs(this.months),\r\n weeks: Math.abs(this.weeks),\r\n days: Math.abs(this.days),\r\n hours: Math.abs(this.hours),\r\n minutes: Math.abs(this.minutes),\r\n seconds: Math.abs(this.seconds),\r\n milliseconds: Math.abs(this.milliseconds),\r\n });\r\n }\r\n\r\n /**\r\n * String representation\r\n */\r\n toString(): string {\r\n return this.toISO();\r\n }\r\n}\r\n\r\n/**\r\n * Duration Plugin\r\n */\r\nexport class DurationPlugin implements ITimeGuardPlugin {\r\n name = 'duration';\r\n version = '1.0.0';\r\n\r\n /**\r\n * Install plugin into TimeGuard\r\n */\r\n install(TimeGuardClass: typeof TimeGuard): void {\r\n /**\r\n * Create a Duration between this date and another\r\n */\r\n (TimeGuardClass.prototype as any).duration = function (other: TimeGuard): Duration {\r\n return Duration.between(this, other);\r\n };\r\n\r\n /**\r\n * Get Duration class for creating custom durations\r\n */\r\n (TimeGuardClass as any).Duration = Duration;\r\n\r\n /**\r\n * Create Duration from ISO 8601 string\r\n */\r\n (TimeGuardClass as any).duration = {\r\n fromISO: (iso: string): Duration => Duration.fromISO(iso),\r\n between: (from: TimeGuard, to: TimeGuard): Duration => Duration.between(from, to),\r\n fromMilliseconds: (ms: number): Duration => Duration.fromMilliseconds(ms),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Create and export default instance\r\n */\r\nexport const durationPlugin = new DurationPlugin();\r\n\r\nexport default durationPlugin;\r\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relative-time.cjs","names":[],"sources":["../../src/plugins/relative-time/index.ts"],"sourcesContent":["/**\r\n * TimeGuard Relative Time Plugin\r\n * Adds human-readable time differences (e.g., \"2 hours ago\", \"in 3 days\")\r\n * Follows SOLID principles and Temporal API standards\r\n */\r\n\r\nimport type { ITimeGuardPlugin } from '../../types';\r\nimport type { TimeGuard } from '../../
|
|
1
|
+
{"version":3,"file":"relative-time.cjs","names":[],"sources":["../../src/plugins/relative-time/index.ts"],"sourcesContent":["/**\r\n * TimeGuard Relative Time Plugin\r\n * Adds human-readable time differences (e.g., \"2 hours ago\", \"in 3 days\")\r\n * Follows SOLID principles and Temporal API standards\r\n */\r\n\r\nimport type { ITimeGuardPlugin } from '../../types';\r\nimport type { TimeGuard } from '../../index';\r\nimport type { RelativeTimeConfig, RelativeTimeFormats, RelativeTimeThreshold } from './types';\r\n\r\nconst DEFAULT_THRESHOLDS: RelativeTimeThreshold[] = [\r\n { l: 's', r: 44, d: 'second' },\r\n { l: 'm', r: 89 },\r\n { l: 'mm', r: 44, d: 'minute' },\r\n { l: 'h', r: 89 },\r\n { l: 'hh', r: 21, d: 'hour' },\r\n { l: 'd', r: 35 },\r\n { l: 'dd', r: 25, d: 'day' },\r\n { l: 'M', r: 45 },\r\n { l: 'MM', r: 10, d: 'month' },\r\n { l: 'y', r: 17 },\r\n { l: 'yy', d: 'year' },\r\n];\r\n\r\nconst DEFAULT_FORMATS: RelativeTimeFormats = {\r\n future: 'in %s',\r\n past: '%s ago',\r\n s: 'a few seconds',\r\n m: 'a minute',\r\n mm: '%d minutes',\r\n h: 'an hour',\r\n hh: '%d hours',\r\n d: 'a day',\r\n dd: '%d days',\r\n M: 'a month',\r\n MM: '%d months',\r\n y: 'a year',\r\n yy: '%d years',\r\n};\r\n\r\nexport class RelativeTimePlugin implements ITimeGuardPlugin {\r\n name = 'relative-time';\r\n version = '1.0.0';\r\n \r\n private config: RelativeTimeConfig;\r\n private formats: RelativeTimeFormats;\r\n\r\n constructor(config?: RelativeTimeConfig) {\r\n this.config = {\r\n thresholds: config?.thresholds || DEFAULT_THRESHOLDS,\r\n rounding: config?.rounding || Math.round,\r\n };\r\n this.formats = DEFAULT_FORMATS;\r\n }\r\n\r\n /**\r\n * Install plugin into TimeGuard\r\n */\r\n install(TimeGuardClass: typeof TimeGuard): void {\r\n const plugin = this;\r\n\r\n /**\r\n * Get relative time string (e.g., \"2 hours ago\")\r\n */\r\n (TimeGuardClass.prototype as any).fromNow = function (withoutSuffix?: boolean): string {\r\n return plugin.formatRelativeTime(this, false, withoutSuffix);\r\n };\r\n\r\n /**\r\n * Get future relative time string (e.g., \"in 3 days\")\r\n */\r\n (TimeGuardClass.prototype as any).toNow = function (withoutSuffix?: boolean): string {\r\n return plugin.formatRelativeTime(this, true, withoutSuffix);\r\n };\r\n\r\n /**\r\n * Get human-readable duration\r\n */\r\n (TimeGuardClass.prototype as any).humanize = function (\r\n other?: TimeGuard,\r\n withoutSuffix?: boolean,\r\n ): string {\r\n if (other) {\r\n return plugin.formatRelativeTime(this, other.isAfter(this), withoutSuffix);\r\n }\r\n return plugin.formatRelativeTime(this, false, withoutSuffix);\r\n };\r\n }\r\n\r\n /**\r\n * Format relative time\r\n */\r\n private formatRelativeTime(\r\n date: TimeGuard,\r\n isFuture: boolean,\r\n withoutSuffix?: boolean,\r\n ): string {\r\n const now = (date.constructor as typeof TimeGuard).now();\r\n let diff = now.diff(date, 'millisecond');\r\n const absDiff = Math.abs(diff);\r\n const isFromNow = diff > 0;\r\n const actualIsFuture = isFuture ?? !isFromNow;\r\n\r\n let result = this.getRelativeTimeString(absDiff);\r\n\r\n if (withoutSuffix) {\r\n return result;\r\n }\r\n\r\n const suffix = actualIsFuture ? this.formats.future : this.formats.past;\r\n return suffix.replace('%s', result);\r\n }\r\n\r\n /**\r\n * Get relative time string based on milliseconds\r\n */\r\n private getRelativeTimeString(milliseconds: number): string {\r\n const thresholds = this.config.thresholds || DEFAULT_THRESHOLDS;\r\n const rounding = this.config.rounding || Math.round;\r\n\r\n for (let i = 0; i < thresholds.length; i++) {\r\n const threshold = thresholds[i];\r\n const nextThreshold = i + 1 < thresholds.length ? thresholds[i + 1] : null;\r\n\r\n // Skip if we haven't reached this threshold\r\n if (nextThreshold && threshold.r && milliseconds < threshold.r * 1000) {\r\n continue;\r\n }\r\n\r\n // Convert to appropriate unit\r\n let value: number;\r\n if (threshold.d) {\r\n const unitMs = this.getUnitMilliseconds(threshold.d);\r\n value = rounding(milliseconds / unitMs);\r\n } else {\r\n value = 1;\r\n }\r\n\r\n const label = threshold.l;\r\n const format = (this.formats as any)[label] || label;\r\n\r\n if (typeof format === 'string') {\r\n return format.includes('%d')\r\n ? format.replace('%d', String(value))\r\n : format;\r\n }\r\n\r\n return format;\r\n }\r\n\r\n // Fallback\r\n return `${rounding(milliseconds / 1000)} seconds`;\r\n }\r\n\r\n /**\r\n * Get milliseconds per unit\r\n */\r\n private getUnitMilliseconds(unit: string): number {\r\n const msMap: Record<string, number> = {\r\n second: 1000,\r\n minute: 1000 * 60,\r\n hour: 1000 * 60 * 60,\r\n day: 1000 * 60 * 60 * 24,\r\n month: 1000 * 60 * 60 * 24 * 30,\r\n year: 1000 * 60 * 60 * 24 * 365,\r\n };\r\n return msMap[unit] || 1;\r\n }\r\n\r\n /**\r\n * Set format strings\r\n */\r\n setFormats(formats: Partial<RelativeTimeFormats>): void {\r\n Object.assign(this.formats, formats);\r\n }\r\n\r\n /**\r\n * Get current formats\r\n */\r\n getFormats(): RelativeTimeFormats {\r\n return { ...this.formats };\r\n }\r\n}\r\n\r\n/**\r\n * Create and export default instance\r\n */\r\nexport default new RelativeTimePlugin();\r\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! time-guard v2.5.
|
|
1
|
+
/*! time-guard v2.5.3 | (c) 2026 Berea-Soft | MIT License | https://github.com/Berea-Soft/time-guard */
|
|
2
2
|
//#region src/plugins/relative-time/index.ts
|
|
3
3
|
var e = [
|
|
4
4
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relative-time.es.js","names":[],"sources":["../../src/plugins/relative-time/index.ts"],"sourcesContent":["/**\r\n * TimeGuard Relative Time Plugin\r\n * Adds human-readable time differences (e.g., \"2 hours ago\", \"in 3 days\")\r\n * Follows SOLID principles and Temporal API standards\r\n */\r\n\r\nimport type { ITimeGuardPlugin } from '../../types';\r\nimport type { TimeGuard } from '../../
|
|
1
|
+
{"version":3,"file":"relative-time.es.js","names":[],"sources":["../../src/plugins/relative-time/index.ts"],"sourcesContent":["/**\r\n * TimeGuard Relative Time Plugin\r\n * Adds human-readable time differences (e.g., \"2 hours ago\", \"in 3 days\")\r\n * Follows SOLID principles and Temporal API standards\r\n */\r\n\r\nimport type { ITimeGuardPlugin } from '../../types';\r\nimport type { TimeGuard } from '../../index';\r\nimport type { RelativeTimeConfig, RelativeTimeFormats, RelativeTimeThreshold } from './types';\r\n\r\nconst DEFAULT_THRESHOLDS: RelativeTimeThreshold[] = [\r\n { l: 's', r: 44, d: 'second' },\r\n { l: 'm', r: 89 },\r\n { l: 'mm', r: 44, d: 'minute' },\r\n { l: 'h', r: 89 },\r\n { l: 'hh', r: 21, d: 'hour' },\r\n { l: 'd', r: 35 },\r\n { l: 'dd', r: 25, d: 'day' },\r\n { l: 'M', r: 45 },\r\n { l: 'MM', r: 10, d: 'month' },\r\n { l: 'y', r: 17 },\r\n { l: 'yy', d: 'year' },\r\n];\r\n\r\nconst DEFAULT_FORMATS: RelativeTimeFormats = {\r\n future: 'in %s',\r\n past: '%s ago',\r\n s: 'a few seconds',\r\n m: 'a minute',\r\n mm: '%d minutes',\r\n h: 'an hour',\r\n hh: '%d hours',\r\n d: 'a day',\r\n dd: '%d days',\r\n M: 'a month',\r\n MM: '%d months',\r\n y: 'a year',\r\n yy: '%d years',\r\n};\r\n\r\nexport class RelativeTimePlugin implements ITimeGuardPlugin {\r\n name = 'relative-time';\r\n version = '1.0.0';\r\n \r\n private config: RelativeTimeConfig;\r\n private formats: RelativeTimeFormats;\r\n\r\n constructor(config?: RelativeTimeConfig) {\r\n this.config = {\r\n thresholds: config?.thresholds || DEFAULT_THRESHOLDS,\r\n rounding: config?.rounding || Math.round,\r\n };\r\n this.formats = DEFAULT_FORMATS;\r\n }\r\n\r\n /**\r\n * Install plugin into TimeGuard\r\n */\r\n install(TimeGuardClass: typeof TimeGuard): void {\r\n const plugin = this;\r\n\r\n /**\r\n * Get relative time string (e.g., \"2 hours ago\")\r\n */\r\n (TimeGuardClass.prototype as any).fromNow = function (withoutSuffix?: boolean): string {\r\n return plugin.formatRelativeTime(this, false, withoutSuffix);\r\n };\r\n\r\n /**\r\n * Get future relative time string (e.g., \"in 3 days\")\r\n */\r\n (TimeGuardClass.prototype as any).toNow = function (withoutSuffix?: boolean): string {\r\n return plugin.formatRelativeTime(this, true, withoutSuffix);\r\n };\r\n\r\n /**\r\n * Get human-readable duration\r\n */\r\n (TimeGuardClass.prototype as any).humanize = function (\r\n other?: TimeGuard,\r\n withoutSuffix?: boolean,\r\n ): string {\r\n if (other) {\r\n return plugin.formatRelativeTime(this, other.isAfter(this), withoutSuffix);\r\n }\r\n return plugin.formatRelativeTime(this, false, withoutSuffix);\r\n };\r\n }\r\n\r\n /**\r\n * Format relative time\r\n */\r\n private formatRelativeTime(\r\n date: TimeGuard,\r\n isFuture: boolean,\r\n withoutSuffix?: boolean,\r\n ): string {\r\n const now = (date.constructor as typeof TimeGuard).now();\r\n let diff = now.diff(date, 'millisecond');\r\n const absDiff = Math.abs(diff);\r\n const isFromNow = diff > 0;\r\n const actualIsFuture = isFuture ?? !isFromNow;\r\n\r\n let result = this.getRelativeTimeString(absDiff);\r\n\r\n if (withoutSuffix) {\r\n return result;\r\n }\r\n\r\n const suffix = actualIsFuture ? this.formats.future : this.formats.past;\r\n return suffix.replace('%s', result);\r\n }\r\n\r\n /**\r\n * Get relative time string based on milliseconds\r\n */\r\n private getRelativeTimeString(milliseconds: number): string {\r\n const thresholds = this.config.thresholds || DEFAULT_THRESHOLDS;\r\n const rounding = this.config.rounding || Math.round;\r\n\r\n for (let i = 0; i < thresholds.length; i++) {\r\n const threshold = thresholds[i];\r\n const nextThreshold = i + 1 < thresholds.length ? thresholds[i + 1] : null;\r\n\r\n // Skip if we haven't reached this threshold\r\n if (nextThreshold && threshold.r && milliseconds < threshold.r * 1000) {\r\n continue;\r\n }\r\n\r\n // Convert to appropriate unit\r\n let value: number;\r\n if (threshold.d) {\r\n const unitMs = this.getUnitMilliseconds(threshold.d);\r\n value = rounding(milliseconds / unitMs);\r\n } else {\r\n value = 1;\r\n }\r\n\r\n const label = threshold.l;\r\n const format = (this.formats as any)[label] || label;\r\n\r\n if (typeof format === 'string') {\r\n return format.includes('%d')\r\n ? format.replace('%d', String(value))\r\n : format;\r\n }\r\n\r\n return format;\r\n }\r\n\r\n // Fallback\r\n return `${rounding(milliseconds / 1000)} seconds`;\r\n }\r\n\r\n /**\r\n * Get milliseconds per unit\r\n */\r\n private getUnitMilliseconds(unit: string): number {\r\n const msMap: Record<string, number> = {\r\n second: 1000,\r\n minute: 1000 * 60,\r\n hour: 1000 * 60 * 60,\r\n day: 1000 * 60 * 60 * 24,\r\n month: 1000 * 60 * 60 * 24 * 30,\r\n year: 1000 * 60 * 60 * 24 * 365,\r\n };\r\n return msMap[unit] || 1;\r\n }\r\n\r\n /**\r\n * Set format strings\r\n */\r\n setFormats(formats: Partial<RelativeTimeFormats>): void {\r\n Object.assign(this.formats, formats);\r\n }\r\n\r\n /**\r\n * Get current formats\r\n */\r\n getFormats(): RelativeTimeFormats {\r\n return { ...this.formats };\r\n }\r\n}\r\n\r\n/**\r\n * Create and export default instance\r\n */\r\nexport default new RelativeTimePlugin();\r\n"],"mappings":"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"}
|