|
1 | 1 | import { formatOffset, parseZoneInfo, isUndefined, objToLocalTS } from "../impl/util.js";
|
2 | 2 | import Zone from "../zone.js";
|
3 | 3 |
|
| 4 | +let hasLongOffset = true; |
| 5 | +try { |
| 6 | + new Intl.DateTimeFormat("en-US", { timeZoneName: "longOffset" }); |
| 7 | +} catch (e) { |
| 8 | + hasLongOffset = false; |
| 9 | +} |
| 10 | + |
4 | 11 | let dtfCache = {};
|
5 | 12 | function makeDTF(zone) {
|
6 | 13 | if (!dtfCache[zone]) {
|
7 |
| - dtfCache[zone] = new Intl.DateTimeFormat("en-US", { |
8 |
| - hour12: false, |
9 |
| - timeZone: zone, |
10 |
| - year: "numeric", |
11 |
| - month: "2-digit", |
12 |
| - day: "2-digit", |
13 |
| - hour: "2-digit", |
14 |
| - minute: "2-digit", |
15 |
| - second: "2-digit", |
16 |
| - era: "short", |
17 |
| - }); |
| 14 | + dtfCache[zone] = new Intl.DateTimeFormat( |
| 15 | + "en-US", |
| 16 | + hasLongOffset |
| 17 | + ? { |
| 18 | + timeZone: zone, |
| 19 | + timeZoneName: "longOffset", |
| 20 | + year: "numeric", |
| 21 | + } |
| 22 | + : { |
| 23 | + hour12: false, |
| 24 | + timeZone: zone, |
| 25 | + year: "numeric", |
| 26 | + month: "2-digit", |
| 27 | + day: "2-digit", |
| 28 | + hour: "2-digit", |
| 29 | + minute: "2-digit", |
| 30 | + second: "2-digit", |
| 31 | + era: "short", |
| 32 | + } |
| 33 | + ); |
18 | 34 | }
|
19 | 35 | return dtfCache[zone];
|
20 | 36 | }
|
@@ -52,6 +68,28 @@ function partsOffset(dtf, date) {
|
52 | 68 | return filled;
|
53 | 69 | }
|
54 | 70 |
|
| 71 | +function longOffset(dtf, ts) { |
| 72 | + let formatted; |
| 73 | + |
| 74 | + try { |
| 75 | + formatted = dtf.format(ts); |
| 76 | + } catch (e) { |
| 77 | + return NaN; |
| 78 | + } |
| 79 | + |
| 80 | + const idx = formatted.search(/GMT([+-][0-9][0-9]:[0-9][0-9](:[0-9][0-9])?)?/); |
| 81 | + const sign = formatted.charCodeAt(idx + 3); |
| 82 | + |
| 83 | + if (isNaN(sign)) return 0; |
| 84 | + |
| 85 | + return ( |
| 86 | + (44 - sign) * |
| 87 | + (Number(formatted.slice(idx + 4, idx + 6)) * 60 + |
| 88 | + Number(formatted.slice(idx + 7, idx + 9)) + |
| 89 | + Number(formatted.slice(idx + 10, idx + 12)) / 60) |
| 90 | + ); |
| 91 | +} |
| 92 | + |
55 | 93 | let ianaZoneCache = {};
|
56 | 94 | /**
|
57 | 95 | * A zone identified by an IANA identifier, like America/New_York
|
@@ -145,6 +183,8 @@ export default class IANAZone extends Zone {
|
145 | 183 |
|
146 | 184 | /** @override **/
|
147 | 185 | offset(ts) {
|
| 186 | + if (hasLongOffset) return longOffset(makeDTF(this.name), ts); |
| 187 | + |
148 | 188 | const date = new Date(ts);
|
149 | 189 |
|
150 | 190 | if (isNaN(date)) return NaN;
|
|
0 commit comments