| 
									
										
										
										
											2021-05-28 00:17:38 -06:00
										 |  |  | # [xtz.js](https://github.com/therootcompany/tz.js)
 | 
					
						
							| 
									
										
										
										
											2019-06-12 08:39:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 00:57:42 -06:00
										 |  |  | A fast, lightweight, zero-dependency library to translate between Time Zones and UTC with native `Intl.DateTimeFormat` | 
					
						
							|  |  |  | in ~100 LoC. For Node.js & Browsers. | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 02:04:29 -06:00
										 |  |  | [](https://therootcompany.github.io/tz.js/) | 
					
						
							| 
									
										
										
										
											2021-05-28 02:03:41 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 08:08:53 -06:00
										 |  |  | XTZ is a poor man's `Temporal` polyfill, but just for time zones. \ | 
					
						
							| 
									
										
										
										
											2021-05-28 02:03:41 -06:00
										 |  |  | Demo: <https://therootcompany.github.io/tz.js/> | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:29:07 -07:00
										 |  |  | ```js | 
					
						
							| 
									
										
										
										
											2022-03-09 23:52:13 -07:00
										 |  |  | // What's the current time, in ISO+Offset format? | 
					
						
							| 
									
										
										
										
											2022-03-09 23:29:07 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | TZ.toLocalISOString(new Date()); // "2021-11-07T03:15:59.000-0500" | 
					
						
							|  |  |  | TZ.timeZone(); // "America/New_York" | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | ```js | 
					
						
							| 
									
										
										
										
											2022-03-09 23:52:13 -07:00
										 |  |  | // What will the ISO+Offset datetime string be | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | // when it's 3:15am in New York? | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2022-03-09 23:52:13 -07:00
										 |  |  | // (Relative New York time to Absolute ISO+Offset Time) | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | TZ.toOffsetISOString("2021-11-07 03:15:59.000", "America/New_York"); | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | // "2021-11-07T03:15:59.000-0500" | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | // What time will it be in New York | 
					
						
							|  |  |  | // when it's 7:15am UTC? | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2022-03-09 23:52:13 -07:00
										 |  |  | // (Absolute UTC Zulu time to Relative New York time) | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | TZ.toTimeZoneISOString("2021-03-14T07:15:59.000Z", "America/New_York"); | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | // "2021-03-14T03:15:59.000-0400" | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Features
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:52:13 -07:00
										 |  |  | - [x] Translate a UTC Zulu time to a Time Zone | 
					
						
							|  |  |  | - [x] Translate a Zoned time to ISO+Offset | 
					
						
							| 
									
										
										
										
											2021-05-28 00:57:42 -06:00
										 |  |  | - [x] Handles **Daylight Savings**, Weird Time Zones, etc... | 
					
						
							|  |  |  |   - [x] Well-tested `npm run test` | 
					
						
							|  |  |  | - [x] Lightweight (No deps) | 
					
						
							|  |  |  |   - 5kb Source + Comments | 
					
						
							|  |  |  |   - 2.5kb Minified | 
					
						
							|  |  |  |   - <1kb `gzip`d | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 00:42:21 -06:00
										 |  |  | Compatible with Browsers, and Node.js. | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 00:42:21 -06:00
										 |  |  | ## Browsers
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 00:42:21 -06:00
										 |  |  | ```html | 
					
						
							|  |  |  | <script src="https://unpkg.com/xtz@latest/xtz.min.js"></script> | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2021-05-28 00:42:21 -06:00
										 |  |  | var TZ = window.XTZ; | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 00:42:21 -06:00
										 |  |  | ## Node.js & Webpack
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 00:42:21 -06:00
										 |  |  | ```bash | 
					
						
							|  |  |  | npm install --save xtz | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2021-05-28 00:42:21 -06:00
										 |  |  | var TZ = require("xtz"); | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 02:03:41 -06:00
										 |  |  | ## Demo
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | See <https://therootcompany.github.io/tz.js/>. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-09 03:00:25 -06:00
										 |  |  | ## How was this built?
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | I live-streamed the creation of this entire project. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If you'd like to learn how I did it and what challenges I encountered, you can watch here: | 
					
						
							|  |  |  | https://www.youtube.com/playlist?list=PLxki0D-ilnqa6horOJ2G18WMZlJeQFlAt | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | (though there have been a few minor updates and bug fixes off-camera) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | # API
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:29:07 -07:00
										 |  |  | - `toLocalISOString(dateOrNull)` | 
					
						
							| 
									
										
										
										
											2021-05-28 00:57:42 -06:00
										 |  |  | - `toTimeZone(utcDate, timeZone)` | 
					
						
							|  |  |  | - `toTimeZoneISOString(isoString, timeZone)` | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | - `fromTimeZone(dtString, timeZone)` | 
					
						
							|  |  |  | - `toOffsetISOString(dtString, timeZone)` | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## `toTimeZone(utcDate, timeZone)`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | > Convert UTC into a Target Time Zone
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:52:13 -07:00
										 |  |  | Use ISO timestamps representing the absolute UTC time (ISO with or without offset): | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```txt | 
					
						
							|  |  |  | "2021-11-07T08:15:59.000Z" | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | ```js | 
					
						
							|  |  |  | var utcDate = TZ.toTimeZone("2021-03-14T07:15:59.000Z", "America/New_York"); | 
					
						
							|  |  |  | // { | 
					
						
							|  |  |  | //   year: 2021, month: 2, day: 14, | 
					
						
							|  |  |  | //   hour: 3, minute: 15, second: 59, millisecond: 0, | 
					
						
							|  |  |  | //   offset: -240, timeZoneName: "Eastern Daylight Time" | 
					
						
							|  |  |  | // } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | utcDate.toISOString(); | 
					
						
							|  |  |  | // "2021-03-14T03:15:59.000-0400" | 
					
						
							|  |  |  | // (same as "2021-11-07T07:15:59.000Z") | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Convert directly to an ISO String:
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | TZ.toTimeZoneISOString("2021-11-07T08:15:59.000Z", "America/New_York"); | 
					
						
							|  |  |  | // "2021-11-07T03:15:59.000-0500" | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | ### Or use our bespoke (custom) date object:
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | var tzDate = TZ.toTimeZone("2021-11-07T08:15:59.000Z", "America/New_York"); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:52:13 -07:00
										 |  |  | ### You can also use a date object with an absolute ISO time:
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | var tzDate = TZ.toTimeZone( | 
					
						
							| 
									
										
										
										
											2021-05-28 00:57:42 -06:00
										 |  |  |   new Date("2021-11-07T08:15:59.000Z"), | 
					
						
							|  |  |  |   "America/New_York" | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | ); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | console.log(tzDate.toISOString()); | 
					
						
							|  |  |  | // "2021-11-07T03:15:59.000-0500" | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | ### Our ISO Strings + Offsets work with JavaScript's native Date object!!
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | new Date("2021-11-07T03:15:59.000-0500").toISOString()); | 
					
						
							|  |  |  | // "2021-11-07T08:15:59.000Z" | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | ## `fromTimeZone(dtString, timeZone)`
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:52:13 -07:00
										 |  |  | > Convert a Target Time Zone into ISO
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | Use ISO-like timestamps representing the _local_ time in the target time zone: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```txt | 
					
						
							| 
									
										
										
										
											2021-05-28 02:14:13 -06:00
										 |  |  | "2021-11-0 03:15:59.000" | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | ```js | 
					
						
							|  |  |  | var tzDate = TZ.fromTimeZone("2021-11-07 03:15:59.000", "America/New_York"); | 
					
						
							|  |  |  | // { | 
					
						
							|  |  |  | //   year: 2021, month: 10, day: 7, | 
					
						
							|  |  |  | //   hour: 3, minute: 15, second: 59, millisecond: 0, | 
					
						
							|  |  |  | //   offset: -300, timeZoneName: "Eastern Standard Time" | 
					
						
							|  |  |  | // } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | tzDate.toISOString(); | 
					
						
							|  |  |  | // "2021-11-07T03:15:59.000-0500" | 
					
						
							|  |  |  | // (same as "2021-11-07T08:15:59.000Z") | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Convert directly to an offset ISO String:
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | TZ.toOffsetISOString("2021-11-07 03:15:59.000", "America/New_York"); | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | // "2021-11-07T03:15:59.000-0500" | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | ### Or our bespoke date object:
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | var utcDate = TZ.fromTimeZone("2021-11-07 03:15:59.000", "America/New_York"); | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | ### Use a Date as a source time
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 00:57:42 -06:00
										 |  |  | You can also use a date object as the source time, but the date's UTC time will be treated as **_relative to time | 
					
						
							|  |  |  | zone_** rather than absolute (this is a workaround for JavaScript's lack of bi-directional timezone support). | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  | var utcDate = TZ.fromTimeZone( | 
					
						
							| 
									
										
										
										
											2021-05-28 00:57:42 -06:00
										 |  |  |   new Date("2021-11-07T03:15:59.000Z"), | 
					
						
							|  |  |  |   "America/New_York" | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | ); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | utcDate.toISOString(); | 
					
						
							|  |  |  | // "2021-11-07T03:15:59.000-0500" | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Daylight Savings / Edge Cases
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | > In 2021 Daylight Savings (in the US)
 | 
					
						
							|  |  |  | > | 
					
						
							| 
									
										
										
										
											2021-05-28 08:08:53 -06:00
										 |  |  | > - begins at 2am on March 14th (skips to 3am)
 | 
					
						
							|  |  |  | > - ends at 2am on November 7th (resets to 1am)
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | > | 
					
						
							|  |  |  | > See <https://www.timeanddate.com/time/change/usa>.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Q: What happens in March when 2am is skipped? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 00:57:42 -06:00
										 |  |  | - A: Although 2am is not a valid time, rather than throwing an error this library will resolve to 1am instead, which | 
					
						
							|  |  |  |   is an hour early in real ("tick-tock" or "monotonic") time. | 
					
						
							|  |  |  |   ```js | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  |   var utcDate = TZ.fromTimeZone("2021-03-14 02:15:59.000", "America/New_York"); | 
					
						
							| 
									
										
										
										
											2021-05-28 00:57:42 -06:00
										 |  |  |   utcDate.toISOString(); | 
					
						
							|  |  |  |   // "2021-03-14T02:15:59.000-0400" | 
					
						
							|  |  |  |   // (same as "2021-03-14T01:15:59.000-0500") | 
					
						
							|  |  |  |   ``` | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 08:08:53 -06:00
										 |  |  | Q: What happens in November when 1am happens twice? | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 08:08:53 -06:00
										 |  |  | - A: Although both 1ams are distinguishable with ISO offset times, only the first can be resolved from a local time | 
					
						
							| 
									
										
										
										
											2021-05-28 00:57:42 -06:00
										 |  |  |   with this library. | 
					
						
							|  |  |  |   ```js | 
					
						
							| 
									
										
										
										
											2022-03-09 23:40:03 -07:00
										 |  |  |   var utcDate = TZ.fromTimeZone("2021-11-07 01:15:59.000", "America/New_York"); | 
					
						
							| 
									
										
										
										
											2021-05-28 00:57:42 -06:00
										 |  |  |   utcDate.toISOString(); | 
					
						
							|  |  |  |   // "2021-11-07T01:15:59.000-0400", same as "2021-11-07T05:15:59.000Z" | 
					
						
							| 
									
										
										
										
											2021-05-28 08:08:53 -06:00
										 |  |  |   // (an hour before the 2nd 1am at "2021-11-07T01:15:59.000-0500") | 
					
						
							| 
									
										
										
										
											2021-05-28 00:57:42 -06:00
										 |  |  |   ``` | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | # List of Time Zones
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | See the [Full List of Time Zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) on Wikipedia. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Common Zones for Testing: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```txt | 
					
						
							|  |  |  | America/New_York    -0500 | 
					
						
							|  |  |  | America/Denver      -0700 | 
					
						
							|  |  |  | America/Phoenix     -0700 (No DST) | 
					
						
							|  |  |  | America/Los_Angeles -0800 | 
					
						
							| 
									
										
										
										
											2021-05-28 09:04:56 -06:00
										 |  |  | UTC                 Z | 
					
						
							| 
									
										
										
										
											2021-05-27 17:51:33 -06:00
										 |  |  | Australia/Adelaide  +0930 (30-min, has DST) | 
					
						
							|  |  |  | Asia/Kathmandu      +0545 (No DST, 45-min) | 
					
						
							|  |  |  | Asia/Kolkata        +0530 (No DST, 30-min) | 
					
						
							|  |  |  | ``` |