ts-time-utils 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +343 -0
  2. package/dist/age.d.ts +49 -0
  3. package/dist/age.d.ts.map +1 -0
  4. package/dist/age.js +106 -0
  5. package/dist/calculate.d.ts +49 -0
  6. package/dist/calculate.d.ts.map +1 -0
  7. package/dist/calculate.js +179 -0
  8. package/dist/calendar.d.ts +82 -0
  9. package/dist/calendar.d.ts.map +1 -0
  10. package/dist/calendar.js +154 -0
  11. package/dist/constants.d.ts +35 -0
  12. package/dist/constants.d.ts.map +1 -0
  13. package/dist/constants.js +17 -0
  14. package/dist/esm/age.d.ts +49 -0
  15. package/dist/esm/age.d.ts.map +1 -0
  16. package/dist/esm/age.js +106 -0
  17. package/dist/esm/calculate.d.ts +49 -0
  18. package/dist/esm/calculate.d.ts.map +1 -0
  19. package/dist/esm/calculate.js +179 -0
  20. package/dist/esm/calendar.d.ts +82 -0
  21. package/dist/esm/calendar.d.ts.map +1 -0
  22. package/dist/esm/calendar.js +154 -0
  23. package/dist/esm/constants.d.ts +35 -0
  24. package/dist/esm/constants.d.ts.map +1 -0
  25. package/dist/esm/constants.js +17 -0
  26. package/dist/esm/format.d.ts +25 -0
  27. package/dist/esm/format.d.ts.map +1 -0
  28. package/dist/esm/format.js +189 -0
  29. package/dist/esm/index.d.ts +17 -0
  30. package/dist/esm/index.d.ts.map +1 -0
  31. package/dist/esm/index.js +28 -0
  32. package/dist/esm/interval.d.ts +30 -0
  33. package/dist/esm/interval.d.ts.map +1 -0
  34. package/dist/esm/interval.js +86 -0
  35. package/dist/esm/parse.d.ts +31 -0
  36. package/dist/esm/parse.d.ts.map +1 -0
  37. package/dist/esm/parse.js +217 -0
  38. package/dist/esm/performance.d.ts +110 -0
  39. package/dist/esm/performance.d.ts.map +1 -0
  40. package/dist/esm/performance.js +222 -0
  41. package/dist/esm/rangePresets.d.ts +45 -0
  42. package/dist/esm/rangePresets.d.ts.map +1 -0
  43. package/dist/esm/rangePresets.js +124 -0
  44. package/dist/esm/timezone.d.ts +38 -0
  45. package/dist/esm/timezone.d.ts.map +1 -0
  46. package/dist/esm/timezone.js +99 -0
  47. package/dist/esm/validate.d.ts +62 -0
  48. package/dist/esm/validate.d.ts.map +1 -0
  49. package/dist/esm/validate.js +108 -0
  50. package/dist/esm/workingHours.d.ts +25 -0
  51. package/dist/esm/workingHours.d.ts.map +1 -0
  52. package/dist/esm/workingHours.js +107 -0
  53. package/dist/format.d.ts +25 -0
  54. package/dist/format.d.ts.map +1 -0
  55. package/dist/format.js +189 -0
  56. package/dist/index.d.ts +17 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +28 -0
  59. package/dist/interval.d.ts +30 -0
  60. package/dist/interval.d.ts.map +1 -0
  61. package/dist/interval.js +86 -0
  62. package/dist/parse.d.ts +31 -0
  63. package/dist/parse.d.ts.map +1 -0
  64. package/dist/parse.js +217 -0
  65. package/dist/performance.d.ts +110 -0
  66. package/dist/performance.d.ts.map +1 -0
  67. package/dist/performance.js +222 -0
  68. package/dist/rangePresets.d.ts +45 -0
  69. package/dist/rangePresets.d.ts.map +1 -0
  70. package/dist/rangePresets.js +124 -0
  71. package/dist/timezone.d.ts +38 -0
  72. package/dist/timezone.d.ts.map +1 -0
  73. package/dist/timezone.js +99 -0
  74. package/dist/validate.d.ts +62 -0
  75. package/dist/validate.d.ts.map +1 -0
  76. package/dist/validate.js +108 -0
  77. package/dist/workingHours.d.ts +25 -0
  78. package/dist/workingHours.d.ts.map +1 -0
  79. package/dist/workingHours.js +107 -0
  80. package/package.json +102 -0
@@ -0,0 +1,45 @@
1
+ /** Predefined date range helpers (returns [start,end]) */
2
+ export interface DateRange {
3
+ start: Date;
4
+ end: Date;
5
+ }
6
+ export declare function today(now?: Date): DateRange;
7
+ export declare function yesterday(now?: Date): DateRange;
8
+ export declare function tomorrow(now?: Date): DateRange;
9
+ export declare function lastNDays(n: number, now?: Date): DateRange;
10
+ export declare function nextNDays(n: number, now?: Date): DateRange;
11
+ export declare function thisWeek(now?: Date): DateRange;
12
+ export declare function lastWeek(now?: Date): DateRange;
13
+ export declare function nextWeek(now?: Date): DateRange;
14
+ export declare function thisMonth(now?: Date): DateRange;
15
+ export declare function lastMonth(now?: Date): DateRange;
16
+ export declare function nextMonth(now?: Date): DateRange;
17
+ export declare function thisYear(now?: Date): DateRange;
18
+ export declare function lastYear(now?: Date): DateRange;
19
+ export declare function nextYear(now?: Date): DateRange;
20
+ export declare function rollingWindowDays(days: number, now?: Date): DateRange;
21
+ export declare function quarterRange(date?: Date): DateRange;
22
+ export declare function lastQuarter(date?: Date): DateRange;
23
+ export declare function nextQuarter(date?: Date): DateRange;
24
+ /** Map of preset functions for dynamic access */
25
+ export declare const RANGE_PRESETS: {
26
+ today: typeof today;
27
+ yesterday: typeof yesterday;
28
+ tomorrow: typeof tomorrow;
29
+ last7Days: (now?: Date) => DateRange;
30
+ last30Days: (now?: Date) => DateRange;
31
+ next7Days: (now?: Date) => DateRange;
32
+ thisWeek: typeof thisWeek;
33
+ lastWeek: typeof lastWeek;
34
+ nextWeek: typeof nextWeek;
35
+ thisMonth: typeof thisMonth;
36
+ lastMonth: typeof lastMonth;
37
+ nextMonth: typeof nextMonth;
38
+ thisYear: typeof thisYear;
39
+ lastYear: typeof lastYear;
40
+ nextYear: typeof nextYear;
41
+ quarter: typeof quarterRange;
42
+ lastQuarter: typeof lastQuarter;
43
+ nextQuarter: typeof nextQuarter;
44
+ };
45
+ //# sourceMappingURL=rangePresets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rangePresets.d.ts","sourceRoot":"","sources":["../src/rangePresets.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAE1D,MAAM,WAAW,SAAS;IAAG,KAAK,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,IAAI,CAAC;CAAE;AAQtD,wBAAgB,KAAK,CAAC,GAAG,OAAa,GAAG,SAAS,CAA4B;AAC9E,wBAAgB,SAAS,CAAC,GAAG,OAAa,GAAG,SAAS,CAKrD;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAKpD;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,SAAS,CAIhE;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,SAAS,CAIhE;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAOpD;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAKpD;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAKpD;AAED,wBAAgB,SAAS,CAAC,GAAG,OAAa,GAAG,SAAS,CAIrD;AAED,wBAAgB,SAAS,CAAC,GAAG,OAAa,GAAG,SAAS,CAKrD;AAED,wBAAgB,SAAS,CAAC,GAAG,OAAa,GAAG,SAAS,CAKrD;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAIpD;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAKpD;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAKpD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,SAAS,CAI3E;AAED,wBAAgB,YAAY,CAAC,IAAI,OAAa,GAAG,SAAS,CAKzD;AAED,wBAAgB,WAAW,CAAC,IAAI,OAAa,GAAG,SAAS,CAKxD;AAED,wBAAgB,WAAW,CAAC,IAAI,OAAa,GAAG,SAAS,CAKxD;AAED,iDAAiD;AACjD,eAAO,MAAM,aAAa;;;;sBAEN,IAAI;uBACH,IAAI;sBACL,IAAI;;;;;;;;;;;;;CAKvB,CAAC"}
@@ -0,0 +1,124 @@
1
+ /** Predefined date range helpers (returns [start,end]) */
2
+ function todayRange(now = new Date()) {
3
+ const start = new Date(now);
4
+ start.setHours(0, 0, 0, 0);
5
+ const end = new Date(start);
6
+ end.setDate(end.getDate() + 1);
7
+ return { start, end };
8
+ }
9
+ export function today(now = new Date()) { return todayRange(now); }
10
+ export function yesterday(now = new Date()) {
11
+ const t = todayRange(now);
12
+ const end = new Date(t.start); // yesterday end equals today start
13
+ const start = new Date(end);
14
+ start.setDate(start.getDate() - 1);
15
+ return { start, end };
16
+ }
17
+ export function tomorrow(now = new Date()) {
18
+ const t = todayRange(now);
19
+ t.start.setDate(t.start.getDate() + 1);
20
+ t.end.setDate(t.end.getDate() + 1);
21
+ return t;
22
+ }
23
+ export function lastNDays(n, now = new Date()) {
24
+ const end = new Date(now);
25
+ const start = new Date(end);
26
+ start.setDate(start.getDate() - n);
27
+ return { start, end };
28
+ }
29
+ export function nextNDays(n, now = new Date()) {
30
+ const start = new Date(now);
31
+ const end = new Date(start);
32
+ end.setDate(end.getDate() + n);
33
+ return { start, end };
34
+ }
35
+ export function thisWeek(now = new Date()) {
36
+ const start = new Date(now);
37
+ const day = start.getDay(); // 0 Sunday
38
+ start.setHours(0, 0, 0, 0);
39
+ start.setDate(start.getDate() - day); // start of week Sunday
40
+ const end = new Date(start);
41
+ end.setDate(end.getDate() + 7);
42
+ return { start, end };
43
+ }
44
+ export function lastWeek(now = new Date()) {
45
+ const w = thisWeek(now);
46
+ w.start.setDate(w.start.getDate() - 7);
47
+ w.end.setDate(w.end.getDate() - 7);
48
+ return w;
49
+ }
50
+ export function nextWeek(now = new Date()) {
51
+ const w = thisWeek(now);
52
+ w.start.setDate(w.start.getDate() + 7);
53
+ w.end.setDate(w.end.getDate() + 7);
54
+ return w;
55
+ }
56
+ export function thisMonth(now = new Date()) {
57
+ const start = new Date(now.getFullYear(), now.getMonth(), 1);
58
+ const end = new Date(now.getFullYear(), now.getMonth() + 1, 1);
59
+ return { start, end };
60
+ }
61
+ export function lastMonth(now = new Date()) {
62
+ const m = thisMonth(now);
63
+ m.start.setMonth(m.start.getMonth() - 1);
64
+ m.end.setMonth(m.end.getMonth() - 1);
65
+ return m;
66
+ }
67
+ export function nextMonth(now = new Date()) {
68
+ const m = thisMonth(now);
69
+ m.start.setMonth(m.start.getMonth() + 1);
70
+ m.end.setMonth(m.end.getMonth() + 1);
71
+ return m;
72
+ }
73
+ export function thisYear(now = new Date()) {
74
+ const start = new Date(now.getFullYear(), 0, 1);
75
+ const end = new Date(now.getFullYear() + 1, 0, 1);
76
+ return { start, end };
77
+ }
78
+ export function lastYear(now = new Date()) {
79
+ const y = thisYear(now);
80
+ y.start.setFullYear(y.start.getFullYear() - 1);
81
+ y.end.setFullYear(y.end.getFullYear() - 1);
82
+ return y;
83
+ }
84
+ export function nextYear(now = new Date()) {
85
+ const y = thisYear(now);
86
+ y.start.setFullYear(y.start.getFullYear() + 1);
87
+ y.end.setFullYear(y.end.getFullYear() + 1);
88
+ return y;
89
+ }
90
+ export function rollingWindowDays(days, now = new Date()) {
91
+ const end = new Date(now);
92
+ const start = new Date(end);
93
+ start.setDate(start.getDate() - days);
94
+ return { start, end };
95
+ }
96
+ export function quarterRange(date = new Date()) {
97
+ const q = Math.floor(date.getMonth() / 3); // 0-3
98
+ const start = new Date(date.getFullYear(), q * 3, 1);
99
+ const end = new Date(date.getFullYear(), q * 3 + 3, 1);
100
+ return { start, end };
101
+ }
102
+ export function lastQuarter(date = new Date()) {
103
+ const q = quarterRange(date);
104
+ q.start.setMonth(q.start.getMonth() - 3);
105
+ q.end.setMonth(q.end.getMonth() - 3);
106
+ return q;
107
+ }
108
+ export function nextQuarter(date = new Date()) {
109
+ const q = quarterRange(date);
110
+ q.start.setMonth(q.start.getMonth() + 3);
111
+ q.end.setMonth(q.end.getMonth() + 3);
112
+ return q;
113
+ }
114
+ /** Map of preset functions for dynamic access */
115
+ export const RANGE_PRESETS = {
116
+ today, yesterday, tomorrow,
117
+ last7Days: (now) => lastNDays(7, now),
118
+ last30Days: (now) => lastNDays(30, now),
119
+ next7Days: (now) => nextNDays(7, now),
120
+ thisWeek, lastWeek, nextWeek,
121
+ thisMonth, lastMonth, nextMonth,
122
+ thisYear, lastYear, nextYear,
123
+ quarter: quarterRange, lastQuarter, nextQuarter,
124
+ };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Timezone utilities (rely on Intl API, fallbacks where possible)
3
+ */
4
+ export interface ZonedTime {
5
+ date: Date;
6
+ zone: string;
7
+ offsetMinutes: number;
8
+ }
9
+ /** Get offset (minutes) for a zone at a given date */
10
+ export declare function getTimezoneOffset(zone: string, date?: Date): number | null;
11
+ /** Format date/time in a zone */
12
+ export declare function formatInTimeZone(date: Date, zone: string, options?: Intl.DateTimeFormatOptions): string;
13
+ /** Get a lightweight ZonedTime object */
14
+ export declare function getZonedTime(date: Date, zone: string): ZonedTime | null;
15
+ /** Convert a date (treated as absolute moment) to another zone's clock components */
16
+ export declare function convertDateToZone(date: Date, zone: string): {
17
+ year: number;
18
+ month: number;
19
+ day: number;
20
+ hour: number;
21
+ minute: number;
22
+ second: number;
23
+ } | null;
24
+ /** Check if provided zone string is a valid IANA zone */
25
+ export declare function isValidTimeZone(zone: string): boolean;
26
+ /** List a subset of common timezones (cannot enumerate all via API) */
27
+ export declare const COMMON_TIMEZONES: string[];
28
+ /** Get current local offset in minutes */
29
+ export declare function getLocalOffset(): number;
30
+ /** Compare two timezones offset at given date */
31
+ export declare function compareZoneOffsets(zoneA: string, zoneB: string, date?: Date): number | null;
32
+ /** Shift a date by target zone offset difference relative to current local zone.
33
+ * This does not change the absolute moment; instead returns a new Date representing
34
+ * the same wall clock time in the target zone interpreted as local.
35
+ * For example useful for naive scheduling.
36
+ */
37
+ export declare function reinterpretAsZone(date: Date, targetZone: string): Date | null;
38
+ //# sourceMappingURL=timezone.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timezone.d.ts","sourceRoot":"","sources":["../src/timezone.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,sDAAsD;AACtD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,MAAM,GAAG,IAAI,CAgBtF;AAED,iCAAiC;AACjC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,qBAA0B,GAAG,MAAM,CAG3G;AAED,yCAAyC;AACzC,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAIvE;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;CAAE,GAAG,IAAI,CAoB9J;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED,uEAAuE;AACvE,eAAO,MAAM,gBAAgB,UAK5B,CAAC;AAEF,0CAA0C;AAC1C,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,MAAM,GAAG,IAAI,CAKvG;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAI7E"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Timezone utilities (rely on Intl API, fallbacks where possible)
3
+ */
4
+ /** Get offset (minutes) for a zone at a given date */
5
+ export function getTimezoneOffset(zone, date = new Date()) {
6
+ try {
7
+ const dtf = new Intl.DateTimeFormat('en-US', { timeZone: zone, timeZoneName: 'shortOffset', hour: '2-digit' });
8
+ const parts = dtf.formatToParts(date);
9
+ const tzPart = parts.find(p => p.type === 'timeZoneName');
10
+ if (!tzPart)
11
+ return null;
12
+ // Examples: "GMT+2", "UTC-05:00"
13
+ const match = tzPart.value.match(/([+-])(\d{1,2})(?::?(\d{2}))?/);
14
+ if (!match)
15
+ return 0; // could be GMT or UTC with no offset
16
+ const sign = match[1] === '-' ? -1 : 1;
17
+ const hours = parseInt(match[2], 10);
18
+ const mins = match[3] ? parseInt(match[3], 10) : 0;
19
+ return sign * (hours * 60 + mins);
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ }
25
+ /** Format date/time in a zone */
26
+ export function formatInTimeZone(date, zone, options = {}) {
27
+ const fmt = new Intl.DateTimeFormat('en-US', { timeZone: zone, ...options });
28
+ return fmt.format(date);
29
+ }
30
+ /** Get a lightweight ZonedTime object */
31
+ export function getZonedTime(date, zone) {
32
+ const offset = getTimezoneOffset(zone, date);
33
+ if (offset == null)
34
+ return null;
35
+ return { date: new Date(date), zone, offsetMinutes: offset };
36
+ }
37
+ /** Convert a date (treated as absolute moment) to another zone's clock components */
38
+ export function convertDateToZone(date, zone) {
39
+ try {
40
+ const fmt = new Intl.DateTimeFormat('en-US', {
41
+ timeZone: zone,
42
+ year: 'numeric', month: '2-digit', day: '2-digit',
43
+ hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false
44
+ });
45
+ const parts = fmt.formatToParts(date);
46
+ const get = (type) => parseInt(parts.find(p => p.type === type)?.value || '0', 10);
47
+ return {
48
+ year: get('year'),
49
+ month: get('month'),
50
+ day: get('day'),
51
+ hour: get('hour'),
52
+ minute: get('minute'),
53
+ second: get('second')
54
+ };
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
60
+ /** Check if provided zone string is a valid IANA zone */
61
+ export function isValidTimeZone(zone) {
62
+ try {
63
+ new Intl.DateTimeFormat('en-US', { timeZone: zone });
64
+ return true;
65
+ }
66
+ catch {
67
+ return false;
68
+ }
69
+ }
70
+ /** List a subset of common timezones (cannot enumerate all via API) */
71
+ export const COMMON_TIMEZONES = [
72
+ 'UTC', 'Etc/UTC', 'Europe/London', 'Europe/Paris', 'Europe/Berlin', 'Europe/Madrid', 'Europe/Rome',
73
+ 'America/New_York', 'America/Chicago', 'America/Denver', 'America/Los_Angeles', 'America/Toronto', 'America/Sao_Paulo',
74
+ 'Asia/Tehran', 'Asia/Dubai', 'Asia/Tokyo', 'Asia/Shanghai', 'Asia/Singapore', 'Asia/Kolkata', 'Asia/Hong_Kong',
75
+ 'Australia/Sydney', 'Pacific/Auckland'
76
+ ];
77
+ /** Get current local offset in minutes */
78
+ export function getLocalOffset() {
79
+ return -new Date().getTimezoneOffset();
80
+ }
81
+ /** Compare two timezones offset at given date */
82
+ export function compareZoneOffsets(zoneA, zoneB, date = new Date()) {
83
+ const a = getTimezoneOffset(zoneA, date);
84
+ const b = getTimezoneOffset(zoneB, date);
85
+ if (a == null || b == null)
86
+ return null;
87
+ return a - b; // positive if A ahead of B
88
+ }
89
+ /** Shift a date by target zone offset difference relative to current local zone.
90
+ * This does not change the absolute moment; instead returns a new Date representing
91
+ * the same wall clock time in the target zone interpreted as local.
92
+ * For example useful for naive scheduling.
93
+ */
94
+ export function reinterpretAsZone(date, targetZone) {
95
+ const target = convertDateToZone(date, targetZone);
96
+ if (!target)
97
+ return null;
98
+ return new Date(Date.UTC(target.year, target.month - 1, target.day, target.hour, target.minute, target.second));
99
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Check if a date is valid
3
+ * @param date - date to validate
4
+ */
5
+ export declare function isValidDate(date: Date | string | number): boolean;
6
+ /**
7
+ * Check if a year is a leap year
8
+ * @param year - year to check
9
+ */
10
+ export declare function isLeapYear(year: number): boolean;
11
+ /**
12
+ * Check if a date is in the past
13
+ * @param date - date to check
14
+ */
15
+ export declare function isPast(date: Date): boolean;
16
+ /**
17
+ * Check if a date is in the future
18
+ * @param date - date to check
19
+ */
20
+ export declare function isFuture(date: Date): boolean;
21
+ /**
22
+ * Check if a date is today
23
+ * @param date - date to check
24
+ */
25
+ export declare function isToday(date: Date): boolean;
26
+ /**
27
+ * Check if a date is yesterday
28
+ * @param date - date to check
29
+ */
30
+ export declare function isYesterday(date: Date): boolean;
31
+ /**
32
+ * Check if a date is tomorrow
33
+ * @param date - date to check
34
+ */
35
+ export declare function isTomorrow(date: Date): boolean;
36
+ /**
37
+ * Check if two dates are the same day
38
+ * @param date1 - first date
39
+ * @param date2 - second date
40
+ */
41
+ export declare function isSameDay(date1: Date, date2: Date): boolean;
42
+ /**
43
+ * Check if a date is a weekend (Saturday or Sunday)
44
+ * @param date - date to check
45
+ */
46
+ export declare function isWeekend(date: Date): boolean;
47
+ /**
48
+ * Check if a date is a weekday (Monday through Friday)
49
+ * @param date - date to check
50
+ */
51
+ export declare function isWeekday(date: Date): boolean;
52
+ /**
53
+ * Check if a time string is valid (HH:MM or HH:MM:SS format)
54
+ * @param time - time string to validate
55
+ */
56
+ export declare function isValidTimeString(time: string): boolean;
57
+ /**
58
+ * Check if a date string is valid ISO 8601 format
59
+ * @param dateString - date string to validate
60
+ */
61
+ export declare function isValidISOString(dateString: string): boolean;
62
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAWjE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE1C;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE5C;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAO3C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAQ/C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAQ9C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,OAAO,CAM3D;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAG7C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE7C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAG5D"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Check if a date is valid
3
+ * @param date - date to validate
4
+ */
5
+ export function isValidDate(date) {
6
+ if (date instanceof Date) {
7
+ return !isNaN(date.getTime());
8
+ }
9
+ if (typeof date === 'string' || typeof date === 'number') {
10
+ const parsed = new Date(date);
11
+ return !isNaN(parsed.getTime());
12
+ }
13
+ return false;
14
+ }
15
+ /**
16
+ * Check if a year is a leap year
17
+ * @param year - year to check
18
+ */
19
+ export function isLeapYear(year) {
20
+ return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
21
+ }
22
+ /**
23
+ * Check if a date is in the past
24
+ * @param date - date to check
25
+ */
26
+ export function isPast(date) {
27
+ return date.getTime() < new Date().getTime();
28
+ }
29
+ /**
30
+ * Check if a date is in the future
31
+ * @param date - date to check
32
+ */
33
+ export function isFuture(date) {
34
+ return date.getTime() > new Date().getTime();
35
+ }
36
+ /**
37
+ * Check if a date is today
38
+ * @param date - date to check
39
+ */
40
+ export function isToday(date) {
41
+ const today = new Date();
42
+ return (date.getDate() === today.getDate() &&
43
+ date.getMonth() === today.getMonth() &&
44
+ date.getFullYear() === today.getFullYear());
45
+ }
46
+ /**
47
+ * Check if a date is yesterday
48
+ * @param date - date to check
49
+ */
50
+ export function isYesterday(date) {
51
+ const yesterday = new Date();
52
+ yesterday.setDate(yesterday.getDate() - 1);
53
+ return (date.getDate() === yesterday.getDate() &&
54
+ date.getMonth() === yesterday.getMonth() &&
55
+ date.getFullYear() === yesterday.getFullYear());
56
+ }
57
+ /**
58
+ * Check if a date is tomorrow
59
+ * @param date - date to check
60
+ */
61
+ export function isTomorrow(date) {
62
+ const tomorrow = new Date();
63
+ tomorrow.setDate(tomorrow.getDate() + 1);
64
+ return (date.getDate() === tomorrow.getDate() &&
65
+ date.getMonth() === tomorrow.getMonth() &&
66
+ date.getFullYear() === tomorrow.getFullYear());
67
+ }
68
+ /**
69
+ * Check if two dates are the same day
70
+ * @param date1 - first date
71
+ * @param date2 - second date
72
+ */
73
+ export function isSameDay(date1, date2) {
74
+ return (date1.getDate() === date2.getDate() &&
75
+ date1.getMonth() === date2.getMonth() &&
76
+ date1.getFullYear() === date2.getFullYear());
77
+ }
78
+ /**
79
+ * Check if a date is a weekend (Saturday or Sunday)
80
+ * @param date - date to check
81
+ */
82
+ export function isWeekend(date) {
83
+ const dayOfWeek = date.getDay();
84
+ return dayOfWeek === 0 || dayOfWeek === 6; // Sunday or Saturday
85
+ }
86
+ /**
87
+ * Check if a date is a weekday (Monday through Friday)
88
+ * @param date - date to check
89
+ */
90
+ export function isWeekday(date) {
91
+ return !isWeekend(date);
92
+ }
93
+ /**
94
+ * Check if a time string is valid (HH:MM or HH:MM:SS format)
95
+ * @param time - time string to validate
96
+ */
97
+ export function isValidTimeString(time) {
98
+ const timeRegex = /^([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/;
99
+ return timeRegex.test(time);
100
+ }
101
+ /**
102
+ * Check if a date string is valid ISO 8601 format
103
+ * @param dateString - date string to validate
104
+ */
105
+ export function isValidISOString(dateString) {
106
+ const isoRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z?$/;
107
+ return isoRegex.test(dateString) && isValidDate(dateString);
108
+ }
@@ -0,0 +1,25 @@
1
+ /** Working hours utilities */
2
+ export interface WorkingHoursConfig {
3
+ workingDays: number[];
4
+ hours: {
5
+ start: number;
6
+ end: number;
7
+ };
8
+ breaks?: {
9
+ start: number;
10
+ end: number;
11
+ }[];
12
+ timezone?: string;
13
+ }
14
+ export declare const DEFAULT_WORKING_HOURS: WorkingHoursConfig;
15
+ /** Check if a date is a configured working day */
16
+ export declare function isWorkingDay(date: Date, config?: WorkingHoursConfig): boolean;
17
+ /** Check if inside working hours (excluding breaks) */
18
+ export declare function isWorkingTime(date: Date, config?: WorkingHoursConfig): boolean;
19
+ /** Move date forward to next working minute */
20
+ export declare function nextWorkingTime(date: Date, config?: WorkingHoursConfig): Date;
21
+ /** Compute working time (ms) between two dates */
22
+ export declare function workingTimeBetween(start: Date, end: Date, config?: WorkingHoursConfig): number;
23
+ /** Advance by working hours amount (simple iterative approach) */
24
+ export declare function addWorkingHours(start: Date, hours: number, config?: WorkingHoursConfig): Date;
25
+ //# sourceMappingURL=workingHours.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workingHours.d.ts","sourceRoot":"","sources":["../src/workingHours.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAE9B,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,qBAAqB,EAAE,kBAInC,CAAC;AAEF,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,GAAE,kBAA0C,GAAG,OAAO,CAEpG;AAOD,uDAAuD;AACvD,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,GAAE,kBAA0C,GAAG,OAAO,CAUrG;AAED,+CAA+C;AAC/C,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,GAAE,kBAA0C,GAAG,IAAI,CAMpG;AAYD,kDAAkD;AAClD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAE,kBAA0C,GAAG,MAAM,CA+BrH;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,kBAA0C,GAAG,IAAI,CAcpH"}
@@ -0,0 +1,107 @@
1
+ /** Working hours utilities */
2
+ export const DEFAULT_WORKING_HOURS = {
3
+ workingDays: [1, 2, 3, 4, 5],
4
+ hours: { start: 9, end: 17 },
5
+ breaks: [{ start: 12, end: 13 }]
6
+ };
7
+ /** Check if a date is a configured working day */
8
+ export function isWorkingDay(date, config = DEFAULT_WORKING_HOURS) {
9
+ return config.workingDays.includes(date.getDay());
10
+ }
11
+ /** Convert date to fractional hour */
12
+ function toHourFraction(date) {
13
+ return date.getHours() + date.getMinutes() / 60 + date.getSeconds() / 3600;
14
+ }
15
+ /** Check if inside working hours (excluding breaks) */
16
+ export function isWorkingTime(date, config = DEFAULT_WORKING_HOURS) {
17
+ if (!isWorkingDay(date, config))
18
+ return false;
19
+ const h = toHourFraction(date);
20
+ if (h < config.hours.start || h >= config.hours.end)
21
+ return false;
22
+ if (config.breaks) {
23
+ for (const b of config.breaks) {
24
+ if (h >= b.start && h < b.end)
25
+ return false;
26
+ }
27
+ }
28
+ return true;
29
+ }
30
+ /** Move date forward to next working minute */
31
+ export function nextWorkingTime(date, config = DEFAULT_WORKING_HOURS) {
32
+ const d = new Date(date);
33
+ while (!isWorkingTime(d, config)) {
34
+ d.setMinutes(d.getMinutes() + 1);
35
+ }
36
+ return d;
37
+ }
38
+ /** Clamp a date into working window of its day */
39
+ function clampToWorkingWindow(date, config) {
40
+ if (!isWorkingDay(date, config))
41
+ return null;
42
+ const start = new Date(date);
43
+ start.setHours(config.hours.start, 0, 0, 0);
44
+ const end = new Date(date);
45
+ end.setHours(config.hours.end, 0, 0, 0);
46
+ if (date < start)
47
+ return start;
48
+ if (date > end)
49
+ return null;
50
+ return date;
51
+ }
52
+ /** Compute working time (ms) between two dates */
53
+ export function workingTimeBetween(start, end, config = DEFAULT_WORKING_HOURS) {
54
+ if (end <= start)
55
+ return 0;
56
+ let total = 0;
57
+ const cursor = new Date(start);
58
+ while (cursor < end) {
59
+ if (isWorkingDay(cursor, config)) {
60
+ const windowStart = new Date(cursor);
61
+ windowStart.setHours(config.hours.start, 0, 0, 0);
62
+ const windowEnd = new Date(cursor);
63
+ windowEnd.setHours(config.hours.end, 0, 0, 0);
64
+ const rangeStart = cursor > windowStart ? cursor : windowStart;
65
+ const rangeEnd = end < windowEnd ? end : windowEnd;
66
+ if (rangeStart < rangeEnd) {
67
+ let segment = (rangeEnd.getTime() - rangeStart.getTime()) / 1000 / 60 / 60; // hours
68
+ // subtract breaks
69
+ if (config.breaks) {
70
+ for (const b of config.breaks) {
71
+ const bStart = new Date(rangeStart);
72
+ bStart.setHours(Math.floor(b.start), (b.start % 1) * 60, 0, 0);
73
+ const bEnd = new Date(rangeStart);
74
+ bEnd.setHours(Math.floor(b.end), (b.end % 1) * 60, 0, 0);
75
+ const overlapStart = bStart > rangeStart ? bStart : rangeStart;
76
+ const overlapEnd = bEnd < rangeEnd ? bEnd : rangeEnd;
77
+ if (overlapStart < overlapEnd) {
78
+ segment -= (overlapEnd.getTime() - overlapStart.getTime()) / 1000 / 60 / 60;
79
+ }
80
+ }
81
+ }
82
+ total += segment;
83
+ }
84
+ }
85
+ // advance to next day start
86
+ cursor.setHours(24, 0, 0, 0);
87
+ }
88
+ return total * 60 * 60 * 1000; // ms
89
+ }
90
+ /** Advance by working hours amount (simple iterative approach) */
91
+ export function addWorkingHours(start, hours, config = DEFAULT_WORKING_HOURS) {
92
+ if (hours <= 0)
93
+ return new Date(start);
94
+ let remaining = hours * 60; // minutes
95
+ let cursor = new Date(start);
96
+ cursor = nextWorkingTime(cursor, config);
97
+ while (remaining > 0) {
98
+ if (isWorkingTime(cursor, config)) {
99
+ cursor.setMinutes(cursor.getMinutes() + 1);
100
+ remaining -= 1;
101
+ }
102
+ else {
103
+ cursor = nextWorkingTime(cursor, config);
104
+ }
105
+ }
106
+ return cursor;
107
+ }