chronos-ts 1.1.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,671 @@
1
+ "use strict";
2
+ /**
3
+ * ChronosTimezone - Timezone handling and conversions
4
+ * @module ChronosTimezone
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.Timezones = exports.ChronosTimezone = exports.TIMEZONES = void 0;
8
+ // ============================================================================
9
+ // Timezone Data
10
+ // ============================================================================
11
+ /**
12
+ * Common timezone identifiers
13
+ */
14
+ exports.TIMEZONES = {
15
+ // UTC
16
+ UTC: 'UTC',
17
+ GMT: 'GMT',
18
+ // Americas
19
+ 'America/New_York': 'America/New_York',
20
+ 'America/Chicago': 'America/Chicago',
21
+ 'America/Denver': 'America/Denver',
22
+ 'America/Los_Angeles': 'America/Los_Angeles',
23
+ 'America/Phoenix': 'America/Phoenix',
24
+ 'America/Anchorage': 'America/Anchorage',
25
+ 'America/Toronto': 'America/Toronto',
26
+ 'America/Vancouver': 'America/Vancouver',
27
+ 'America/Mexico_City': 'America/Mexico_City',
28
+ 'America/Sao_Paulo': 'America/Sao_Paulo',
29
+ 'America/Buenos_Aires': 'America/Buenos_Aires',
30
+ 'America/Lima': 'America/Lima',
31
+ 'America/Bogota': 'America/Bogota',
32
+ // Europe
33
+ 'Europe/London': 'Europe/London',
34
+ 'Europe/Paris': 'Europe/Paris',
35
+ 'Europe/Berlin': 'Europe/Berlin',
36
+ 'Europe/Madrid': 'Europe/Madrid',
37
+ 'Europe/Rome': 'Europe/Rome',
38
+ 'Europe/Amsterdam': 'Europe/Amsterdam',
39
+ 'Europe/Brussels': 'Europe/Brussels',
40
+ 'Europe/Vienna': 'Europe/Vienna',
41
+ 'Europe/Warsaw': 'Europe/Warsaw',
42
+ 'Europe/Prague': 'Europe/Prague',
43
+ 'Europe/Moscow': 'Europe/Moscow',
44
+ 'Europe/Istanbul': 'Europe/Istanbul',
45
+ 'Europe/Athens': 'Europe/Athens',
46
+ 'Europe/Helsinki': 'Europe/Helsinki',
47
+ 'Europe/Stockholm': 'Europe/Stockholm',
48
+ 'Europe/Oslo': 'Europe/Oslo',
49
+ 'Europe/Copenhagen': 'Europe/Copenhagen',
50
+ 'Europe/Dublin': 'Europe/Dublin',
51
+ 'Europe/Zurich': 'Europe/Zurich',
52
+ // Asia
53
+ 'Asia/Tokyo': 'Asia/Tokyo',
54
+ 'Asia/Shanghai': 'Asia/Shanghai',
55
+ 'Asia/Hong_Kong': 'Asia/Hong_Kong',
56
+ 'Asia/Singapore': 'Asia/Singapore',
57
+ 'Asia/Seoul': 'Asia/Seoul',
58
+ 'Asia/Taipei': 'Asia/Taipei',
59
+ 'Asia/Bangkok': 'Asia/Bangkok',
60
+ 'Asia/Jakarta': 'Asia/Jakarta',
61
+ 'Asia/Manila': 'Asia/Manila',
62
+ 'Asia/Kuala_Lumpur': 'Asia/Kuala_Lumpur',
63
+ 'Asia/Ho_Chi_Minh': 'Asia/Ho_Chi_Minh',
64
+ 'Asia/Dubai': 'Asia/Dubai',
65
+ 'Asia/Kolkata': 'Asia/Kolkata',
66
+ 'Asia/Mumbai': 'Asia/Mumbai',
67
+ 'Asia/Karachi': 'Asia/Karachi',
68
+ 'Asia/Dhaka': 'Asia/Dhaka',
69
+ 'Asia/Tehran': 'Asia/Tehran',
70
+ 'Asia/Riyadh': 'Asia/Riyadh',
71
+ 'Asia/Jerusalem': 'Asia/Jerusalem',
72
+ // Australia/Pacific
73
+ 'Australia/Sydney': 'Australia/Sydney',
74
+ 'Australia/Melbourne': 'Australia/Melbourne',
75
+ 'Australia/Brisbane': 'Australia/Brisbane',
76
+ 'Australia/Perth': 'Australia/Perth',
77
+ 'Australia/Adelaide': 'Australia/Adelaide',
78
+ 'Pacific/Auckland': 'Pacific/Auckland',
79
+ 'Pacific/Fiji': 'Pacific/Fiji',
80
+ 'Pacific/Honolulu': 'Pacific/Honolulu',
81
+ // Africa
82
+ 'Africa/Cairo': 'Africa/Cairo',
83
+ 'Africa/Johannesburg': 'Africa/Johannesburg',
84
+ 'Africa/Lagos': 'Africa/Lagos',
85
+ 'Africa/Nairobi': 'Africa/Nairobi',
86
+ 'Africa/Casablanca': 'Africa/Casablanca',
87
+ };
88
+ // ============================================================================
89
+ // ChronosTimezone Class
90
+ // ============================================================================
91
+ /**
92
+ * ChronosTimezone - Handles timezone operations and conversions
93
+ *
94
+ * This class provides comprehensive timezone handling including:
95
+ * - Timezone information retrieval
96
+ * - Offset calculations
97
+ * - DST detection
98
+ * - Timezone conversions
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * // Get timezone info
103
+ * const tz = ChronosTimezone.create('America/New_York');
104
+ * console.log(tz.offset); // -5 or -4 depending on DST
105
+ *
106
+ * // Check DST
107
+ * console.log(tz.isDST(new Date())); // true/false
108
+ *
109
+ * // Convert between timezones
110
+ * const utcDate = new Date();
111
+ * const localDate = ChronosTimezone.convert(utcDate, 'UTC', 'America/New_York');
112
+ * ```
113
+ */
114
+ class ChronosTimezone {
115
+ // ============================================================================
116
+ // Constructor
117
+ // ============================================================================
118
+ /**
119
+ * Create a new ChronosTimezone
120
+ */
121
+ constructor(identifier = 'UTC') {
122
+ this._originalOffset = null;
123
+ this._cachedOffset = null;
124
+ this._cachedDate = null;
125
+ const normalized = this._normalizeIdentifier(identifier);
126
+ this._identifier = normalized.identifier;
127
+ this._originalOffset = normalized.originalOffset;
128
+ }
129
+ /**
130
+ * Normalize timezone identifier
131
+ */
132
+ _normalizeIdentifier(identifier) {
133
+ // Handle UTC aliases
134
+ if (identifier.toUpperCase() === 'Z' ||
135
+ identifier.toUpperCase() === 'GMT') {
136
+ return { identifier: 'UTC', originalOffset: null };
137
+ }
138
+ // Handle offset strings like +05:30, -08:00
139
+ if (/^[+-]\d{2}:\d{2}$/.test(identifier)) {
140
+ // Store original offset and convert to Etc/GMT for internal use
141
+ const offsetHours = this._parseOffsetString(identifier);
142
+ const etcGmt = `Etc/GMT${offsetHours >= 0 ? '-' : '+'}${Math.abs(Math.floor(offsetHours))}`;
143
+ return { identifier: etcGmt, originalOffset: identifier };
144
+ }
145
+ return { identifier, originalOffset: null };
146
+ }
147
+ /**
148
+ * Parse offset string to hours
149
+ */
150
+ _parseOffsetString(offset) {
151
+ const match = offset.match(/^([+-])(\d{2}):(\d{2})$/);
152
+ if (!match)
153
+ return 0;
154
+ const sign = match[1] === '+' ? 1 : -1;
155
+ const hours = parseInt(match[2], 10);
156
+ const minutes = parseInt(match[3], 10);
157
+ return sign * (hours + minutes / 60);
158
+ }
159
+ // ============================================================================
160
+ // Static Factory Methods
161
+ // ============================================================================
162
+ /**
163
+ * Create a timezone instance
164
+ */
165
+ static create(identifier = 'UTC') {
166
+ return new ChronosTimezone(identifier);
167
+ }
168
+ /**
169
+ * Create UTC timezone
170
+ */
171
+ static utc() {
172
+ return new ChronosTimezone('UTC');
173
+ }
174
+ /**
175
+ * Create timezone from local system timezone
176
+ */
177
+ static local() {
178
+ const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
179
+ return new ChronosTimezone(tz);
180
+ }
181
+ /**
182
+ * Create timezone from offset in hours
183
+ */
184
+ static fromOffset(offsetHours) {
185
+ const sign = offsetHours >= 0 ? '+' : '-';
186
+ const absOffset = Math.abs(offsetHours);
187
+ const hours = Math.floor(absOffset);
188
+ const minutes = Math.round((absOffset - hours) * 60);
189
+ const offsetString = `${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
190
+ return new ChronosTimezone(offsetString);
191
+ }
192
+ /**
193
+ * Get the local system timezone identifier
194
+ */
195
+ static localIdentifier() {
196
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
197
+ }
198
+ // ============================================================================
199
+ // Getters
200
+ // ============================================================================
201
+ /**
202
+ * Get timezone identifier
203
+ * Returns the original offset string if created from an offset, otherwise returns the IANA identifier
204
+ */
205
+ get identifier() {
206
+ var _a;
207
+ return (_a = this._originalOffset) !== null && _a !== void 0 ? _a : this._identifier;
208
+ }
209
+ /**
210
+ * Get the internal IANA timezone identifier (used for Intl operations)
211
+ */
212
+ get ianaIdentifier() {
213
+ return this._identifier;
214
+ }
215
+ /**
216
+ * Get timezone name (alias for identifier)
217
+ */
218
+ get name() {
219
+ var _a;
220
+ return (_a = this._originalOffset) !== null && _a !== void 0 ? _a : this._identifier;
221
+ }
222
+ /**
223
+ * Get timezone abbreviation for a given date
224
+ */
225
+ getAbbreviation(date = new Date()) {
226
+ var _a;
227
+ try {
228
+ const formatter = new Intl.DateTimeFormat('en-US', {
229
+ timeZone: this._identifier,
230
+ timeZoneName: 'short',
231
+ });
232
+ const parts = formatter.formatToParts(date);
233
+ const tzPart = parts.find((p) => p.type === 'timeZoneName');
234
+ return (_a = tzPart === null || tzPart === void 0 ? void 0 : tzPart.value) !== null && _a !== void 0 ? _a : this._identifier;
235
+ }
236
+ catch (_b) {
237
+ return this._identifier;
238
+ }
239
+ }
240
+ /**
241
+ * Get full timezone name for a given date
242
+ */
243
+ getFullName(date = new Date()) {
244
+ var _a;
245
+ try {
246
+ const formatter = new Intl.DateTimeFormat('en-US', {
247
+ timeZone: this._identifier,
248
+ timeZoneName: 'long',
249
+ });
250
+ const parts = formatter.formatToParts(date);
251
+ const tzPart = parts.find((p) => p.type === 'timeZoneName');
252
+ return (_a = tzPart === null || tzPart === void 0 ? void 0 : tzPart.value) !== null && _a !== void 0 ? _a : this._identifier;
253
+ }
254
+ catch (_b) {
255
+ return this._identifier;
256
+ }
257
+ }
258
+ // ============================================================================
259
+ // Offset Calculations
260
+ // ============================================================================
261
+ /**
262
+ * Get UTC offset in minutes for a given date
263
+ */
264
+ getOffsetMinutes(date = new Date()) {
265
+ try {
266
+ // Create formatters for UTC and target timezone
267
+ const utcFormatter = new Intl.DateTimeFormat('en-US', {
268
+ timeZone: 'UTC',
269
+ year: 'numeric',
270
+ month: 'numeric',
271
+ day: 'numeric',
272
+ hour: 'numeric',
273
+ minute: 'numeric',
274
+ hour12: false,
275
+ });
276
+ const tzFormatter = new Intl.DateTimeFormat('en-US', {
277
+ timeZone: this._identifier,
278
+ year: 'numeric',
279
+ month: 'numeric',
280
+ day: 'numeric',
281
+ hour: 'numeric',
282
+ minute: 'numeric',
283
+ hour12: false,
284
+ });
285
+ const utcParts = this._parseIntlParts(utcFormatter.formatToParts(date));
286
+ const tzParts = this._parseIntlParts(tzFormatter.formatToParts(date));
287
+ const utcDate = new Date(Date.UTC(utcParts.year, utcParts.month - 1, utcParts.day, utcParts.hour, utcParts.minute));
288
+ const tzDate = new Date(Date.UTC(tzParts.year, tzParts.month - 1, tzParts.day, tzParts.hour, tzParts.minute));
289
+ return (tzDate.getTime() - utcDate.getTime()) / 60000;
290
+ }
291
+ catch (_a) {
292
+ return 0;
293
+ }
294
+ }
295
+ /**
296
+ * Parse Intl formatter parts to components
297
+ */
298
+ _parseIntlParts(parts) {
299
+ const result = { year: 0, month: 0, day: 0, hour: 0, minute: 0 };
300
+ for (const part of parts) {
301
+ switch (part.type) {
302
+ case 'year':
303
+ result.year = parseInt(part.value, 10);
304
+ break;
305
+ case 'month':
306
+ result.month = parseInt(part.value, 10);
307
+ break;
308
+ case 'day':
309
+ result.day = parseInt(part.value, 10);
310
+ break;
311
+ case 'hour':
312
+ result.hour = parseInt(part.value, 10);
313
+ break;
314
+ case 'minute':
315
+ result.minute = parseInt(part.value, 10);
316
+ break;
317
+ }
318
+ }
319
+ return result;
320
+ }
321
+ /**
322
+ * Get UTC offset in hours for a given date
323
+ */
324
+ getOffsetHours(date = new Date()) {
325
+ return this.getOffsetMinutes(date) / 60;
326
+ }
327
+ /**
328
+ * Get UTC offset as string (e.g., "+05:30", "-08:00")
329
+ */
330
+ getOffsetString(date = new Date()) {
331
+ const offsetMinutes = this.getOffsetMinutes(date);
332
+ const sign = offsetMinutes >= 0 ? '+' : '-';
333
+ const absMinutes = Math.abs(offsetMinutes);
334
+ const hours = Math.floor(absMinutes / 60);
335
+ const minutes = absMinutes % 60;
336
+ return `${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
337
+ }
338
+ /**
339
+ * Get complete offset information
340
+ */
341
+ getOffset(date = new Date()) {
342
+ const minutes = this.getOffsetMinutes(date);
343
+ return {
344
+ minutes,
345
+ hours: minutes / 60,
346
+ string: this.getOffsetString(date),
347
+ };
348
+ }
349
+ // ============================================================================
350
+ // DST (Daylight Saving Time)
351
+ // ============================================================================
352
+ /**
353
+ * Check if DST is in effect for a given date
354
+ */
355
+ isDST(date = new Date()) {
356
+ const jan = new Date(date.getFullYear(), 0, 1);
357
+ const jul = new Date(date.getFullYear(), 6, 1);
358
+ const janOffset = this.getOffsetMinutes(jan);
359
+ const julOffset = this.getOffsetMinutes(jul);
360
+ const currentOffset = this.getOffsetMinutes(date);
361
+ // DST is in effect if current offset matches the larger offset
362
+ const standardOffset = Math.min(janOffset, julOffset);
363
+ return currentOffset !== standardOffset;
364
+ }
365
+ /**
366
+ * Check if timezone observes DST
367
+ */
368
+ observesDST() {
369
+ const currentYear = new Date().getFullYear();
370
+ const jan = new Date(currentYear, 0, 15);
371
+ const jul = new Date(currentYear, 6, 15);
372
+ return this.getOffsetMinutes(jan) !== this.getOffsetMinutes(jul);
373
+ }
374
+ /**
375
+ * Get the next DST transition
376
+ */
377
+ getNextDSTTransition(from = new Date()) {
378
+ if (!this.observesDST()) {
379
+ return null;
380
+ }
381
+ const currentOffset = this.getOffsetMinutes(from);
382
+ const checkDate = new Date(from);
383
+ // Search forward up to 1 year
384
+ for (let i = 0; i < 366; i++) {
385
+ checkDate.setDate(checkDate.getDate() + 1);
386
+ const newOffset = this.getOffsetMinutes(checkDate);
387
+ if (newOffset !== currentOffset) {
388
+ // Found a transition, binary search for exact time
389
+ const exactDate = this._findExactTransition(new Date(checkDate.getTime() - 24 * 60 * 60 * 1000), checkDate);
390
+ return {
391
+ date: exactDate,
392
+ fromOffset: currentOffset,
393
+ toOffset: newOffset,
394
+ isDSTStart: newOffset > currentOffset,
395
+ };
396
+ }
397
+ }
398
+ return null;
399
+ }
400
+ /**
401
+ * Binary search to find exact DST transition time
402
+ */
403
+ _findExactTransition(start, end) {
404
+ const startOffset = this.getOffsetMinutes(start);
405
+ while (end.getTime() - start.getTime() > 60000) {
406
+ // Within 1 minute
407
+ const mid = new Date((start.getTime() + end.getTime()) / 2);
408
+ const midOffset = this.getOffsetMinutes(mid);
409
+ if (midOffset === startOffset) {
410
+ start = mid;
411
+ }
412
+ else {
413
+ end = mid;
414
+ }
415
+ }
416
+ return end;
417
+ }
418
+ // ============================================================================
419
+ // Conversion
420
+ // ============================================================================
421
+ /**
422
+ * Convert a date to this timezone (returns formatted string)
423
+ */
424
+ format(date, formatOptions) {
425
+ const options = Object.assign({ timeZone: this._identifier }, formatOptions);
426
+ return new Intl.DateTimeFormat('en-US', options).format(date);
427
+ }
428
+ /**
429
+ * Get date components in this timezone
430
+ */
431
+ getComponents(date) {
432
+ var _a;
433
+ const formatter = new Intl.DateTimeFormat('en-US', {
434
+ timeZone: this._identifier,
435
+ year: 'numeric',
436
+ month: 'numeric',
437
+ day: 'numeric',
438
+ hour: 'numeric',
439
+ minute: 'numeric',
440
+ second: 'numeric',
441
+ weekday: 'short',
442
+ hour12: false,
443
+ });
444
+ const parts = formatter.formatToParts(date);
445
+ const result = {
446
+ year: 0,
447
+ month: 0,
448
+ day: 0,
449
+ hour: 0,
450
+ minute: 0,
451
+ second: 0,
452
+ dayOfWeek: 0,
453
+ };
454
+ const dayMap = {
455
+ Sun: 0,
456
+ Mon: 1,
457
+ Tue: 2,
458
+ Wed: 3,
459
+ Thu: 4,
460
+ Fri: 5,
461
+ Sat: 6,
462
+ };
463
+ for (const part of parts) {
464
+ switch (part.type) {
465
+ case 'year':
466
+ result.year = parseInt(part.value, 10);
467
+ break;
468
+ case 'month':
469
+ result.month = parseInt(part.value, 10);
470
+ break;
471
+ case 'day':
472
+ result.day = parseInt(part.value, 10);
473
+ break;
474
+ case 'hour':
475
+ result.hour = parseInt(part.value, 10);
476
+ break;
477
+ case 'minute':
478
+ result.minute = parseInt(part.value, 10);
479
+ break;
480
+ case 'second':
481
+ result.second = parseInt(part.value, 10);
482
+ break;
483
+ case 'weekday':
484
+ result.dayOfWeek = (_a = dayMap[part.value]) !== null && _a !== void 0 ? _a : 0;
485
+ break;
486
+ }
487
+ }
488
+ return result;
489
+ }
490
+ /**
491
+ * Convert a date from one timezone to another
492
+ */
493
+ static convert(date, from, to) {
494
+ const fromTz = new ChronosTimezone(from);
495
+ const toTz = new ChronosTimezone(to);
496
+ const fromOffset = fromTz.getOffsetMinutes(date);
497
+ const toOffset = toTz.getOffsetMinutes(date);
498
+ const diffMinutes = toOffset - fromOffset;
499
+ return new Date(date.getTime() + diffMinutes * 60000);
500
+ }
501
+ /**
502
+ * Convert a UTC date to this timezone
503
+ */
504
+ fromUTC(date) {
505
+ return ChronosTimezone.convert(date, 'UTC', this._identifier);
506
+ }
507
+ /**
508
+ * Convert a date in this timezone to UTC
509
+ */
510
+ toUTC(date) {
511
+ return ChronosTimezone.convert(date, this._identifier, 'UTC');
512
+ }
513
+ // ============================================================================
514
+ // Information
515
+ // ============================================================================
516
+ /**
517
+ * Get comprehensive timezone information
518
+ */
519
+ getInfo(date = new Date()) {
520
+ var _a;
521
+ return {
522
+ identifier: (_a = this._originalOffset) !== null && _a !== void 0 ? _a : this._identifier,
523
+ abbreviation: this.getAbbreviation(date),
524
+ name: this.getFullName(date),
525
+ offset: this.getOffset(date),
526
+ isDST: this.isDST(date),
527
+ observesDST: this.observesDST(),
528
+ };
529
+ }
530
+ /**
531
+ * Check if two timezones are equivalent at a given moment
532
+ */
533
+ equals(other, date = new Date()) {
534
+ const otherTz = typeof other === 'string' ? new ChronosTimezone(other) : other;
535
+ return this.getOffsetMinutes(date) === otherTz.getOffsetMinutes(date);
536
+ }
537
+ /**
538
+ * Check if this is the same timezone identifier
539
+ */
540
+ isSame(other) {
541
+ const otherIdentifier = typeof other === 'string' ? other : other.identifier;
542
+ return this.identifier === otherIdentifier;
543
+ }
544
+ // ============================================================================
545
+ // Static Utilities
546
+ // ============================================================================
547
+ /**
548
+ * Get all available timezone identifiers
549
+ * Note: This returns common timezones. Use Intl.supportedValuesOf('timeZone') for all.
550
+ */
551
+ static getAvailableTimezones() {
552
+ // Try to use the native method if available
553
+ if (typeof Intl !== 'undefined' && 'supportedValuesOf' in Intl) {
554
+ try {
555
+ return Intl.supportedValuesOf('timeZone');
556
+ }
557
+ catch (_a) {
558
+ // Fall back to predefined list
559
+ }
560
+ }
561
+ return Object.values(exports.TIMEZONES);
562
+ }
563
+ /**
564
+ * Check if a timezone identifier is valid
565
+ */
566
+ static isValid(identifier) {
567
+ try {
568
+ new Intl.DateTimeFormat('en-US', { timeZone: identifier });
569
+ return true;
570
+ }
571
+ catch (_a) {
572
+ return false;
573
+ }
574
+ }
575
+ /**
576
+ * Get timezones grouped by region
577
+ */
578
+ static getTimezonesByRegion() {
579
+ const timezones = ChronosTimezone.getAvailableTimezones();
580
+ const grouped = {};
581
+ for (const tz of timezones) {
582
+ const parts = tz.split('/');
583
+ const region = parts[0];
584
+ if (!grouped[region]) {
585
+ grouped[region] = [];
586
+ }
587
+ grouped[region].push(tz);
588
+ }
589
+ return grouped;
590
+ }
591
+ /**
592
+ * Find timezones that match a given offset
593
+ */
594
+ static findByOffset(offsetHours, date = new Date()) {
595
+ const targetMinutes = offsetHours * 60;
596
+ const result = [];
597
+ for (const tz of ChronosTimezone.getAvailableTimezones()) {
598
+ const timezone = new ChronosTimezone(tz);
599
+ if (timezone.getOffsetMinutes(date) === targetMinutes) {
600
+ result.push(timezone);
601
+ }
602
+ }
603
+ return result;
604
+ }
605
+ /**
606
+ * Get current time in a specific timezone
607
+ */
608
+ static now(identifier) {
609
+ const tz = new ChronosTimezone(identifier);
610
+ return tz.fromUTC(new Date());
611
+ }
612
+ // ============================================================================
613
+ // Serialization
614
+ // ============================================================================
615
+ /**
616
+ * Convert to string
617
+ */
618
+ toString() {
619
+ var _a;
620
+ return (_a = this._originalOffset) !== null && _a !== void 0 ? _a : this._identifier;
621
+ }
622
+ /**
623
+ * Convert to JSON
624
+ */
625
+ toJSON() {
626
+ var _a;
627
+ const now = new Date();
628
+ return {
629
+ identifier: (_a = this._originalOffset) !== null && _a !== void 0 ? _a : this._identifier,
630
+ offset: this.getOffsetString(now),
631
+ isDST: this.isDST(now),
632
+ observesDST: this.observesDST(),
633
+ };
634
+ }
635
+ /**
636
+ * Get primitive value
637
+ */
638
+ valueOf() {
639
+ var _a;
640
+ return (_a = this._originalOffset) !== null && _a !== void 0 ? _a : this._identifier;
641
+ }
642
+ }
643
+ exports.ChronosTimezone = ChronosTimezone;
644
+ // ============================================================================
645
+ // Common Timezone Aliases
646
+ // ============================================================================
647
+ /**
648
+ * Pre-created timezone instances for common timezones
649
+ */
650
+ exports.Timezones = {
651
+ UTC: ChronosTimezone.utc(),
652
+ Local: ChronosTimezone.local(),
653
+ // US
654
+ Eastern: ChronosTimezone.create('America/New_York'),
655
+ Central: ChronosTimezone.create('America/Chicago'),
656
+ Mountain: ChronosTimezone.create('America/Denver'),
657
+ Pacific: ChronosTimezone.create('America/Los_Angeles'),
658
+ // Europe
659
+ London: ChronosTimezone.create('Europe/London'),
660
+ Paris: ChronosTimezone.create('Europe/Paris'),
661
+ Berlin: ChronosTimezone.create('Europe/Berlin'),
662
+ // Asia
663
+ Tokyo: ChronosTimezone.create('Asia/Tokyo'),
664
+ Shanghai: ChronosTimezone.create('Asia/Shanghai'),
665
+ Singapore: ChronosTimezone.create('Asia/Singapore'),
666
+ Dubai: ChronosTimezone.create('Asia/Dubai'),
667
+ Mumbai: ChronosTimezone.create('Asia/Kolkata'),
668
+ // Australia/Pacific
669
+ Sydney: ChronosTimezone.create('Australia/Sydney'),
670
+ Auckland: ChronosTimezone.create('Pacific/Auckland'),
671
+ };