Skip to content

Commit b505b94

Browse files
Merge pull request #124 from knowledgecode/develop
feat: add defaultDate option to parse/isValid for partial date string support
2 parents 80dec7b + 702ef4c commit b505b94

13 files changed

Lines changed: 605 additions & 504 deletions

File tree

docs/api/format.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,18 @@ For available plugins, see the [`plugins`](#plugins) option in FormatterOptions.
119119

120120
The `FormatterOptions` object allows you to customize the formatting behavior:
121121

122+
```typescript
123+
interface FormatterOptions {
124+
locale?: Locale;
125+
timeZone?: TimeZone | string;
126+
numeral?: Numeral;
127+
calendar?: 'gregory' | 'buddhist';
128+
hour12?: 'h11' | 'h12';
129+
hour24?: 'h23' | 'h24';
130+
plugins?: FormatterPlugin[];
131+
}
132+
```
133+
122134
### locale
123135

124136
**Type**: `Locale`

docs/api/index.md

Lines changed: 0 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -73,88 +73,6 @@ format(new Date(), 'YYYY年M月D日(ddd) HH:mm', {
7373
// => 2025年8月23日(土) 23:30
7474
```
7575

76-
## Types and Interfaces
77-
78-
### Option Types
79-
80-
#### FormatterOptions
81-
82-
```typescript
83-
interface FormatterOptions {
84-
locale?: Locale; // Locale object for localized formatting
85-
timeZone?: TimeZone | string; // Timezone object or IANA timezone name string
86-
numeral?: Numeral; // Numeral system for number formatting
87-
calendar?: 'gregory' | 'buddhist'; // Calendar system
88-
hour12?: 'h11' | 'h12'; // 12-hour format type
89-
hour24?: 'h23' | 'h24'; // 24-hour format type
90-
}
91-
```
92-
93-
#### ParserOptions
94-
95-
```typescript
96-
interface ParserOptions {
97-
locale?: Locale; // Locale object for localized parsing
98-
timeZone?: TimeZone | string; // Timezone object or IANA timezone name string
99-
numeral?: Numeral; // Numeral system for number parsing
100-
calendar?: 'gregory' | 'buddhist'; // Calendar system
101-
hour12?: 'h11' | 'h12'; // 12-hour format type
102-
hour24?: 'h23' | 'h24'; // 24-hour format type
103-
ignoreCase?: boolean; // Case-insensitive parsing
104-
}
105-
```
106-
107-
## Format Tokens
108-
109-
### Date Tokens
110-
111-
| Token | Meaning | Output Examples |
112-
|--------|----------------------------|-------------------|
113-
| `YYYY` | 4-digit year | 0999, 2015 |
114-
| `YY` | 2-digit year | 99, 01, 15 |
115-
| `Y` | Year without zero padding | 2, 44, 888, 2015 |
116-
| `MMMM` | Full month name | January, December |
117-
| `MMM` | Short month name | Jan, Dec |
118-
| `MM` | Month | 01, 12 |
119-
| `M` | Month without zero padding | 1, 12 |
120-
| `DD` | Day | 02, 31 |
121-
| `D` | Day without zero padding | 2, 31 |
122-
123-
### Time Tokens
124-
125-
| Token | Meaning | Output Examples |
126-
|-------|---------------------------------------------|-----------------|
127-
| `HH` | Hour in 24-hour format | 23, 08 |
128-
| `H` | Hour in 24-hour format without zero padding | 23, 8 |
129-
| `hh` | Hour in 12-hour format | 11, 08 |
130-
| `h` | Hour in 12-hour format without zero padding | 11, 8 |
131-
| `mm` | Minutes | 14, 07 |
132-
| `m` | Minutes without zero padding | 14, 7 |
133-
| `ss` | Seconds | 05, 10 |
134-
| `s` | Seconds without zero padding | 5, 10 |
135-
| `SSS` | 3-digit milliseconds | 753, 022 |
136-
| `SS` | 2-digit milliseconds | 75, 02 |
137-
| `S` | 1-digit milliseconds | 7, 0 |
138-
139-
### Day of Week Tokens
140-
141-
| Token | Meaning | Output Examples |
142-
|--------|---------------------|-----------------|
143-
| `dddd` | Full day name | Friday, Sunday |
144-
| `ddd` | Short day name | Fri, Sun |
145-
| `dd` | Very short day name | Fr, Su |
146-
147-
### AM/PM and Timezone Tokens
148-
149-
| Token | Meaning | Output Examples |
150-
|-------|--------------------------------|-----------------|
151-
| `A` | Uppercase AM/PM | AM, PM |
152-
| `AA` | Uppercase AM/PM (with periods) | A.M., P.M. |
153-
| `a` | Lowercase AM/PM | am, pm |
154-
| `aa` | Lowercase AM/PM (with periods) | a.m., p.m. |
155-
| `Z` | Timezone offset | +0100, -0800 |
156-
| `ZZ` | Timezone offset with colon | +01:00, -08:00 |
157-
15876
## Supported Locales
15977

16078
date-and-time supports 40+ locales. Import only the ones you need:

docs/api/isValid.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,25 @@ isValid('august 23, 2025', 'MMMM D, YYYY', { ignoreCase: true }); // => true
7272
isValid('August 23, 2025', 'MMMM D, YYYY'); // => true (correct case)
7373
```
7474

75+
### defaultDate Validation
76+
77+
Use `defaultDate` to provide context for validation of partial date strings. The most practical use case is leap year-aware validation of month-day strings.
78+
79+
```typescript
80+
import { isValid } from 'date-and-time';
81+
82+
// Leap day validation — result depends on the year
83+
isValid('02-29', 'MM-DD', { defaultDate: { Y: 2024 } }); // => true (2024 is a leap year)
84+
isValid('02-29', 'MM-DD', { defaultDate: { Y: 2023 } }); // => false (2023 is not a leap year)
85+
isValid('02-29', 'MM-DD'); // => false (default year 1970 is not a leap year)
86+
87+
// Day range validation — depends on both year and month
88+
isValid('29', 'D', { defaultDate: { Y: 2024, M: 2 } }); // => true (Feb 2024 has 29 days)
89+
isValid('31', 'D', { defaultDate: { Y: 2024, M: 4 } }); // => false (April has 30 days)
90+
```
91+
92+
**Note**: Values provided in `defaultDate` are also subject to range validation. For example, an out-of-range `H` value in `defaultDate` will cause `isValid()` to return `false`.
93+
7594
## Advanced Validation Patterns
7695

7796
### Multiple Format Validation

docs/api/parse.md

Lines changed: 84 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,22 @@ For available plugins, see the [`plugins`](#plugins) option in ParserOptions.
124124

125125
## ParserOptions
126126

127+
The `ParserOptions` object allows you to customize the parsing behavior:
128+
129+
```typescript
130+
interface ParserOptions {
131+
locale?: Locale;
132+
timeZone?: TimeZone | string;
133+
numeral?: Numeral;
134+
calendar?: 'gregory' | 'buddhist';
135+
hour12?: 'h11' | 'h12';
136+
hour24?: 'h23' | 'h24';
137+
ignoreCase?: boolean;
138+
defaultDate?: ParsedComponents;
139+
plugins?: ParserPlugin[];
140+
}
141+
```
142+
127143
### locale
128144

129145
**Type**: `Locale`
@@ -220,28 +236,6 @@ parse('August 23, 2568', 'MMMM D, YYYY', { calendar: 'buddhist' });
220236
// => Fri Aug 23 2025 00:00:00 GMT-0700
221237
```
222238

223-
### ignoreCase
224-
225-
**Type**: `boolean`
226-
**Default**: `false`
227-
228-
Enables case-insensitive parsing for text elements.
229-
230-
```typescript
231-
import { parse } from 'date-and-time';
232-
233-
// Case-sensitive (default)
234-
parse('august 23, 2025', 'MMMM D, YYYY');
235-
// => Invalid Date
236-
237-
// Case-insensitive
238-
parse('AUGUST 23, 2025', 'MMMM D, YYYY', { ignoreCase: true });
239-
// => Fri Aug 23 2025 00:00:00 GMT-0700
240-
241-
parse('fri aug 23 2025', 'ddd MMM DD YYYY', { ignoreCase: true });
242-
// => Fri Aug 23 2025 00:00:00 GMT-0700
243-
```
244-
245239
### hour12
246240

247241
**Type**: `"h11" | "h12"`
@@ -280,6 +274,72 @@ parse('24:30', 'H:mm', { hour24: 'h24' });
280274
// => Thu Jan 01 1970 00:30:00 GMT-0800
281275
```
282276

277+
### ignoreCase
278+
279+
**Type**: `boolean`
280+
**Default**: `false`
281+
282+
Enables case-insensitive parsing for text elements.
283+
284+
```typescript
285+
import { parse } from 'date-and-time';
286+
287+
// Case-sensitive (default)
288+
parse('august 23, 2025', 'MMMM D, YYYY');
289+
// => Invalid Date
290+
291+
// Case-insensitive
292+
parse('AUGUST 23, 2025', 'MMMM D, YYYY', { ignoreCase: true });
293+
// => Fri Aug 23 2025 00:00:00 GMT-0700
294+
295+
parse('fri aug 23 2025', 'ddd MMM DD YYYY', { ignoreCase: true });
296+
// => Fri Aug 23 2025 00:00:00 GMT-0700
297+
```
298+
299+
### defaultDate
300+
301+
**Type**: `ParsedComponents`
302+
**Default**: `{ Y: 1970, M: 1, D: 1, m: 0, s: 0, S: 0 }`
303+
304+
Specifies default values for date/time components that are missing from the format string. This is useful when parsing partial strings such as time-only or month-day formats.
305+
306+
```typescript
307+
interface ParsedComponents {
308+
Y?: number; // Year
309+
M?: number; // Month (1-12)
310+
D?: number; // Day
311+
H?: number; // Hour (24-hour)
312+
A?: number; // Meridiem (0: AM, 1: PM)
313+
h?: number; // Hour (12-hour)
314+
m?: number; // Minute
315+
s?: number; // Second
316+
S?: number; // Millisecond
317+
Z?: number; // Timezone offset in minutes (e.g., UTC+9 = -540)
318+
}
319+
```
320+
321+
**Note**: If `defaultDate.Z` is set, it takes precedence over the `timeZone` option. `Z` is in minutes, using the same sign convention as the `Z` / `ZZ` format tokens (e.g., UTC+9 = `-540`).
322+
323+
```typescript
324+
import { parse } from 'date-and-time';
325+
326+
// Parse time-only string — fill in date from defaultDate
327+
parse('12:30', 'HH:mm', { defaultDate: { Y: 2024, M: 3, D: 15 } });
328+
// => Fri Mar 15 2024 12:30:00
329+
330+
// Parse month-day only — fill in year from defaultDate
331+
parse('03-15', 'MM-DD', { defaultDate: { Y: 2024 } });
332+
// => Fri Mar 15 2024 00:00:00
333+
334+
// Fill in time components for a date-only format
335+
parse('2024-03-15', 'YYYY-MM-DD', { defaultDate: { H: 10, m: 30, s: 45 } });
336+
// => Fri Mar 15 2024 10:30:45
337+
338+
// defaultDate.Z takes precedence over timeZone option
339+
parse('12:30', 'HH:mm', { defaultDate: { Y: 2024, M: 3, D: 15, Z: -540 }, timeZone: 'UTC' });
340+
// => Fri Mar 15 2024 03:30:00 UTC (interpreted as UTC+9; timeZone: 'UTC' is ignored)
341+
```
342+
283343
### plugins
284344

285345
**Type**: `ParserPlugin[]`
@@ -340,6 +400,8 @@ parse('2025', 'YYYY');
340400
// => Wed Jan 01 2025 00:00:00 GMT-0800
341401
```
342402

403+
To customize these defaults, use the [`defaultDate`](#defaultdate) option.
404+
343405
### Date Range Limitations
344406

345407
The parsable maximum date is `December 31, 9999`, and the minimum date is `January 1, 0001`.

docs/api/preparse.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ preparse(dateString, formatString[, options])
1616
|----------------|----------------------------|----------|--------------------------------------------------------------------------|
1717
| `dateString` | `string` | Yes | The date string to parse |
1818
| `formatString` | `string \| CompiledObject` | Yes | Format pattern string or compiled object |
19-
| `options` | `ParserOptions` | No | Parsing options for customization (see [`parse()`](./parse) for details) |
19+
| `options` | `ParserOptions` | No | Parsing options for customization (see [`parse()`](./parse#parseroptions) for details) |
2020

2121
### Returns
2222

@@ -94,7 +94,7 @@ console.log(result);
9494

9595
## ParserOptions
9696

97-
The `options` parameter accepts the same `ParserOptions` as the [`parse()`](./parse#parseroptions) function. This includes locale, timezone, numeral system, calendar, case sensitivity, and hour format settings. Refer to the parse documentation for complete details on all available options.
97+
The `options` parameter accepts the same `ParserOptions` as the [`parse()`](./parse#parseroptions) function. This includes locale, timezone, numeral system, calendar, case sensitivity, hour format settings, and `defaultDate`. Refer to the parse documentation for complete details on all available options.
9898

9999
## Use Cases
100100

0 commit comments

Comments
 (0)