@lbd-sh/date-tz 1.0.9 → 1.0.11

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 LBD Srl
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # Date TZ ⏰✨
2
2
 
3
- `DateTz` is the timezone swiss‑army knife for modern JavaScript and TypeScript projects. It keeps minute-precision timestamps aligned with IANA zones, gracefully glides across daylight-saving transitions, and exposes a lightweight API that feels familiar yet powerful. Whether you are building dashboards, schedulers, or automation pipelines, DateTz keeps your time math honest. 🌍
3
+ <p align="center">
4
+ <a href="https://www.transfeero.com" target="_blank" rel="noopener">
5
+ <img src="https://transfeeropublic.s3.eu-west-1.amazonaws.com/logo_transfeero_final_black.png" alt="Transfeero" height="60" />
6
+ </a>
7
+ </p>
8
+
9
+ `DateTz` is the timezone swiss‑army knife for modern JavaScript and TypeScript projects. It keeps minute-precision timestamps aligned with IANA zones, gracefully glides across daylight-saving transitions, and exposes a lightweight API that feels familiar yet powerful. Whether you are building dashboards, schedulers, or automation pipelines, DateTz keeps your time math honest. 🌍 DateTz is maintained and proudly sponsored by [Transfeero](https://www.transfeero.com), the premium airport transfer platform.
4
10
 
5
11
  ---
6
12
 
@@ -352,4 +358,7 @@ Community feedback keeps DateTz sharp—thanks for being part of it! 🙌
352
358
 
353
359
  ## License
354
360
 
355
- ISC © lbd-sh
361
+ MIT © lbd-sh
362
+
363
+ Created with ❤️ by [Transfeero](https://www.transfeero.com) and friends.
364
+ Offered by **LBD Srl** · [www.lbdsh.com](https://www.lbdsh.com)
package/package.json CHANGED
@@ -2,15 +2,18 @@
2
2
  "name": "@lbd-sh/date-tz",
3
3
  "displayName": "Date TZ",
4
4
  "engineStrict": false,
5
- "version": "1.0.9",
5
+ "version": "1.0.11",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "scripts": {
9
9
  "build": "tsc",
10
- "test": "echo \"Error: no test specified\" && exit 1"
10
+ "test": "vitest run"
11
11
  },
12
12
  "devDependencies": {
13
- "typescript": "^5.7.2"
13
+ "@types/node": "^24.9.2",
14
+ "ts-node": "^10.9.2",
15
+ "typescript": "^5.7.2",
16
+ "vitest": "^4.0.6"
14
17
  },
15
18
  "description": "A lightweight JavaScript/TypeScript date-time utility with full timezone support, custom formatting, parsing, and manipulation features.",
16
19
  "keywords": [
@@ -51,5 +54,5 @@
51
54
  "url": "git+https://github.com/lbdsh/date-tz.git"
52
55
  },
53
56
  "markdown": "github",
54
- "license": "ISC"
57
+ "license": "MIT"
55
58
  }
@@ -1,213 +1,206 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { IDateTz } from './idate-tz';
1
3
  import { DateTz } from './date-tz';
2
4
 
3
- describe('DateTz', () => {
4
- it('should create an instance with the correct date and timezone', () => {
5
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
6
- expect(dateTz.datetime).toBe(1609459200000);
7
- expect(dateTz.timezone).toBe(0);
8
- });
9
-
10
- it('should compare two DateTz instances with the same timezone', () => {
11
- const dateTz1 = new DateTz(1609459200000, 0);
12
- const dateTz2 = new DateTz(1609545600000, 0); // 2021-01-02 00:00:00 UTC
13
- expect(dateTz1.compare(dateTz2)).toBeLessThan(0);
14
- });
15
-
16
- it('should throw an error when comparing two DateTz instances with different timezones', () => {
17
- const dateTz1 = new DateTz(1609459200000, 0);
18
- const dateTz2 = new DateTz(1609459200000, 1);
19
- expect(() => dateTz1.compare(dateTz2)).toThrow('Cannot compare dates with different timezones');
20
- });
21
-
22
- it('should format the date correctly with the default pattern', () => {
23
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
24
- expect(dateTz.toString()).toBe('2021-01-01 00:00:00');
25
- });
26
-
27
- it('should format the date correctly with a custom pattern', () => {
28
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
29
- expect(dateTz.toString('DD/MM/YYYY')).toBe('01/01/2021');
30
- });
31
-
32
- it('should add minutes correctly', () => {
33
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
34
- dateTz.add(30, 'minute');
35
- expect(dateTz.toString()).toBe('2021-01-01 00:30:00');
36
- });
37
-
38
- it('should add hours correctly', () => {
39
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
40
- dateTz.add(2, 'hour');
41
- expect(dateTz.toString()).toBe('2021-01-01 02:00:00');
42
- });
5
+ const BASE_TIMESTAMP = Date.UTC(2021, 0, 1, 0, 0); // 2021-01-01 00:00 UTC
43
6
 
44
- it('should add days correctly', () => {
45
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
46
- dateTz.add(1, 'day');
47
- expect(dateTz.toString()).toBe('2021-01-02 00:00:00');
7
+ describe('DateTz', () => {
8
+ it('creates an instance from a timestamp and timezone', () => {
9
+ const dateTz = new DateTz(BASE_TIMESTAMP, 'UTC');
10
+ expect(dateTz.timestamp).toBe(BASE_TIMESTAMP);
11
+ expect(dateTz.timezone).toBe('UTC');
48
12
  });
49
13
 
50
- it('should add months correctly', () => {
51
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
52
- dateTz.add(1, 'month');
53
- expect(dateTz.toString()).toBe('2021-02-01 00:00:00');
14
+ it('creates an instance from an IDateTz-like object', () => {
15
+ const dateTz = new DateTz({ timestamp: BASE_TIMESTAMP, timezone: 'Europe/Rome' });
16
+ expect(dateTz.timestamp).toBe(BASE_TIMESTAMP);
17
+ expect(dateTz.timezone).toBe('Europe/Rome');
54
18
  });
55
19
 
56
- it('should add years correctly', () => {
57
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
58
- dateTz.add(1, 'year');
59
- expect(dateTz.toString()).toBe('2022-01-01 00:00:00');
20
+ it('compares two instances in the same timezone', () => {
21
+ const earlier = new DateTz(BASE_TIMESTAMP, 'UTC');
22
+ const later = new DateTz(BASE_TIMESTAMP + 24 * 60 * 60 * 1000, 'UTC');
23
+ expect(earlier.compare(later)).toBeLessThan(0);
60
24
  });
61
25
 
62
- it('should return the correct year', () => {
63
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
64
- expect(dateTz.year).toBe(2021);
26
+ it('returns zero when comparing identical timestamps', () => {
27
+ const a = new DateTz(BASE_TIMESTAMP, 'UTC');
28
+ const b = new DateTz(BASE_TIMESTAMP, 'UTC');
29
+ expect(a.compare(b)).toBe(0);
65
30
  });
66
31
 
67
- it('should return the correct month', () => {
68
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
69
- expect(dateTz.month).toBe(0); // January
32
+ it('compares against plain IDateTz objects', () => {
33
+ const deltaMinutes = 5;
34
+ const a = new DateTz(BASE_TIMESTAMP + deltaMinutes * 60_000, 'UTC');
35
+ const other: IDateTz = { timestamp: BASE_TIMESTAMP, timezone: 'UTC' };
36
+ expect(a.compare(other)).toBe(deltaMinutes * 60_000);
70
37
  });
71
38
 
72
- it('should return the correct day', () => {
73
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
74
- expect(dateTz.day).toBe(1);
39
+ it('throws when comparing instances from different timezones', () => {
40
+ const utc = new DateTz(BASE_TIMESTAMP, 'UTC');
41
+ const rome = new DateTz(BASE_TIMESTAMP, 'Europe/Rome');
42
+ expect(() => utc.compare(rome)).toThrow('Cannot compare dates with different timezones');
75
43
  });
76
44
 
77
- it('should return the correct hour', () => {
78
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
79
- expect(dateTz.hour).toBe(0);
45
+ it('formats using the default pattern', () => {
46
+ const dateTz = new DateTz(BASE_TIMESTAMP, 'UTC');
47
+ expect(dateTz.toString()).toBe('2021-01-01 00:00:00');
80
48
  });
81
49
 
82
- it('should return the correct minute', () => {
83
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
84
- expect(dateTz.minute).toBe(0);
50
+ it('rounds timestamps down to the nearest minute', () => {
51
+ const withSeconds = BASE_TIMESTAMP + 45_000 + 500;
52
+ const dateTz = new DateTz(withSeconds, 'UTC');
53
+ expect(dateTz.timestamp).toBe(BASE_TIMESTAMP);
54
+ expect(dateTz.toString()).toBe('2021-01-01 00:00:00');
85
55
  });
86
56
 
87
- it('should create an instance with the correct date and timezone', () => {
88
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
89
- expect(dateTz.datetime).toBe(1609459200000);
90
- expect(dateTz.timezone).toBe(0);
57
+ it('formats using a custom pattern and timezone token', () => {
58
+ const dateTz = new DateTz(BASE_TIMESTAMP, 'Europe/Rome');
59
+ expect(dateTz.toString('DD/MM/YYYY HH:mm tz')).toBe('01/01/2021 01:00 Europe/Rome');
91
60
  });
92
61
 
93
- it('should compare two DateTz instances with the same timezone', () => {
94
- const dateTz1 = new DateTz(1609459200000, 0);
95
- const dateTz2 = new DateTz(1609545600000, 0); // 2021-01-02 00:00:00 UTC
96
- expect(dateTz1.compare(dateTz2)).toBeLessThan(0);
62
+ it('formats using month names and 12-hour tokens', () => {
63
+ const dateTz = new DateTz(BASE_TIMESTAMP, 'UTC');
64
+ expect(dateTz.toString('LM DD, YYYY hh:mm aa')).toBe('January 01, 2021 12:00 am');
97
65
  });
98
66
 
99
- it('should throw an error when comparing two DateTz instances with different timezones', () => {
100
- const dateTz1 = new DateTz(1609459200000, 0);
101
- const dateTz2 = new DateTz(1609459200000, 1);
102
- expect(() => dateTz1.compare(dateTz2)).toThrow('Cannot compare dates with different timezones');
67
+ it('retains chaining behaviour for add', () => {
68
+ const dateTz = new DateTz(BASE_TIMESTAMP, 'UTC');
69
+ const result = dateTz.add(1, 'day');
70
+ expect(result).toBe(dateTz);
103
71
  });
104
72
 
105
- it('should format the date correctly with the default pattern', () => {
106
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
107
- expect(dateTz.toString()).toBe('2021-01-01 00:00:00');
108
- });
109
-
110
- it('should format the date correctly with a custom pattern', () => {
111
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
112
- expect(dateTz.toString('DD/MM/YYYY')).toBe('01/01/2021');
73
+ it('adds time in different units', () => {
74
+ const dateTz = new DateTz(BASE_TIMESTAMP, 'UTC');
75
+ dateTz.add(90, 'minute'); // +1h30
76
+ expect(dateTz.toString()).toBe('2021-01-01 01:30:00');
77
+ dateTz.add(1, 'day');
78
+ expect(dateTz.toString()).toBe('2021-01-02 01:30:00');
79
+ dateTz.add(1, 'month');
80
+ expect(dateTz.toString()).toBe('2021-02-02 01:30:00');
81
+ dateTz.add(1, 'year');
82
+ expect(dateTz.toString()).toBe('2022-02-02 01:30:00');
113
83
  });
114
84
 
115
- it('should add minutes correctly', () => {
116
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
117
- dateTz.add(30, 'minute');
118
- expect(dateTz.toString()).toBe('2021-01-01 00:30:00');
85
+ it('sets specific components of the date', () => {
86
+ const dateTz = new DateTz(BASE_TIMESTAMP, 'UTC');
87
+ dateTz.set(2023, 'year')
88
+ .set(2, 'month') // February (1-based)
89
+ .set(15, 'day')
90
+ .set(9, 'hour')
91
+ .set(45, 'minute');
92
+ expect(dateTz.toString()).toBe('2023-02-15 09:45:00');
119
93
  });
120
94
 
121
- it('should add hours correctly', () => {
122
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
123
- dateTz.add(2, 'hour');
124
- expect(dateTz.toString()).toBe('2021-01-01 02:00:00');
95
+ it('handles leap year arithmetic when adding days', () => {
96
+ const leap = new DateTz(Date.UTC(2020, 1, 28, 0, 0), 'UTC');
97
+ leap.add(1, 'day');
98
+ expect(leap.toString()).toBe('2020-02-29 00:00:00');
99
+ leap.add(1, 'day');
100
+ expect(leap.toString()).toBe('2020-03-01 00:00:00');
125
101
  });
126
102
 
127
- it('should add days correctly', () => {
128
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
129
- dateTz.add(1, 'day');
130
- expect(dateTz.toString()).toBe('2021-01-02 00:00:00');
103
+ it('parses a date string with a custom pattern', () => {
104
+ const parsed = DateTz.parse('2021-01-05 18:30:00', 'YYYY-MM-DD HH:mm:ss', 'UTC');
105
+ expect(parsed.toString()).toBe('2021-01-05 18:30:00');
106
+ expect(parsed.timezone).toBe('UTC');
131
107
  });
132
108
 
133
- it('should add months correctly', () => {
134
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
135
- dateTz.add(1, 'month');
136
- expect(dateTz.toString()).toBe('2021-02-01 00:00:00');
109
+ it('parses using a non-UTC timezone', () => {
110
+ const parsed = DateTz.parse('2021-01-05 18:30:00', 'YYYY-MM-DD HH:mm:ss', 'Europe/Rome');
111
+ expect(parsed.timezone).toBe('Europe/Rome');
112
+ expect(parsed.toString('YYYY-MM-DD HH:mm tz')).toBe('2021-01-05 18:30 Europe/Rome');
137
113
  });
138
114
 
139
- it('should add years correctly', () => {
140
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
141
- dateTz.add(1, 'year');
142
- expect(dateTz.toString()).toBe('2022-01-01 00:00:00');
115
+ it('throws when parsing a 12-hour pattern without an AM/PM marker', () => {
116
+ expect(() => DateTz.parse('2021-01-05 06:30', 'YYYY-MM-DD hh:mm', 'UTC'))
117
+ .toThrow('AM/PM marker (aa or AA) is required when using 12-hour format (hh)');
143
118
  });
144
119
 
145
- it('should return the correct year', () => {
146
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
147
- expect(dateTz.year).toBe(2021);
120
+ it('throws when parsing with an unknown timezone', () => {
121
+ expect(() => DateTz.parse('2021-01-05 06:30:00', 'YYYY-MM-DD HH:mm:ss', 'Mars/Phobos'))
122
+ .toThrow('Invalid timezone: Mars/Phobos');
148
123
  });
149
124
 
150
- it('should return the correct month', () => {
151
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
152
- expect(dateTz.month).toBe(0); // January
125
+ it('clones to a different timezone without mutating the original', () => {
126
+ const original = new DateTz(BASE_TIMESTAMP, 'UTC');
127
+ const clone = original.cloneToTimezone('Europe/Rome');
128
+ expect(original.timezone).toBe('UTC');
129
+ expect(clone.timezone).toBe('Europe/Rome');
130
+ expect(clone.toString()).toBe('2021-01-01 01:00:00');
131
+ expect(clone.timestamp).toBe(original.timestamp);
132
+ expect(clone).not.toBe(original);
153
133
  });
154
134
 
155
- it('should return the correct day', () => {
156
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
157
- expect(dateTz.day).toBe(1);
135
+ it('converts to a different timezone in place', () => {
136
+ const dateTz = new DateTz(BASE_TIMESTAMP, 'UTC');
137
+ const originalTimestamp = dateTz.timestamp;
138
+ const result = dateTz.convertToTimezone('Europe/Rome');
139
+ expect(result).toBe(dateTz);
140
+ expect(dateTz.timezone).toBe('Europe/Rome');
141
+ expect(dateTz.toString()).toBe('2021-01-01 01:00:00');
142
+ expect(dateTz.timestamp).toBe(originalTimestamp);
158
143
  });
159
144
 
160
- it('should return the correct hour', () => {
161
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
162
- expect(dateTz.hour).toBe(0);
145
+ it('exposes timezone offset information', () => {
146
+ const la = new DateTz(BASE_TIMESTAMP, 'America/Los_Angeles');
147
+ expect(la.timezoneOffset).toEqual({ sdt: -28800, dst: -25200 });
163
148
  });
164
149
 
165
- it('should return the correct minute', () => {
166
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
167
- expect(dateTz.minute).toBe(0);
150
+ it('reports comparability correctly', () => {
151
+ const utc = new DateTz(BASE_TIMESTAMP, 'UTC');
152
+ const rome = new DateTz(BASE_TIMESTAMP, 'Europe/Rome');
153
+ expect(utc.isComparable(rome)).toBe(false);
154
+ expect(utc.isComparable(new DateTz(BASE_TIMESTAMP, 'UTC'))).toBe(true);
155
+ const plain: IDateTz = { timestamp: BASE_TIMESTAMP, timezone: 'UTC' };
156
+ expect(utc.isComparable(plain)).toBe(true);
168
157
  });
169
158
 
170
- it('should parse a date string correctly', () => {
171
- const dateTz = DateTz.parse('2021--01-01 00:00:00', 'YYYY--MM-DD HH:mm', 0);
172
- expect(dateTz.datetime).toBe(1609459200000);
173
- expect(dateTz.timezone).toBe(0);
159
+ it('exposes date parts adjusted for timezone', () => {
160
+ const rome = new DateTz(BASE_TIMESTAMP, 'Europe/Rome');
161
+ expect(rome.year).toBe(2021);
162
+ expect(rome.month).toBe(0);
163
+ expect(rome.day).toBe(1);
164
+ expect(rome.hour).toBe(1);
165
+ expect(rome.minute).toBe(0);
166
+ expect(rome.dayOfWeek).toBe(5);
174
167
  });
175
168
 
176
- it('should set the year correctly', () => {
177
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
178
- dateTz.set(2022, 'year');
179
- expect(dateTz.toString()).toBe('2022-01-01 00:00:00');
169
+ it('detects daylight saving time boundaries', () => {
170
+ const winter = new DateTz(Date.UTC(2021, 0, 1, 20, 0), 'America/Los_Angeles');
171
+ const summer = new DateTz(Date.UTC(2021, 6, 1, 19, 0), 'America/Los_Angeles');
172
+ expect(winter.isDst).toBe(false);
173
+ expect(summer.isDst).toBe(true);
180
174
  });
181
175
 
182
- it('should set the month correctly', () => {
183
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
184
- dateTz.set(2, 'month');
185
- expect(dateTz.toString()).toBe('2021-02-01 00:00:00');
176
+ it('reports isDst as false for timezones without daylight saving time', () => {
177
+ const accra = new DateTz(BASE_TIMESTAMP, 'Africa/Accra');
178
+ expect(accra.isDst).toBe(false);
186
179
  });
187
180
 
188
- it('should set the day correctly', () => {
189
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
190
- dateTz.set(2, 'day');
191
- expect(dateTz.toString()).toBe('2021-01-02 00:00:00');
181
+ it('instantiates via now with the requested timezone', () => {
182
+ const current = DateTz.now('Europe/Rome');
183
+ expect(current.timezone).toBe('Europe/Rome');
192
184
  });
193
185
 
194
- it('should set the hour correctly', () => {
195
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
196
- dateTz.set(2, 'hour');
197
- expect(dateTz.toString()).toBe('2021-01-01 02:00:00');
186
+ it('defaults to UTC when calling now without arguments', () => {
187
+ const current = DateTz.now();
188
+ expect(current.timezone).toBe('UTC');
198
189
  });
199
190
 
200
- it('should set the minute correctly', () => {
201
- const dateTz = new DateTz(1609459200000, 0); // 2021-01-01 00:00:00 UTC
202
- dateTz.set(30, 'minute');
203
- expect(dateTz.toString()).toBe('2021-01-01 00:30:00');
191
+ it('rejects unknown timezones on construction and conversion', () => {
192
+ expect(() => new DateTz(BASE_TIMESTAMP, 'Mars/Phobos')).toThrow('Invalid timezone: Mars/Phobos');
193
+ const dateTz = new DateTz(BASE_TIMESTAMP, 'UTC');
194
+ expect(() => dateTz.convertToTimezone('Mars/Phobos')).toThrow('Invalid timezone: Mars/Phobos');
204
195
  });
205
196
 
206
- it('should convert timezone name to offset correctly', () => {
207
- expect(DateTz.tzNameToOffset('PST')).toBe(-8);
197
+ it('rejects unknown timezones when cloning', () => {
198
+ const dateTz = new DateTz(BASE_TIMESTAMP, 'UTC');
199
+ expect(() => dateTz.cloneToTimezone('Mars/Phobos')).toThrow('Invalid timezone: Mars/Phobos');
208
200
  });
209
201
 
210
- it('should convert timezone offset to name correctly', () => {
211
- expect(DateTz.tzOffsetToName(-8)).toBe('PST');
202
+ it('rejects conversion to plain offsets by id mismatch', () => {
203
+ const dateTz = new DateTz(BASE_TIMESTAMP, 'UTC');
204
+ expect(() => dateTz.convertToTimezone('GMT+1')).toThrow('Invalid timezone: GMT+1');
212
205
  });
213
- });
206
+ });