ts-time-utils 1.0.0 → 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.
- package/README.md +226 -1
- package/dist/calculate.d.ts.map +1 -1
- package/dist/calculate.js +24 -10
- package/dist/countdown.d.ts +217 -0
- package/dist/countdown.d.ts.map +1 -0
- package/dist/countdown.js +298 -0
- package/dist/dateRange.d.ts +266 -0
- package/dist/dateRange.d.ts.map +1 -0
- package/dist/dateRange.js +433 -0
- package/dist/esm/calculate.d.ts.map +1 -1
- package/dist/esm/calculate.js +24 -10
- package/dist/esm/countdown.d.ts +217 -0
- package/dist/esm/countdown.d.ts.map +1 -0
- package/dist/esm/countdown.js +298 -0
- package/dist/esm/dateRange.d.ts +266 -0
- package/dist/esm/dateRange.d.ts.map +1 -0
- package/dist/esm/dateRange.js +433 -0
- package/dist/esm/index.d.ts +5 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +8 -0
- package/dist/esm/naturalLanguage.d.ts +107 -0
- package/dist/esm/naturalLanguage.d.ts.map +1 -0
- package/dist/esm/naturalLanguage.js +344 -0
- package/dist/esm/recurrence.d.ts +149 -0
- package/dist/esm/recurrence.d.ts.map +1 -0
- package/dist/esm/recurrence.js +404 -0
- package/dist/esm/types.d.ts +21 -0
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/naturalLanguage.d.ts +107 -0
- package/dist/naturalLanguage.d.ts.map +1 -0
- package/dist/naturalLanguage.js +344 -0
- package/dist/recurrence.d.ts +149 -0
- package/dist/recurrence.d.ts.map +1 -0
- package/dist/recurrence.js +404 -0
- package/dist/types.d.ts +21 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +30 -2
package/dist/esm/index.d.ts
CHANGED
|
@@ -16,6 +16,10 @@ export { today, yesterday, tomorrow, lastNDays, nextNDays, thisWeek, lastWeek, n
|
|
|
16
16
|
export { Duration, createDuration, isValidDuration, parseDurationString, formatDurationString, maxDuration, minDuration, sumDurations, averageDuration } from './duration.js';
|
|
17
17
|
export { serializeDate, deserializeDate, createDateReviver, createDateReplacer, parseISOString, toEpochTimestamp, fromEpochTimestamp, createEpochTimestamp, toDateObject, fromDateObject, isValidISODateString, isValidEpochTimestamp, cloneDate, datesEqual, now, parseJSONWithDates, stringifyWithDates } from './serialize.js';
|
|
18
18
|
export { registerLocale, getLocaleConfig, getSupportedLocales, formatRelativeTime, formatDateLocale, formatTimeLocale, formatDateTimeLocale, getMonthNames, getDayNames, getFirstDayOfWeek, isLocaleSupported, getBestMatchingLocale, detectLocale, convertRelativeTime, detectLocaleFromRelativeTime, convertFormatPattern, convertFormattedDate, convertRelativeTimeArray, compareLocaleFormats } from './locale.js';
|
|
19
|
+
export { createRecurrence, getNextOccurrence, getOccurrencesBetween, isRecurrenceDate, isValidRecurrenceRule, recurrenceToString } from './recurrence.js';
|
|
20
|
+
export { createCountdown, getRemainingTime, formatCountdown, isExpired, getProgressPercentage, getTimeUntil, createDeadline, type Countdown, type RemainingTime, type CountdownOptions } from './countdown.js';
|
|
21
|
+
export { dateRangeOverlap, hasOverlappingRanges, mergeDateRanges, findGaps, splitRange, containsDate, getIntersection, getUnion, subtractRange, getRangeDuration, expandRange, shrinkRange, rangeContains, sortRanges } from './dateRange.js';
|
|
22
|
+
export { parseNaturalDate, parseRelativePhrase, extractDatesFromText, suggestDateFromContext, type NaturalParseOptions, type ExtractedDate } from './naturalLanguage.js';
|
|
19
23
|
export { MILLISECONDS_PER_SECOND, MILLISECONDS_PER_MINUTE, MILLISECONDS_PER_HOUR, MILLISECONDS_PER_DAY, MILLISECONDS_PER_WEEK, MILLISECONDS_PER_MONTH, MILLISECONDS_PER_YEAR, SECONDS_PER_MINUTE, SECONDS_PER_HOUR, SECONDS_PER_DAY, SECONDS_PER_WEEK, type TimeUnit, type FormatOptions } from './constants.js';
|
|
20
|
-
export type { DateInput, DateRange, ParseOptions, WorkingHoursConfig, AgeResult, ZonedTime, Interval, BenchmarkResult, RecurrencePattern, LocaleFormatOptions, BusinessConfig, DateValidator, DateTransformer, TimeUtilsError, ParseError, ValidationError, DurationUnit, DurationInput, DurationComparison, SerializationOptions, DateObject, EpochTimestamp, SupportedLocale, LocaleConfig, RelativeTimeOptions, RelativeTimeUnit } from './types.js';
|
|
24
|
+
export type { DateInput, DateRange, ParseOptions, WorkingHoursConfig, AgeResult, ZonedTime, Interval, BenchmarkResult, RecurrencePattern, RecurrenceRule, RecurrenceFrequency, LocaleFormatOptions, BusinessConfig, DateValidator, DateTransformer, TimeUtilsError, ParseError, ValidationError, DurationUnit, DurationInput, DurationComparison, SerializationOptions, DateObject, EpochTimestamp, SupportedLocale, LocaleConfig, RelativeTimeOptions, RelativeTimeUnit } from './types.js';
|
|
21
25
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/index.js
CHANGED
|
@@ -32,5 +32,13 @@ export { serializeDate, deserializeDate, createDateReviver, createDateReplacer,
|
|
|
32
32
|
export { registerLocale, getLocaleConfig, getSupportedLocales, formatRelativeTime, formatDateLocale, formatTimeLocale, formatDateTimeLocale, getMonthNames, getDayNames, getFirstDayOfWeek, isLocaleSupported, getBestMatchingLocale, detectLocale,
|
|
33
33
|
// Conversion utilities
|
|
34
34
|
convertRelativeTime, detectLocaleFromRelativeTime, convertFormatPattern, convertFormattedDate, convertRelativeTimeArray, compareLocaleFormats } from './locale.js';
|
|
35
|
+
// Recurrence utilities
|
|
36
|
+
export { createRecurrence, getNextOccurrence, getOccurrencesBetween, isRecurrenceDate, isValidRecurrenceRule, recurrenceToString } from './recurrence.js';
|
|
37
|
+
// Countdown utilities
|
|
38
|
+
export { createCountdown, getRemainingTime, formatCountdown, isExpired, getProgressPercentage, getTimeUntil, createDeadline } from './countdown.js';
|
|
39
|
+
// Date range utilities
|
|
40
|
+
export { dateRangeOverlap, hasOverlappingRanges, mergeDateRanges, findGaps, splitRange, containsDate, getIntersection, getUnion, subtractRange, getRangeDuration, expandRange, shrinkRange, rangeContains, sortRanges } from './dateRange.js';
|
|
41
|
+
// Natural language parsing utilities
|
|
42
|
+
export { parseNaturalDate, parseRelativePhrase, extractDatesFromText, suggestDateFromContext } from './naturalLanguage.js';
|
|
35
43
|
// Constants and types
|
|
36
44
|
export { MILLISECONDS_PER_SECOND, MILLISECONDS_PER_MINUTE, MILLISECONDS_PER_HOUR, MILLISECONDS_PER_DAY, MILLISECONDS_PER_WEEK, MILLISECONDS_PER_MONTH, MILLISECONDS_PER_YEAR, SECONDS_PER_MINUTE, SECONDS_PER_HOUR, SECONDS_PER_DAY, SECONDS_PER_WEEK } from './constants.js';
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Recurring events and pattern-based date generation utilities
|
|
3
|
+
* Provides RRULE-inspired recurrence patterns for creating repeating events
|
|
4
|
+
*/
|
|
5
|
+
import type { DateInput, RecurrenceRule } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Creates a recurrence pattern generator
|
|
8
|
+
* @param rule - The recurrence rule defining the pattern
|
|
9
|
+
* @returns An object with methods to work with the recurrence
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* // Daily recurrence
|
|
14
|
+
* const daily = createRecurrence({
|
|
15
|
+
* frequency: 'daily',
|
|
16
|
+
* interval: 1,
|
|
17
|
+
* startDate: new Date('2024-01-01')
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* // Weekly on Monday and Wednesday
|
|
21
|
+
* const weekly = createRecurrence({
|
|
22
|
+
* frequency: 'weekly',
|
|
23
|
+
* interval: 1,
|
|
24
|
+
* startDate: new Date('2024-01-01'),
|
|
25
|
+
* byWeekday: [1, 3] // Monday = 1, Wednesday = 3
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* // Monthly on the 15th
|
|
29
|
+
* const monthly = createRecurrence({
|
|
30
|
+
* frequency: 'monthly',
|
|
31
|
+
* interval: 1,
|
|
32
|
+
* startDate: new Date('2024-01-01'),
|
|
33
|
+
* byMonthDay: [15]
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function createRecurrence(rule: RecurrenceRule): {
|
|
38
|
+
rule: RecurrenceRule;
|
|
39
|
+
getNextOccurrence: (afterDate?: DateInput) => Date | null;
|
|
40
|
+
getOccurrencesBetween: (start: DateInput, end: DateInput, limit?: number) => Date[];
|
|
41
|
+
isRecurrenceDate: (date: DateInput) => boolean;
|
|
42
|
+
getAllOccurrences: (limit?: number) => Date[];
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Gets the next occurrence of a recurring event after a specified date
|
|
46
|
+
* @param rule - The recurrence rule
|
|
47
|
+
* @param afterDate - Date to find next occurrence after (defaults to now)
|
|
48
|
+
* @returns The next occurrence date, or null if no more occurrences
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* const rule = {
|
|
53
|
+
* frequency: 'daily',
|
|
54
|
+
* interval: 2,
|
|
55
|
+
* startDate: new Date('2024-01-01')
|
|
56
|
+
* };
|
|
57
|
+
*
|
|
58
|
+
* const next = getNextOccurrence(rule, new Date('2024-01-05'));
|
|
59
|
+
* // Returns Date('2024-01-07') - every other day
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare function getNextOccurrence(rule: RecurrenceRule, afterDate?: DateInput): Date | null;
|
|
63
|
+
/**
|
|
64
|
+
* Gets all occurrences of a recurring event between two dates
|
|
65
|
+
* @param rule - The recurrence rule
|
|
66
|
+
* @param start - Start date of the range
|
|
67
|
+
* @param end - End date of the range
|
|
68
|
+
* @param limit - Maximum number of occurrences to return (default: 1000)
|
|
69
|
+
* @returns Array of dates that match the recurrence pattern
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* const rule = {
|
|
74
|
+
* frequency: 'weekly',
|
|
75
|
+
* interval: 1,
|
|
76
|
+
* startDate: new Date('2024-01-01'),
|
|
77
|
+
* byWeekday: [1, 5] // Monday and Friday
|
|
78
|
+
* };
|
|
79
|
+
*
|
|
80
|
+
* const occurrences = getOccurrencesBetween(
|
|
81
|
+
* rule,
|
|
82
|
+
* new Date('2024-01-01'),
|
|
83
|
+
* new Date('2024-01-31')
|
|
84
|
+
* );
|
|
85
|
+
* // Returns all Mondays and Fridays in January 2024
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export declare function getOccurrencesBetween(rule: RecurrenceRule, start: DateInput, end: DateInput, limit?: number): Date[];
|
|
89
|
+
/**
|
|
90
|
+
* Checks if a specific date matches a recurrence rule
|
|
91
|
+
* @param date - The date to check
|
|
92
|
+
* @param rule - The recurrence rule
|
|
93
|
+
* @returns True if the date matches the recurrence pattern
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* const rule = {
|
|
98
|
+
* frequency: 'weekly',
|
|
99
|
+
* interval: 1,
|
|
100
|
+
* startDate: new Date('2024-01-01'),
|
|
101
|
+
* byWeekday: [1] // Mondays only
|
|
102
|
+
* };
|
|
103
|
+
*
|
|
104
|
+
* isRecurrenceDate(new Date('2024-01-08'), rule); // true (Monday)
|
|
105
|
+
* isRecurrenceDate(new Date('2024-01-09'), rule); // false (Tuesday)
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export declare function isRecurrenceDate(date: DateInput, rule: RecurrenceRule): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Validates a recurrence rule
|
|
111
|
+
* @param rule - The recurrence rule to validate
|
|
112
|
+
* @returns True if the rule is valid
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* isValidRecurrenceRule({
|
|
117
|
+
* frequency: 'daily',
|
|
118
|
+
* interval: 1,
|
|
119
|
+
* startDate: new Date()
|
|
120
|
+
* }); // true
|
|
121
|
+
*
|
|
122
|
+
* isValidRecurrenceRule({
|
|
123
|
+
* frequency: 'daily',
|
|
124
|
+
* interval: 0, // Invalid
|
|
125
|
+
* startDate: new Date()
|
|
126
|
+
* }); // false
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export declare function isValidRecurrenceRule(rule: Partial<RecurrenceRule>): boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Converts a recurrence rule to a human-readable string
|
|
132
|
+
* @param rule - The recurrence rule
|
|
133
|
+
* @returns A human-readable description
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* const rule = {
|
|
138
|
+
* frequency: 'weekly',
|
|
139
|
+
* interval: 2,
|
|
140
|
+
* startDate: new Date('2024-01-01'),
|
|
141
|
+
* byWeekday: [1, 3, 5]
|
|
142
|
+
* };
|
|
143
|
+
*
|
|
144
|
+
* recurrenceToString(rule);
|
|
145
|
+
* // "Every 2 weeks on Monday, Wednesday, Friday"
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export declare function recurrenceToString(rule: RecurrenceRule): string;
|
|
149
|
+
//# sourceMappingURL=recurrence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recurrence.d.ts","sourceRoot":"","sources":["../../src/recurrence.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAuB,MAAM,YAAY,CAAC;AAGjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc;;oCAKjB,SAAS;mCACV,SAAS,OAAO,SAAS,UAAU,MAAM;6BAE/C,SAAS;;EAqBrC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAyC1F;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,SAAS,EAChB,GAAG,EAAE,SAAS,EACd,KAAK,SAAO,GACX,IAAI,EAAE,CA6BR;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAW/E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAgC5E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CA6C/D"}
|