ts-time-utils 0.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/README.md +590 -1
  2. package/dist/age.d.ts +1 -10
  3. package/dist/age.d.ts.map +1 -1
  4. package/dist/calculate.d.ts.map +1 -1
  5. package/dist/calculate.js +24 -10
  6. package/dist/constants.d.ts +2 -21
  7. package/dist/constants.d.ts.map +1 -1
  8. package/dist/constants.js +12 -13
  9. package/dist/countdown.d.ts +217 -0
  10. package/dist/countdown.d.ts.map +1 -0
  11. package/dist/countdown.js +298 -0
  12. package/dist/dateRange.d.ts +266 -0
  13. package/dist/dateRange.d.ts.map +1 -0
  14. package/dist/dateRange.js +433 -0
  15. package/dist/duration.d.ts +171 -0
  16. package/dist/duration.d.ts.map +1 -0
  17. package/dist/duration.js +382 -0
  18. package/dist/esm/age.d.ts +1 -10
  19. package/dist/esm/age.d.ts.map +1 -1
  20. package/dist/esm/calculate.d.ts.map +1 -1
  21. package/dist/esm/calculate.js +24 -10
  22. package/dist/esm/constants.d.ts +2 -21
  23. package/dist/esm/constants.d.ts.map +1 -1
  24. package/dist/esm/constants.js +12 -13
  25. package/dist/esm/countdown.d.ts +217 -0
  26. package/dist/esm/countdown.d.ts.map +1 -0
  27. package/dist/esm/countdown.js +298 -0
  28. package/dist/esm/dateRange.d.ts +266 -0
  29. package/dist/esm/dateRange.d.ts.map +1 -0
  30. package/dist/esm/dateRange.js +433 -0
  31. package/dist/esm/duration.d.ts +171 -0
  32. package/dist/esm/duration.d.ts.map +1 -0
  33. package/dist/esm/duration.js +382 -0
  34. package/dist/esm/format.d.ts.map +1 -1
  35. package/dist/esm/index.d.ts +14 -6
  36. package/dist/esm/index.d.ts.map +1 -1
  37. package/dist/esm/index.js +16 -0
  38. package/dist/esm/interval.d.ts +3 -6
  39. package/dist/esm/interval.d.ts.map +1 -1
  40. package/dist/esm/locale.d.ts +94 -0
  41. package/dist/esm/locale.d.ts.map +1 -0
  42. package/dist/esm/locale.js +1087 -0
  43. package/dist/esm/naturalLanguage.d.ts +107 -0
  44. package/dist/esm/naturalLanguage.d.ts.map +1 -0
  45. package/dist/esm/naturalLanguage.js +344 -0
  46. package/dist/esm/performance.d.ts +2 -9
  47. package/dist/esm/performance.d.ts.map +1 -1
  48. package/dist/esm/performance.js +7 -8
  49. package/dist/esm/rangePresets.d.ts +7 -8
  50. package/dist/esm/rangePresets.d.ts.map +1 -1
  51. package/dist/esm/rangePresets.js +11 -9
  52. package/dist/esm/recurrence.d.ts +149 -0
  53. package/dist/esm/recurrence.d.ts.map +1 -0
  54. package/dist/esm/recurrence.js +404 -0
  55. package/dist/esm/serialize.d.ts +73 -0
  56. package/dist/esm/serialize.d.ts.map +1 -0
  57. package/dist/esm/serialize.js +365 -0
  58. package/dist/esm/timezone.d.ts +2 -6
  59. package/dist/esm/timezone.d.ts.map +1 -1
  60. package/dist/esm/timezone.js +1 -1
  61. package/dist/esm/types.d.ts +250 -0
  62. package/dist/esm/types.d.ts.map +1 -0
  63. package/dist/esm/types.js +25 -0
  64. package/dist/esm/workingHours.d.ts +4 -13
  65. package/dist/esm/workingHours.d.ts.map +1 -1
  66. package/dist/esm/workingHours.js +3 -1
  67. package/dist/format.d.ts.map +1 -1
  68. package/dist/index.d.ts +14 -6
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +16 -0
  71. package/dist/interval.d.ts +3 -6
  72. package/dist/interval.d.ts.map +1 -1
  73. package/dist/locale.d.ts +94 -0
  74. package/dist/locale.d.ts.map +1 -0
  75. package/dist/locale.js +1087 -0
  76. package/dist/naturalLanguage.d.ts +107 -0
  77. package/dist/naturalLanguage.d.ts.map +1 -0
  78. package/dist/naturalLanguage.js +344 -0
  79. package/dist/performance.d.ts +2 -9
  80. package/dist/performance.d.ts.map +1 -1
  81. package/dist/performance.js +7 -8
  82. package/dist/rangePresets.d.ts +7 -8
  83. package/dist/rangePresets.d.ts.map +1 -1
  84. package/dist/rangePresets.js +11 -9
  85. package/dist/recurrence.d.ts +149 -0
  86. package/dist/recurrence.d.ts.map +1 -0
  87. package/dist/recurrence.js +404 -0
  88. package/dist/serialize.d.ts +73 -0
  89. package/dist/serialize.d.ts.map +1 -0
  90. package/dist/serialize.js +365 -0
  91. package/dist/timezone.d.ts +2 -6
  92. package/dist/timezone.d.ts.map +1 -1
  93. package/dist/timezone.js +1 -1
  94. package/dist/types.d.ts +250 -0
  95. package/dist/types.d.ts.map +1 -0
  96. package/dist/types.js +25 -0
  97. package/dist/workingHours.d.ts +4 -13
  98. package/dist/workingHours.d.ts.map +1 -1
  99. package/dist/workingHours.js +3 -1
  100. package/package.json +67 -3
@@ -0,0 +1,107 @@
1
+ /**
2
+ * @fileoverview Natural language date parsing utilities
3
+ * Provides intelligent parsing of human-readable date strings
4
+ */
5
+ /**
6
+ * Options for natural language parsing
7
+ */
8
+ export interface NaturalParseOptions {
9
+ /** Reference date for relative parsing (defaults to now) */
10
+ referenceDate?: Date;
11
+ /** Preferred time for dates without time specified */
12
+ defaultTime?: {
13
+ hour: number;
14
+ minute: number;
15
+ second?: number;
16
+ };
17
+ /** Locale for language-specific parsing */
18
+ locale?: string;
19
+ /** Whether to use strict parsing */
20
+ strict?: boolean;
21
+ }
22
+ /**
23
+ * Extracted date information from text
24
+ */
25
+ export interface ExtractedDate {
26
+ /** The parsed date */
27
+ date: Date;
28
+ /** The original text that was matched */
29
+ text: string;
30
+ /** Starting position in the original text */
31
+ index: number;
32
+ /** Type of date pattern matched */
33
+ type: 'absolute' | 'relative' | 'range' | 'time';
34
+ /** Confidence score (0-1) */
35
+ confidence: number;
36
+ }
37
+ /**
38
+ * Parses natural language date strings into Date objects
39
+ * @param input - Natural language date string
40
+ * @param options - Parsing options
41
+ * @returns Parsed date or null if unable to parse
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * parseNaturalDate('tomorrow at 3pm');
46
+ * // Date for tomorrow at 15:00
47
+ *
48
+ * parseNaturalDate('next Friday');
49
+ * // Date for next Friday
50
+ *
51
+ * parseNaturalDate('in 2 weeks');
52
+ * // Date 2 weeks from now
53
+ *
54
+ * parseNaturalDate('December 25th');
55
+ * // Date for Dec 25 this year (or next if passed)
56
+ * ```
57
+ */
58
+ export declare function parseNaturalDate(input: string, options?: NaturalParseOptions): Date | null;
59
+ /**
60
+ * Parses a relative time phrase into a Date
61
+ * @param input - Relative time phrase
62
+ * @param referenceDate - Reference date (defaults to now)
63
+ * @returns Parsed date or null
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * parseRelativePhrase('in 2 hours'); // 2 hours from now
68
+ * parseRelativePhrase('5 minutes ago'); // 5 minutes ago
69
+ * parseRelativePhrase('next week'); // 7 days from now
70
+ * ```
71
+ */
72
+ export declare function parseRelativePhrase(input: string, referenceDate?: Date): Date | null;
73
+ /**
74
+ * Extracts all dates from a text string
75
+ * @param text - Text to extract dates from
76
+ * @param options - Extraction options
77
+ * @returns Array of extracted date information
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * const text = "Meeting tomorrow at 3pm and dinner next Friday at 7pm";
82
+ * const dates = extractDatesFromText(text);
83
+ * // [
84
+ * // { date: Date(...), text: 'tomorrow at 3pm', index: 8, ... },
85
+ * // { date: Date(...), text: 'next Friday at 7pm', index: 37, ... }
86
+ * // ]
87
+ * ```
88
+ */
89
+ export declare function extractDatesFromText(text: string, options?: NaturalParseOptions): ExtractedDate[];
90
+ /**
91
+ * Suggests possible dates based on context
92
+ * @param context - Context string to analyze
93
+ * @param options - Parsing options
94
+ * @returns Array of suggested dates with confidence scores
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * suggestDateFromContext('deadline is end of month');
99
+ * // [{ date: Date(last day of current month), confidence: 0.8, ... }]
100
+ * ```
101
+ */
102
+ export declare function suggestDateFromContext(context: string, options?: NaturalParseOptions): Array<{
103
+ date: Date;
104
+ text: string;
105
+ confidence: number;
106
+ }>;
107
+ //# sourceMappingURL=naturalLanguage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naturalLanguage.d.ts","sourceRoot":"","sources":["../src/naturalLanguage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,aAAa,CAAC,EAAE,IAAI,CAAC;IACrB,sDAAsD;IACtD,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;IACjD,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,IAAI,GAAG,IAAI,CA8C9F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,GAAE,IAAiB,GAAG,IAAI,GAAG,IAAI,CA6DhG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,mBAAwB,GAChC,aAAa,EAAE,CAkDjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,mBAAwB,GAChC,KAAK,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAkDzD"}
@@ -0,0 +1,344 @@
1
+ /**
2
+ * @fileoverview Natural language date parsing utilities
3
+ * Provides intelligent parsing of human-readable date strings
4
+ */
5
+ import { addTime } from './calculate.js';
6
+ import { parseRelativeDate } from './parse.js';
7
+ /**
8
+ * Parses natural language date strings into Date objects
9
+ * @param input - Natural language date string
10
+ * @param options - Parsing options
11
+ * @returns Parsed date or null if unable to parse
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * parseNaturalDate('tomorrow at 3pm');
16
+ * // Date for tomorrow at 15:00
17
+ *
18
+ * parseNaturalDate('next Friday');
19
+ * // Date for next Friday
20
+ *
21
+ * parseNaturalDate('in 2 weeks');
22
+ * // Date 2 weeks from now
23
+ *
24
+ * parseNaturalDate('December 25th');
25
+ * // Date for Dec 25 this year (or next if passed)
26
+ * ```
27
+ */
28
+ export function parseNaturalDate(input, options = {}) {
29
+ const { referenceDate = new Date(), defaultTime } = options;
30
+ const normalized = input.toLowerCase().trim();
31
+ // Try relative phrase parser first (handles "next week", "last month", etc.)
32
+ const relativePhraseResult = parseRelativePhrase(input, referenceDate);
33
+ if (relativePhraseResult)
34
+ return relativePhraseResult;
35
+ // Try existing relative date parser
36
+ const relativeResult = parseRelativeDate(input);
37
+ if (relativeResult)
38
+ return relativeResult;
39
+ // Common absolute patterns
40
+ const absolutePatterns = [
41
+ // "next Friday", "last Monday"
42
+ /^(next|last|this)\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/,
43
+ // "Friday", "Monday" (interpreted as next occurrence)
44
+ /^(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/,
45
+ // "tomorrow at 3pm", "today at noon"
46
+ /^(today|tomorrow|yesterday)\s+at\s+(.+)$/,
47
+ // "3pm today", "noon tomorrow"
48
+ /^(.+?)\s+(today|tomorrow|yesterday)$/,
49
+ // "in 2 weeks", "in 3 days"
50
+ /^in\s+(\d+)\s+(minute|minutes|hour|hours|day|days|week|weeks|month|months|year|years)$/,
51
+ // "2 weeks from now", "3 days ago"
52
+ /^(\d+)\s+(minute|minutes|hour|hours|day|days|week|weeks|month|months|year|years)\s+(from now|ago)$/,
53
+ // "December 25", "Dec 25", "25 December"
54
+ /^(january|february|march|april|may|june|july|august|september|october|november|december|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\s+(\d{1,2})(st|nd|rd|th)?$/,
55
+ /^(\d{1,2})(st|nd|rd|th)?\s+(january|february|march|april|may|june|july|august|september|october|november|december|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)$/,
56
+ ];
57
+ // Check each pattern
58
+ for (const pattern of absolutePatterns) {
59
+ const match = normalized.match(pattern);
60
+ if (match) {
61
+ return parseMatchedPattern(match, referenceDate, defaultTime);
62
+ }
63
+ }
64
+ // Try standard Date parsing as fallback
65
+ const standardDate = new Date(input);
66
+ if (!isNaN(standardDate.getTime())) {
67
+ return standardDate;
68
+ }
69
+ return null;
70
+ }
71
+ /**
72
+ * Parses a relative time phrase into a Date
73
+ * @param input - Relative time phrase
74
+ * @param referenceDate - Reference date (defaults to now)
75
+ * @returns Parsed date or null
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * parseRelativePhrase('in 2 hours'); // 2 hours from now
80
+ * parseRelativePhrase('5 minutes ago'); // 5 minutes ago
81
+ * parseRelativePhrase('next week'); // 7 days from now
82
+ * ```
83
+ */
84
+ export function parseRelativePhrase(input, referenceDate = new Date()) {
85
+ const normalized = input.toLowerCase().trim();
86
+ // "in X units"
87
+ const inPattern = /^in\s+(\d+)\s+(millisecond|milliseconds|second|seconds|minute|minutes|hour|hours|day|days|week|weeks|month|months|year|years)$/;
88
+ let match = normalized.match(inPattern);
89
+ if (match) {
90
+ const amount = parseInt(match[1], 10);
91
+ const unit = normalizeUnit(match[2]);
92
+ return addTime(referenceDate, amount, unit);
93
+ }
94
+ // "X units ago"
95
+ const agoPattern = /^(\d+)\s+(millisecond|milliseconds|second|seconds|minute|minutes|hour|hours|day|days|week|weeks|month|months|year|years)\s+ago$/;
96
+ match = normalized.match(agoPattern);
97
+ if (match) {
98
+ const amount = parseInt(match[1], 10);
99
+ const unit = normalizeUnit(match[2]);
100
+ return addTime(referenceDate, -amount, unit);
101
+ }
102
+ // "X units from now"
103
+ const fromNowPattern = /^(\d+)\s+(millisecond|milliseconds|second|seconds|minute|minutes|hour|hours|day|days|week|weeks|month|months|year|years)\s+from\s+now$/;
104
+ match = normalized.match(fromNowPattern);
105
+ if (match) {
106
+ const amount = parseInt(match[1], 10);
107
+ const unit = normalizeUnit(match[2]);
108
+ return addTime(referenceDate, amount, unit);
109
+ }
110
+ // Common shortcuts - use switch/case to properly use the referenceDate parameter
111
+ switch (normalized) {
112
+ case 'now':
113
+ return new Date(referenceDate);
114
+ case 'today': {
115
+ const d = new Date(referenceDate);
116
+ d.setHours(0, 0, 0, 0);
117
+ return d;
118
+ }
119
+ case 'tomorrow':
120
+ return addTime(referenceDate, 1, 'day');
121
+ case 'yesterday':
122
+ return addTime(referenceDate, -1, 'day');
123
+ case 'next week':
124
+ return addTime(referenceDate, 1, 'week');
125
+ case 'last week':
126
+ return addTime(referenceDate, -1, 'week');
127
+ case 'next month':
128
+ return addTime(referenceDate, 1, 'month');
129
+ case 'last month':
130
+ return addTime(referenceDate, -1, 'month');
131
+ case 'next year':
132
+ return addTime(referenceDate, 1, 'year');
133
+ case 'last year':
134
+ return addTime(referenceDate, -1, 'year');
135
+ default:
136
+ return null;
137
+ }
138
+ }
139
+ /**
140
+ * Extracts all dates from a text string
141
+ * @param text - Text to extract dates from
142
+ * @param options - Extraction options
143
+ * @returns Array of extracted date information
144
+ *
145
+ * @example
146
+ * ```ts
147
+ * const text = "Meeting tomorrow at 3pm and dinner next Friday at 7pm";
148
+ * const dates = extractDatesFromText(text);
149
+ * // [
150
+ * // { date: Date(...), text: 'tomorrow at 3pm', index: 8, ... },
151
+ * // { date: Date(...), text: 'next Friday at 7pm', index: 37, ... }
152
+ * // ]
153
+ * ```
154
+ */
155
+ export function extractDatesFromText(text, options = {}) {
156
+ const { referenceDate = new Date() } = options;
157
+ const results = [];
158
+ // Patterns to match
159
+ const patterns = [
160
+ // Relative dates
161
+ /\b(tomorrow|yesterday|today)\b/gi,
162
+ /\b(next|last|this)\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday|week|month|year)\b/gi,
163
+ /\bin\s+\d+\s+(minute|minutes|hour|hours|day|days|week|weeks|month|months|year|years)\b/gi,
164
+ /\b\d+\s+(minute|minutes|hour|hours|day|days|week|weeks|month|months|year|years)\s+(ago|from now)\b/gi,
165
+ // Absolute dates
166
+ /\b(january|february|march|april|may|june|july|august|september|october|november|december|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\s+\d{1,2}(st|nd|rd|th)?\b/gi,
167
+ /\b\d{1,2}(st|nd|rd|th)?\s+(of\s+)?(january|february|march|april|may|june|july|august|september|october|november|december|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\b/gi,
168
+ // Date formats
169
+ /\b\d{1,2}[\/\-\.]\d{1,2}[\/\-\.]\d{2,4}\b/g,
170
+ /\b\d{4}[\/\-\.]\d{1,2}[\/\-\.]\d{1,2}\b/g,
171
+ // Time patterns (when found with dates)
172
+ /\bat\s+\d{1,2}(:\d{2})?\s*(am|pm|AM|PM)?\b/gi,
173
+ ];
174
+ const processed = new Set();
175
+ for (const pattern of patterns) {
176
+ let match;
177
+ while ((match = pattern.exec(text)) !== null) {
178
+ const matchedText = match[0];
179
+ const index = match.index;
180
+ // Skip if already processed
181
+ if (processed.has(`${index}-${matchedText}`))
182
+ continue;
183
+ processed.add(`${index}-${matchedText}`);
184
+ // Try to parse the matched text
185
+ const parsed = parseNaturalDate(matchedText, { referenceDate });
186
+ if (parsed) {
187
+ results.push({
188
+ date: parsed,
189
+ text: matchedText,
190
+ index,
191
+ type: determineType(matchedText),
192
+ confidence: calculateConfidence(matchedText)
193
+ });
194
+ }
195
+ }
196
+ }
197
+ // Sort by index (order in text)
198
+ return results.sort((a, b) => a.index - b.index);
199
+ }
200
+ /**
201
+ * Suggests possible dates based on context
202
+ * @param context - Context string to analyze
203
+ * @param options - Parsing options
204
+ * @returns Array of suggested dates with confidence scores
205
+ *
206
+ * @example
207
+ * ```ts
208
+ * suggestDateFromContext('deadline is end of month');
209
+ * // [{ date: Date(last day of current month), confidence: 0.8, ... }]
210
+ * ```
211
+ */
212
+ export function suggestDateFromContext(context, options = {}) {
213
+ const { referenceDate = new Date() } = options;
214
+ const suggestions = [];
215
+ const normalized = context.toLowerCase();
216
+ // End of month
217
+ if (normalized.includes('end of month') || normalized.includes('eom')) {
218
+ const date = new Date(referenceDate.getFullYear(), referenceDate.getMonth() + 1, 0);
219
+ suggestions.push({ date, text: 'end of month', confidence: 0.85 });
220
+ }
221
+ // Beginning of month
222
+ if (normalized.includes('beginning of month') || normalized.includes('start of month')) {
223
+ const date = new Date(referenceDate.getFullYear(), referenceDate.getMonth(), 1);
224
+ suggestions.push({ date, text: 'beginning of month', confidence: 0.85 });
225
+ }
226
+ // End of year
227
+ if (normalized.includes('end of year') || normalized.includes('eoy')) {
228
+ const date = new Date(referenceDate.getFullYear(), 11, 31);
229
+ suggestions.push({ date, text: 'end of year', confidence: 0.85 });
230
+ }
231
+ // Beginning of year
232
+ if (normalized.includes('beginning of year') || normalized.includes('start of year')) {
233
+ const date = new Date(referenceDate.getFullYear(), 0, 1);
234
+ suggestions.push({ date, text: 'beginning of year', confidence: 0.85 });
235
+ }
236
+ // End of week
237
+ if (normalized.includes('end of week') || normalized.includes('eow')) {
238
+ const date = new Date(referenceDate);
239
+ const day = date.getDay();
240
+ const diff = 6 - day; // Saturday
241
+ date.setDate(date.getDate() + diff);
242
+ suggestions.push({ date, text: 'end of week', confidence: 0.85 });
243
+ }
244
+ // Extract any explicit dates
245
+ const extracted = extractDatesFromText(context, options);
246
+ for (const item of extracted) {
247
+ suggestions.push({
248
+ date: item.date,
249
+ text: item.text,
250
+ confidence: item.confidence
251
+ });
252
+ }
253
+ // Sort by confidence
254
+ return suggestions.sort((a, b) => b.confidence - a.confidence);
255
+ }
256
+ // Helper functions
257
+ function parseMatchedPattern(match, referenceDate, defaultTime) {
258
+ const pattern = match[0];
259
+ // Weekday patterns
260
+ if (pattern.includes('monday') || pattern.includes('tuesday') ||
261
+ pattern.includes('wednesday') || pattern.includes('thursday') ||
262
+ pattern.includes('friday') || pattern.includes('saturday') ||
263
+ pattern.includes('sunday')) {
264
+ const weekdayMap = {
265
+ 'sunday': 0, 'monday': 1, 'tuesday': 2, 'wednesday': 3,
266
+ 'thursday': 4, 'friday': 5, 'saturday': 6
267
+ };
268
+ const weekday = Object.keys(weekdayMap).find(day => pattern.includes(day));
269
+ if (!weekday)
270
+ return null;
271
+ const targetDay = weekdayMap[weekday];
272
+ const currentDay = referenceDate.getDay();
273
+ let daysToAdd = targetDay - currentDay;
274
+ if (pattern.includes('next')) {
275
+ if (daysToAdd <= 0)
276
+ daysToAdd += 7;
277
+ }
278
+ else if (pattern.includes('last')) {
279
+ if (daysToAdd >= 0)
280
+ daysToAdd -= 7;
281
+ }
282
+ else {
283
+ // "this" or just the weekday name - go to next occurrence
284
+ if (daysToAdd <= 0)
285
+ daysToAdd += 7;
286
+ }
287
+ return addTime(referenceDate, daysToAdd, 'day');
288
+ }
289
+ // "in X units" pattern
290
+ if (match[1] && match[2]) {
291
+ const amount = parseInt(match[1], 10);
292
+ const unit = normalizeUnit(match[2]);
293
+ if (match[3] === 'ago') {
294
+ return addTime(referenceDate, -amount, unit);
295
+ }
296
+ return addTime(referenceDate, amount, unit);
297
+ }
298
+ return null;
299
+ }
300
+ function normalizeUnit(unit) {
301
+ const normalized = unit.toLowerCase().replace(/s$/, '');
302
+ switch (normalized) {
303
+ case 'millisecond': return 'millisecond';
304
+ case 'second': return 'second';
305
+ case 'minute': return 'minute';
306
+ case 'hour': return 'hour';
307
+ case 'day': return 'day';
308
+ case 'week': return 'week';
309
+ case 'month': return 'month';
310
+ case 'year': return 'year';
311
+ default: return 'day';
312
+ }
313
+ }
314
+ function determineType(text) {
315
+ const lower = text.toLowerCase();
316
+ if (lower.includes('ago') || lower.includes('from now') || lower.includes('in ')) {
317
+ return 'relative';
318
+ }
319
+ if (lower.includes('to') || lower.includes(' - ') || lower.includes('between')) {
320
+ return 'range';
321
+ }
322
+ if (lower.includes('at ') || lower.includes('am') || lower.includes('pm') || /\d{1,2}:\d{2}/.test(lower)) {
323
+ return 'time';
324
+ }
325
+ return 'absolute';
326
+ }
327
+ function calculateConfidence(text) {
328
+ const lower = text.toLowerCase();
329
+ let confidence = 0.5; // Base confidence
330
+ // Higher confidence for specific patterns
331
+ if (lower.includes('tomorrow') || lower.includes('yesterday') || lower.includes('today')) {
332
+ confidence += 0.4;
333
+ }
334
+ if (/\d{4}/.test(text)) { // Has year
335
+ confidence += 0.2;
336
+ }
337
+ if (/\d{1,2}:\d{2}/.test(text)) { // Has time
338
+ confidence += 0.15;
339
+ }
340
+ if (lower.includes('next') || lower.includes('last')) {
341
+ confidence += 0.1;
342
+ }
343
+ return Math.min(1.0, confidence);
344
+ }
@@ -91,16 +91,9 @@ export declare function measureTime<T>(fn: () => T): [T, number];
91
91
  */
92
92
  export declare function measureAsync<T>(fn: () => Promise<T>): Promise<[T, number]>;
93
93
  /**
94
- * Benchmark result interface
94
+ * Performance measurement and async utilities
95
95
  */
96
- export interface BenchmarkResult {
97
- totalTime: number;
98
- averageTime: number;
99
- minTime: number;
100
- maxTime: number;
101
- iterations: number;
102
- opsPerSecond: number;
103
- }
96
+ import type { BenchmarkResult } from './types.js';
104
97
  /**
105
98
  * Benchmark a function by running it multiple times
106
99
  * @param fn - function to benchmark
@@ -1 +1 @@
1
- {"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../src/performance.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,EACvB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,EAAE,EAAE,MAAM,EACV,cAAc,SAAwB,GACrC,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACxD,EAAE,EAAE,CAAC,EACL,KAAK,EAAE,MAAM,GACZ,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAOlC;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACxD,EAAE,EAAE,CAAC,EACL,KAAK,EAAE,MAAM,GACZ,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAUlC;AAED;;;;;;GAMG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAC3B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,WAAW,GAAE,MAAU,EACvB,SAAS,GAAE,MAAa,EACxB,QAAQ,GAAE,MAAc,GACvB,OAAO,CAAC,CAAC,CAAC,CAwBZ;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,UAAU,CAAuB;IAEzC;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;OAEG;IACH,IAAI,IAAI,MAAM;IAed;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;OAEG;IACH,MAAM,IAAI,IAAI;IAQd;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,UAAU,IAAI,MAAM;IAepB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,QAAQ,IAAI,OAAO;CAGpB;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,SAAS,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAKvD;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAKhF;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,UAAU,GAAE,MAAa,GAAG,eAAe,CAsBpF"}
1
+ {"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../src/performance.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,EACvB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,EAAE,EAAE,MAAM,EACV,cAAc,SAAwB,GACrC,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACxD,EAAE,EAAE,CAAC,EACL,KAAK,EAAE,MAAM,GACZ,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAOlC;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACxD,EAAE,EAAE,CAAC,EACL,KAAK,EAAE,MAAM,GACZ,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAUlC;AAED;;;;;;GAMG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAC3B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,WAAW,GAAE,MAAU,EACvB,SAAS,GAAE,MAAa,EACxB,QAAQ,GAAE,MAAc,GACvB,OAAO,CAAC,CAAC,CAAC,CAwBZ;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,UAAU,CAAuB;IAEzC;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;OAEG;IACH,IAAI,IAAI,MAAM;IAed;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;OAEG;IACH,MAAM,IAAI,IAAI;IAQd;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,UAAU,IAAI,MAAM;IAepB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,QAAQ,IAAI,OAAO;CAGpB;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,SAAS,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAKvD;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAKhF;AAED;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,UAAU,GAAE,MAAa,GAAG,eAAe,CAqBpF"}
@@ -207,16 +207,15 @@ export function benchmark(fn, iterations = 1000) {
207
207
  times.push(elapsed);
208
208
  }
209
209
  const totalTime = times.reduce((sum, time) => sum + time, 0);
210
- const averageTime = totalTime / iterations;
211
- const minTime = Math.min(...times);
212
- const maxTime = Math.max(...times);
213
- const opsPerSecond = 1000 / averageTime;
210
+ const average = totalTime / iterations;
211
+ const min = Math.min(...times);
212
+ const max = Math.max(...times);
214
213
  return {
215
214
  totalTime,
216
- averageTime,
217
- minTime,
218
- maxTime,
215
+ average,
216
+ min,
217
+ max,
219
218
  iterations,
220
- opsPerSecond
219
+ total: totalTime
221
220
  };
222
221
  }
@@ -1,8 +1,7 @@
1
- /** Predefined date range helpers (returns [start,end]) */
2
- export interface DateRange {
3
- start: Date;
4
- end: Date;
5
- }
1
+ /**
2
+ * Predefined date range helpers for common time periods
3
+ */
4
+ import type { DateRange } from './types.js';
6
5
  export declare function today(now?: Date): DateRange;
7
6
  export declare function yesterday(now?: Date): DateRange;
8
7
  export declare function tomorrow(now?: Date): DateRange;
@@ -18,9 +17,9 @@ export declare function thisYear(now?: Date): DateRange;
18
17
  export declare function lastYear(now?: Date): DateRange;
19
18
  export declare function nextYear(now?: Date): DateRange;
20
19
  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;
20
+ export declare function quarterRange(now?: Date): DateRange;
21
+ export declare function lastQuarter(now?: Date): DateRange;
22
+ export declare function nextQuarter(now?: Date): DateRange;
24
23
  /** Map of preset functions for dynamic access */
25
24
  export declare const RANGE_PRESETS: {
26
25
  today: typeof today;
@@ -1 +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"}
1
+ {"version":3,"file":"rangePresets.d.ts","sourceRoot":"","sources":["../src/rangePresets.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAQ5C,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,GAAG,OAAa,GAAG,SAAS,CAKxD;AAED,wBAAgB,WAAW,CAAC,GAAG,OAAa,GAAG,SAAS,CAKvD;AAED,wBAAgB,WAAW,CAAC,GAAG,OAAa,GAAG,SAAS,CAKvD;AAED,iDAAiD;AACjD,eAAO,MAAM,aAAa;;;;sBAEN,IAAI;uBACH,IAAI;sBACL,IAAI;;;;;;;;;;;;;CAKvB,CAAC"}
@@ -1,4 +1,6 @@
1
- /** Predefined date range helpers (returns [start,end]) */
1
+ /**
2
+ * Predefined date range helpers for common time periods
3
+ */
2
4
  function todayRange(now = new Date()) {
3
5
  const start = new Date(now);
4
6
  start.setHours(0, 0, 0, 0);
@@ -93,20 +95,20 @@ export function rollingWindowDays(days, now = new Date()) {
93
95
  start.setDate(start.getDate() - days);
94
96
  return { start, end };
95
97
  }
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);
98
+ export function quarterRange(now = new Date()) {
99
+ const q = Math.floor(now.getMonth() / 3); // 0-3
100
+ const start = new Date(now.getFullYear(), q * 3, 1);
101
+ const end = new Date(now.getFullYear(), q * 3 + 3, 1);
100
102
  return { start, end };
101
103
  }
102
- export function lastQuarter(date = new Date()) {
103
- const q = quarterRange(date);
104
+ export function lastQuarter(now = new Date()) {
105
+ const q = quarterRange(now);
104
106
  q.start.setMonth(q.start.getMonth() - 3);
105
107
  q.end.setMonth(q.end.getMonth() - 3);
106
108
  return q;
107
109
  }
108
- export function nextQuarter(date = new Date()) {
109
- const q = quarterRange(date);
110
+ export function nextQuarter(now = new Date()) {
111
+ const q = quarterRange(now);
110
112
  q.start.setMonth(q.start.getMonth() + 3);
111
113
  q.end.setMonth(q.end.getMonth() + 3);
112
114
  return q;