Skip to content

Commit 203a219

Browse files
committed
Improve IANAZone.offset performance
1 parent 35a50c2 commit 203a219

File tree

1 file changed

+51
-11
lines changed

1 file changed

+51
-11
lines changed

src/zones/IANAZone.js

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,36 @@
11
import { formatOffset, parseZoneInfo, isUndefined, objToLocalTS } from "../impl/util.js";
22
import Zone from "../zone.js";
33

4+
let hasLongOffset = true;
5+
try {
6+
new Intl.DateTimeFormat("en-US", { timeZoneName: "longOffset" });
7+
} catch (e) {
8+
hasLongOffset = false;
9+
}
10+
411
let dtfCache = {};
512
function makeDTF(zone) {
613
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+
);
1834
}
1935
return dtfCache[zone];
2036
}
@@ -52,6 +68,28 @@ function partsOffset(dtf, date) {
5268
return filled;
5369
}
5470

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+
5593
let ianaZoneCache = {};
5694
/**
5795
* A zone identified by an IANA identifier, like America/New_York
@@ -145,6 +183,8 @@ export default class IANAZone extends Zone {
145183

146184
/** @override **/
147185
offset(ts) {
186+
if (hasLongOffset) return longOffset(makeDTF(this.name), ts);
187+
148188
const date = new Date(ts);
149189

150190
if (isNaN(date)) return NaN;

0 commit comments

Comments
 (0)