@oneluiz/dual-datepicker 3.5.0 β†’ 3.5.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.
package/README.md CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  A lightweight, zero-dependency date range picker for Angular 17+. Built with standalone components, Reactive Forms, and Angular Signals. No Angular Material required.
4
4
 
5
- > **πŸ†• NEW in v3.5.0**: [**Headless Architecture**](HEADLESS.md) - Use date range state WITHOUT the UI component. Perfect for SSR, services, and global dashboard filters! 🎯
5
+ > **πŸ†• NEW in v3.5.1**: [**Timezone-Safe Date Adapter**](docs/TIMEZONE_ADAPTER.md) - Fixes enterprise-critical timezone bugs in ERP, BI, POS, and invoicing systems πŸ›‘οΈ
6
+ > **πŸ†• NEW in v3.5.0**: [**Headless Architecture**](docs/HEADLESS.md) - Use date range state WITHOUT the UI component. Perfect for SSR, services, and global dashboard filters! 🎯
6
7
 
7
8
  [![npm version](https://img.shields.io/npm/v/@oneluiz/dual-datepicker)](https://www.npmjs.com/package/@oneluiz/dual-datepicker)
8
9
  [![npm provenance](https://img.shields.io/badge/provenance-available-brightgreen)](https://www.npmjs.com/package/@oneluiz/dual-datepicker)
@@ -21,6 +22,25 @@ npm install @oneluiz/dual-datepicker
21
22
 
22
23
  ## 🌟 What's New
23
24
 
25
+ ### Timezone-Safe Date Adapter (v3.5.1)
26
+
27
+ **Fixed**: Enterprise timezone bugs that caused date ranges to shift by Β±1 day.
28
+
29
+ ```typescript
30
+ // βœ… No more timezone shift bugs!
31
+ const store = inject(DualDateRangeStore);
32
+ store.applyPreset('THIS_MONTH');
33
+ const range = store.range(); // { start: "2024-03-01", end: "2024-03-31" }
34
+ // Always correct, even across timezones and DST transitions
35
+
36
+ // βœ… Optional: Use your preferred date library
37
+ providers: [
38
+ { provide: DATE_ADAPTER, useClass: LuxonDateAdapter }
39
+ ]
40
+ ```
41
+
42
+ **[πŸ“– Read the Timezone Adapter Guide β†’](docs/TIMEZONE_ADAPTER.md)**
43
+
24
44
  ### Headless Architecture (v3.5.0)
25
45
 
26
46
  Use date range logic **without the UI component**:
@@ -44,7 +64,7 @@ http.get(`/api/sales?start=${range.start}&end=${range.end}`);
44
64
  - 🎯 Service-layer filtering
45
65
  - πŸ“ˆ Analytics and BI tools
46
66
 
47
- **[πŸ“– Read the Headless Architecture Guide β†’](HEADLESS.md)**
67
+ **[πŸ“– Read the Headless Architecture Guide β†’](docs/HEADLESS.md)**
48
68
 
49
69
  ---
50
70
 
@@ -245,7 +265,35 @@ export class DashboardComponent {
245
265
  - βœ… Perfect for services and guards
246
266
  - βœ… Testable and deterministic
247
267
 
248
- **[πŸ“– Full Headless Architecture Guide β†’](HEADLESS.md)** | **[πŸ’» Code Examples β†’](HEADLESS_EXAMPLES.ts)**
268
+ #### SSR-Safe Clock Injection
269
+
270
+ Presets like "Last 7 Days" now use **clock injection** for SSR hydration consistency:
271
+
272
+ ```typescript
273
+ // Server (SSR)
274
+ import { DATE_CLOCK } from '@oneluiz/dual-datepicker';
275
+
276
+ const requestTime = new Date();
277
+
278
+ renderApplication(AppComponent, {
279
+ providers: [
280
+ { provide: DATE_CLOCK, useValue: { now: () => requestTime } }
281
+ ]
282
+ });
283
+ ```
284
+
285
+ ```typescript
286
+ // Client (Browser)
287
+ bootstrapApplication(AppComponent, {
288
+ providers: [
289
+ { provide: DATE_CLOCK, useValue: { now: () => new Date(getServerTime()) } }
290
+ ]
291
+ });
292
+ ```
293
+
294
+ **Result**: Server and client resolve identical presets βœ… No hydration mismatch!
295
+
296
+ **[πŸ“– Full Headless Architecture Guide β†’](HEADLESS.md)** | **[πŸ’» Code Examples β†’](HEADLESS_EXAMPLES.ts)** | **[πŸš€ SSR Clock Injection Guide β†’](SSR_CLOCK_INJECTION.md)**
249
297
 
250
298
  ---
251
299
 
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Date Adapter Abstraction for Timezone-Safe Date Operations
3
+ *
4
+ * Problem:
5
+ * Using Date natively in calendar/range logic causes enterprise bugs:
6
+ * - Date ranges shift by 1 day due to timezone/DST
7
+ * - Server (UTC) vs Client (local timezone) discrepancies
8
+ * - Inconsistent reporting in BI/ERP/invoicing/hotel systems
9
+ *
10
+ * Solution:
11
+ * All date calculations go through an adapter layer.
12
+ * This allows:
13
+ * - Timezone-safe operations by default (NativeDateAdapter normalizes to day boundaries)
14
+ * - Optional integration with Luxon/DayJS/date-fns for advanced timezone handling
15
+ * - Consistent behavior across SSR and client
16
+ * - Migration path to timezone-aware libraries without breaking changes
17
+ *
18
+ * Architecture:
19
+ * ```
20
+ * DualDateRangeStore
21
+ * ↓ uses
22
+ * DateAdapter ← Inject via DATE_ADAPTER token
23
+ * ↓ implements
24
+ * NativeDateAdapter (default, zero deps)
25
+ * LuxonDateAdapter (optional, full timezone support)
26
+ * DayJSDateAdapter (optional, lightweight)
27
+ * ```
28
+ *
29
+ * Usage:
30
+ * ```typescript
31
+ * // Default (NativeDateAdapter)
32
+ * bootstrapApplication(AppComponent);
33
+ *
34
+ * // Advanced (Luxon with timezone)
35
+ * import { LuxonDateAdapter } from '@oneluiz/dual-datepicker/luxon';
36
+ *
37
+ * bootstrapApplication(AppComponent, {
38
+ * providers: [
39
+ * { provide: DATE_ADAPTER, useClass: LuxonDateAdapter }
40
+ * ]
41
+ * });
42
+ * ```
43
+ */
44
+ import { InjectionToken } from '@angular/core';
45
+ /**
46
+ * Date adapter interface for all calendar/range operations
47
+ *
48
+ * All methods operate on "calendar day" level, ignoring time components.
49
+ * Implementations must ensure timezone-safe behavior.
50
+ *
51
+ * Implementations:
52
+ * - NativeDateAdapter: Default, zero dependencies, uses Date with normalization
53
+ * - LuxonDateAdapter: Optional, full timezone support with Luxon
54
+ * - DayJSDateAdapter: Optional, lightweight timezone support
55
+ * - Custom: Implement for your specific backend/timezone requirements
56
+ */
57
+ export interface DateAdapter {
58
+ /**
59
+ * Normalize date to start of day (00:00:00.000)
60
+ *
61
+ * Critical for timezone-safe comparisons.
62
+ *
63
+ * Example:
64
+ * ```typescript
65
+ * const date = new Date('2026-02-21T15:30:00');
66
+ * const normalized = adapter.normalize(date);
67
+ * // β†’ 2026-02-21T00:00:00.000 (in local timezone)
68
+ * ```
69
+ *
70
+ * @param date - Date to normalize
71
+ * @returns Date with time set to 00:00:00.000
72
+ */
73
+ normalize(date: Date): Date;
74
+ /**
75
+ * Check if two dates represent the same calendar day
76
+ *
77
+ * Ignores time component. Timezone-safe.
78
+ *
79
+ * Example:
80
+ * ```typescript
81
+ * const a = new Date('2026-02-21T23:59:59');
82
+ * const b = new Date('2026-02-21T00:00:01');
83
+ * adapter.isSameDay(a, b); // β†’ true
84
+ * ```
85
+ */
86
+ isSameDay(a: Date, b: Date): boolean;
87
+ /**
88
+ * Check if date A is before date B (calendar day level)
89
+ *
90
+ * Example:
91
+ * ```typescript
92
+ * adapter.isBeforeDay(new Date('2026-02-20'), new Date('2026-02-21')); // β†’ true
93
+ * adapter.isBeforeDay(new Date('2026-02-21'), new Date('2026-02-21')); // β†’ false
94
+ * ```
95
+ */
96
+ isBeforeDay(a: Date, b: Date): boolean;
97
+ /**
98
+ * Check if date A is after date B (calendar day level)
99
+ *
100
+ * Example:
101
+ * ```typescript
102
+ * adapter.isAfterDay(new Date('2026-02-22'), new Date('2026-02-21')); // β†’ true
103
+ * adapter.isAfterDay(new Date('2026-02-21'), new Date('2026-02-21')); // β†’ false
104
+ * ```
105
+ */
106
+ isAfterDay(a: Date, b: Date): boolean;
107
+ /**
108
+ * Add days to a date
109
+ *
110
+ * Must handle DST transitions correctly.
111
+ *
112
+ * Example:
113
+ * ```typescript
114
+ * const date = new Date('2026-02-21');
115
+ * const future = adapter.addDays(date, 7);
116
+ * // β†’ 2026-02-28
117
+ * ```
118
+ */
119
+ addDays(date: Date, days: number): Date;
120
+ /**
121
+ * Add months to a date
122
+ *
123
+ * Must handle month overflow (e.g., Jan 31 + 1 month β†’ Feb 28).
124
+ *
125
+ * Example:
126
+ * ```typescript
127
+ * const date = new Date('2026-01-31');
128
+ * const next = adapter.addMonths(date, 1);
129
+ * // β†’ 2026-02-28 (not March 3rd)
130
+ * ```
131
+ */
132
+ addMonths(date: Date, months: number): Date;
133
+ /**
134
+ * Get start of day (00:00:00.000)
135
+ *
136
+ * Similar to normalize() but explicit intent.
137
+ */
138
+ startOfDay(date: Date): Date;
139
+ /**
140
+ * Get end of day (23:59:59.999)
141
+ *
142
+ * Useful for range queries that need to include entire day.
143
+ *
144
+ * Example:
145
+ * ```typescript
146
+ * const date = new Date('2026-02-21');
147
+ * const end = adapter.endOfDay(date);
148
+ * // β†’ 2026-02-21T23:59:59.999
149
+ * ```
150
+ */
151
+ endOfDay(date: Date): Date;
152
+ /**
153
+ * Get first day of month (00:00:00.000)
154
+ *
155
+ * Example:
156
+ * ```typescript
157
+ * const date = new Date('2026-02-21');
158
+ * const start = adapter.startOfMonth(date);
159
+ * // β†’ 2026-02-01T00:00:00.000
160
+ * ```
161
+ */
162
+ startOfMonth(date: Date): Date;
163
+ /**
164
+ * Get last day of month (23:59:59.999)
165
+ *
166
+ * Example:
167
+ * ```typescript
168
+ * const date = new Date('2026-02-21');
169
+ * const end = adapter.endOfMonth(date);
170
+ * // β†’ 2026-02-28T23:59:59.999
171
+ * ```
172
+ */
173
+ endOfMonth(date: Date): Date;
174
+ /**
175
+ * Get year (4-digit)
176
+ *
177
+ * Example:
178
+ * ```typescript
179
+ * adapter.getYear(new Date('2026-02-21')); // β†’ 2026
180
+ * ```
181
+ */
182
+ getYear(date: Date): number;
183
+ /**
184
+ * Get month (0-11, where 0 = January)
185
+ *
186
+ * Example:
187
+ * ```typescript
188
+ * adapter.getMonth(new Date('2026-02-21')); // β†’ 1 (February)
189
+ * ```
190
+ */
191
+ getMonth(date: Date): number;
192
+ /**
193
+ * Get day of month (1-31)
194
+ *
195
+ * Example:
196
+ * ```typescript
197
+ * adapter.getDate(new Date('2026-02-21')); // β†’ 21
198
+ * ```
199
+ */
200
+ getDate(date: Date): number;
201
+ /**
202
+ * Get day of week (0-6, where 0 = Sunday)
203
+ *
204
+ * Example:
205
+ * ```typescript
206
+ * adapter.getDay(new Date('2026-02-21')); // β†’ 6 (Saturday)
207
+ * ```
208
+ */
209
+ getDay(date: Date): number;
210
+ /**
211
+ * Convert Date to ISO date string (YYYY-MM-DD)
212
+ *
213
+ * CRITICAL: Must be timezone-safe!
214
+ * DO NOT use date.toISOString() as it converts to UTC.
215
+ *
216
+ * Example:
217
+ * ```typescript
218
+ * // Local timezone GMT-6 (CST)
219
+ * const date = new Date('2026-02-21T23:00:00'); // 11 PM CST
220
+ *
221
+ * // ❌ WRONG: date.toISOString().split('T')[0]
222
+ * // Returns "2026-02-22" (shifted to UTC!)
223
+ *
224
+ * // βœ… CORRECT: adapter.toISODate(date)
225
+ * // Returns "2026-02-21" (local date preserved)
226
+ * ```
227
+ *
228
+ * @param date - Date to format (or null)
229
+ * @returns ISO date string in YYYY-MM-DD format (local timezone), empty string if null
230
+ */
231
+ toISODate(date: Date | null): string;
232
+ /**
233
+ * Parse ISO date string (YYYY-MM-DD) to Date
234
+ *
235
+ * CRITICAL: Must be timezone-safe!
236
+ * DO NOT use new Date(isoString) as it may parse as UTC.
237
+ *
238
+ * Example:
239
+ * ```typescript
240
+ * // ❌ WRONG: new Date('2026-02-21')
241
+ * // May parse as UTC midnight, which is previous day in some timezones
242
+ *
243
+ * // βœ… CORRECT: adapter.parseISODate('2026-02-21')
244
+ * // Returns Date representing 2026-02-21 00:00:00 in local timezone
245
+ * ```
246
+ *
247
+ * @param isoDate - ISO date string (YYYY-MM-DD) or null
248
+ * @returns Date object or null if invalid
249
+ */
250
+ parseISODate(isoDate: string | null): Date | null;
251
+ /**
252
+ * Get week start day for locale
253
+ *
254
+ * 0 = Sunday, 1 = Monday, etc.
255
+ *
256
+ * Example:
257
+ * ```typescript
258
+ * adapter.getWeekStart('en-US'); // β†’ 0 (Sunday)
259
+ * adapter.getWeekStart('en-GB'); // β†’ 1 (Monday)
260
+ * ```
261
+ *
262
+ * @param locale - Locale string (e.g., 'en-US', 'es-ES')
263
+ * @returns Day number (0-6)
264
+ */
265
+ getWeekStart(locale?: string): 0 | 1 | 2 | 3 | 4 | 5 | 6;
266
+ }
267
+ /**
268
+ * Injection token for DateAdapter
269
+ *
270
+ * Default: NativeDateAdapter (zero dependencies)
271
+ *
272
+ * Override for advanced timezone handling:
273
+ *
274
+ * ```typescript
275
+ * // Luxon with timezone
276
+ * import { LuxonDateAdapter } from '@oneluiz/dual-datepicker/luxon';
277
+ *
278
+ * bootstrapApplication(AppComponent, {
279
+ * providers: [
280
+ * {
281
+ * provide: DATE_ADAPTER,
282
+ * useClass: LuxonDateAdapter
283
+ * }
284
+ * ]
285
+ * });
286
+ * ```
287
+ *
288
+ * Custom implementation:
289
+ *
290
+ * ```typescript
291
+ * class CustomDateAdapter implements DateAdapter {
292
+ * // Your implementation for backend-specific date handling
293
+ * }
294
+ *
295
+ * provide(DATE_ADAPTER, { useClass: CustomDateAdapter });
296
+ * ```
297
+ */
298
+ export declare const DATE_ADAPTER: InjectionToken<DateAdapter>;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Date Clock Abstraction for SSR-Safe Date Resolution
3
+ *
4
+ * Problem:
5
+ * Presets like "Last 7 Days" or "This Month" use new Date() which causes:
6
+ * - SSR hydration mismatch
7
+ * - Server renders "2026-02-14", client renders "2026-02-15"
8
+ * - Different filters in dashboards
9
+ * - Different queries in ERP/BI
10
+ * - Cache inconsistency
11
+ *
12
+ * Solution:
13
+ * Inject a DateClock to control time deterministically:
14
+ *
15
+ * Server (SSR):
16
+ * provide(DATE_CLOCK, {
17
+ * useValue: { now: () => new Date('2026-02-21T00:00:00Z') }
18
+ * })
19
+ *
20
+ * Client (Browser):
21
+ * Uses SystemClock by default (new Date())
22
+ *
23
+ * Testing:
24
+ * provide(DATE_CLOCK, {
25
+ * useValue: { now: () => new Date('2026-01-15T10:30:00Z') }
26
+ * })
27
+ *
28
+ * Architecture:
29
+ * - PresetEngine receives DateClock via DI
30
+ * - All preset calculations use clock.now() instead of new Date()
31
+ * - Deterministic: Same clock.now() β†’ Same preset result
32
+ * - SSR-compatible: Server and client resolve identical ranges
33
+ */
34
+ import { InjectionToken } from '@angular/core';
35
+ /**
36
+ * Clock abstraction for deterministic date resolution
37
+ *
38
+ * Use cases:
39
+ * - SSR: Ensure server and client generate identical presets
40
+ * - Testing: Control time for predictable test results
41
+ * - Replay: Reproduce exact user state from past sessions
42
+ * - Demo: Freeze time for reproducible demos
43
+ */
44
+ export interface DateClock {
45
+ /**
46
+ * Get current date/time
47
+ *
48
+ * Default implementation returns new Date()
49
+ * Override for SSR, testing, or time-travel scenarios
50
+ */
51
+ now(): Date;
52
+ }
53
+ /**
54
+ * Injection token for DateClock
55
+ *
56
+ * Usage:
57
+ * ```typescript
58
+ * // Default (uses SystemClock)
59
+ * bootstrapApplication(AppComponent);
60
+ *
61
+ * // SSR Override
62
+ * bootstrapApplication(AppComponent, {
63
+ * providers: [
64
+ * {
65
+ * provide: DATE_CLOCK,
66
+ * useValue: { now: () => new Date('2026-02-21T00:00:00Z') }
67
+ * }
68
+ * ]
69
+ * });
70
+ *
71
+ * // Testing Override
72
+ * TestBed.configureTestingModule({
73
+ * providers: [
74
+ * {
75
+ * provide: DATE_CLOCK,
76
+ * useValue: { now: () => new Date('2026-01-15T12:00:00Z') }
77
+ * }
78
+ * ]
79
+ * });
80
+ * ```
81
+ */
82
+ export declare const DATE_CLOCK: InjectionToken<DateClock>;
@@ -14,6 +14,10 @@ export interface DateRangeConfig {
14
14
  defaultEndTime?: string;
15
15
  }
16
16
  export declare class DualDateRangeStore {
17
+ private presetEngine;
18
+ private clock;
19
+ private adapter;
20
+ constructor();
17
21
  private config;
18
22
  private _startDate;
19
23
  private _endDate;
@@ -72,6 +76,11 @@ export declare class DualDateRangeStore {
72
76
  reset(): void;
73
77
  /**
74
78
  * Apply a preset by key
79
+ *
80
+ * SSR-Safe: Uses injected DateClock for deterministic resolution
81
+ *
82
+ * @param presetKey - Preset identifier (e.g., 'TODAY', 'LAST_7_DAYS')
83
+ * @param now - Optional date override (defaults to clock.now())
75
84
  */
76
85
  applyPreset(presetKey: string, now?: Date): void;
77
86
  /**
package/core/index.d.ts CHANGED
@@ -5,3 +5,7 @@
5
5
  export * from './dual-date-range.store';
6
6
  export * from './preset.engine';
7
7
  export * from './range.validator';
8
+ export * from './date-clock';
9
+ export * from './system-clock';
10
+ export * from './date-adapter';
11
+ export * from './native-date-adapter';
@@ -0,0 +1,152 @@
1
+ import { DateAdapter } from './date-adapter';
2
+ import * as i0 from "@angular/core";
3
+ export declare class NativeDateAdapter implements DateAdapter {
4
+ /**
5
+ * Normalize date to start of day (00:00:00.000) in local timezone
6
+ *
7
+ * This is the foundation of timezone-safe operations.
8
+ * All other methods use normalized dates for comparisons.
9
+ */
10
+ normalize(date: Date): Date;
11
+ /**
12
+ * Check if two dates are the same calendar day
13
+ *
14
+ * Implementation: Compare YYYY-MM-DD components directly
15
+ * Avoids timezone issues from valueOf() comparisons
16
+ */
17
+ isSameDay(a: Date, b: Date): boolean;
18
+ /**
19
+ * Check if date A is before date B (calendar day level)
20
+ *
21
+ * Implementation: Compare normalized dates using valueOf()
22
+ */
23
+ isBeforeDay(a: Date, b: Date): boolean;
24
+ /**
25
+ * Check if date A is after date B (calendar day level)
26
+ *
27
+ * Implementation: Compare normalized dates using valueOf()
28
+ */
29
+ isAfterDay(a: Date, b: Date): boolean;
30
+ /**
31
+ * Add days to a date
32
+ *
33
+ * Implementation: Use setDate() which handles month rollover automatically
34
+ *
35
+ * Example:
36
+ * Jan 31 + 3 days β†’ Feb 3 βœ…
37
+ * Feb 28 + 1 day β†’ Mar 1 βœ… (non-leap year)
38
+ */
39
+ addDays(date: Date, days: number): Date;
40
+ /**
41
+ * Add months to a date
42
+ *
43
+ * CRITICAL: Handles month overflow correctly
44
+ *
45
+ * Algorithm:
46
+ * 1. Add months using setMonth()
47
+ * 2. If day-of-month changed (overflow), set to last day of target month
48
+ *
49
+ * Examples:
50
+ * - Jan 31 + 1 month β†’ Feb 28 (or Feb 29 in leap year) βœ…
51
+ * - Jan 31 + 2 months β†’ Mar 31 βœ…
52
+ * - Mar 31 + 1 month β†’ Apr 30 βœ…
53
+ * - Dec 31 + 1 month β†’ Jan 31 (next year) βœ…
54
+ */
55
+ addMonths(date: Date, months: number): Date;
56
+ /**
57
+ * Get start of day (00:00:00.000)
58
+ *
59
+ * Alias for normalize() with explicit intent
60
+ */
61
+ startOfDay(date: Date): Date;
62
+ /**
63
+ * Get end of day (23:59:59.999)
64
+ *
65
+ * Useful for inclusive range queries
66
+ */
67
+ endOfDay(date: Date): Date;
68
+ /**
69
+ * Get first day of month (00:00:00.000)
70
+ */
71
+ startOfMonth(date: Date): Date;
72
+ /**
73
+ * Get last day of month (23:59:59.999)
74
+ *
75
+ * Algorithm: Go to 1st of next month, subtract 1 day
76
+ */
77
+ endOfMonth(date: Date): Date;
78
+ /**
79
+ * Get year (4-digit)
80
+ */
81
+ getYear(date: Date): number;
82
+ /**
83
+ * Get month (0-11)
84
+ */
85
+ getMonth(date: Date): number;
86
+ /**
87
+ * Get day of month (1-31)
88
+ */
89
+ getDate(date: Date): number;
90
+ /**
91
+ * Get day of week (0-6, Sunday=0)
92
+ */
93
+ getDay(date: Date): number;
94
+ /**
95
+ * Convert Date to ISO date string (YYYY-MM-DD)
96
+ *
97
+ * CRITICAL: DO NOT use toISOString() - it converts to UTC!
98
+ *
99
+ * Manual construction ensures local timezone is preserved:
100
+ *
101
+ * Example problem with toISOString():
102
+ * ```
103
+ * // Local timezone: GMT-6 (CST)
104
+ * const date = new Date('2026-02-21T23:00:00'); // 11 PM Feb 21 local
105
+ *
106
+ * // WRONG ❌
107
+ * date.toISOString().split('T')[0]
108
+ * // Returns "2026-02-22" (converted to UTC = Feb 22 05:00 AM)
109
+ *
110
+ * // CORRECT βœ…
111
+ * toISODate(date)
112
+ * // Returns "2026-02-21" (local date preserved)
113
+ * ```
114
+ *
115
+ * Implementation: Build YYYY-MM-DD manually from local date components
116
+ */
117
+ toISODate(date: Date): string;
118
+ /**
119
+ * Parse ISO date string (YYYY-MM-DD) to Date
120
+ *
121
+ * CRITICAL: DO NOT use new Date(isoString) - may parse as UTC!
122
+ *
123
+ * Example problem with Date constructor:
124
+ * ```
125
+ * // Local timezone: GMT-6 (CST)
126
+ *
127
+ * // WRONG ❌
128
+ * new Date('2026-02-21')
129
+ * // Parsed as UTC: 2026-02-21T00:00:00Z
130
+ * // In local timezone: Feb 20, 2026 6:00 PM (previous day!)
131
+ *
132
+ * // CORRECT βœ…
133
+ * parseISODate('2026-02-21')
134
+ * // Returns: 2026-02-21T00:00:00 local time
135
+ * ```
136
+ *
137
+ * Implementation: Parse components and construct Date in local timezone
138
+ */
139
+ parseISODate(isoDate: string): Date | null;
140
+ /**
141
+ * Get week start day for locale
142
+ *
143
+ * Default: Sunday (0) for most locales
144
+ * Monday (1) for Europe, ISO 8601
145
+ *
146
+ * Implementation: Simple locale detection
147
+ * For advanced needs, use Intl.Locale or external library
148
+ */
149
+ getWeekStart(locale?: string): 0 | 1 | 2 | 3 | 4 | 5 | 6;
150
+ static Ι΅fac: i0.Ι΅Ι΅FactoryDeclaration<NativeDateAdapter, never>;
151
+ static Ι΅prov: i0.Ι΅Ι΅InjectableDeclaration<NativeDateAdapter>;
152
+ }