UNPKG

5.31 kBJavaScriptView Raw
1import { MIN, MS } from '../../constant';
2var typeToPos = {
3 year: 0,
4 month: 1,
5 day: 2,
6 hour: 3,
7 minute: 4,
8 second: 5
9}; // Cache time-zone lookups from Intl.DateTimeFormat,
10// as it is a *very* slow method.
11
12var dtfCache = {};
13
14var getDateTimeFormat = function getDateTimeFormat(timezone, options) {
15 if (options === void 0) {
16 options = {};
17 }
18
19 var timeZoneName = options.timeZoneName || 'short';
20 var key = timezone + "|" + timeZoneName;
21 var dtf = dtfCache[key];
22
23 if (!dtf) {
24 dtf = new Intl.DateTimeFormat('en-US', {
25 hour12: false,
26 timeZone: timezone,
27 year: 'numeric',
28 month: '2-digit',
29 day: '2-digit',
30 hour: '2-digit',
31 minute: '2-digit',
32 second: '2-digit',
33 timeZoneName: timeZoneName
34 });
35 dtfCache[key] = dtf;
36 }
37
38 return dtf;
39};
40
41export default (function (o, c, d) {
42 var defaultTimezone;
43 var localUtcOffset = d().utcOffset();
44
45 var makeFormatParts = function makeFormatParts(timestamp, timezone, options) {
46 if (options === void 0) {
47 options = {};
48 }
49
50 var date = new Date(timestamp);
51 var dtf = getDateTimeFormat(timezone, options);
52 return dtf.formatToParts(date);
53 };
54
55 var tzOffset = function tzOffset(timestamp, timezone) {
56 var formatResult = makeFormatParts(timestamp, timezone);
57 var filled = [];
58
59 for (var i = 0; i < formatResult.length; i += 1) {
60 var _formatResult$i = formatResult[i],
61 type = _formatResult$i.type,
62 value = _formatResult$i.value;
63 var pos = typeToPos[type];
64
65 if (pos >= 0) {
66 filled[pos] = parseInt(value, 10);
67 }
68 }
69
70 var hour = filled[3]; // Workaround for the same behavior in different node version
71 // https://github.com/nodejs/node/issues/33027
72
73 /* istanbul ignore next */
74
75 var fixedHour = hour === 24 ? 0 : hour;
76 var utcString = filled[0] + "-" + filled[1] + "-" + filled[2] + " " + fixedHour + ":" + filled[4] + ":" + filled[5] + ":000";
77 var utcTs = d.utc(utcString).valueOf();
78 var asTS = +timestamp;
79 var over = asTS % 1000;
80 asTS -= over;
81 return (utcTs - asTS) / (60 * 1000);
82 }; // find the right offset a given local time. The o input is our guess, which determines which
83 // offset we'll pick in ambiguous cases (e.g. there are two 3 AMs b/c Fallback DST)
84 // https://github.com/moment/luxon/blob/master/src/datetime.js#L76
85
86
87 var fixOffset = function fixOffset(localTS, o0, tz) {
88 // Our UTC time is just a guess because our offset is just a guess
89 var utcGuess = localTS - o0 * 60 * 1000; // Test whether the zone matches the offset for this ts
90
91 var o2 = tzOffset(utcGuess, tz); // If so, offset didn't change and we're done
92
93 if (o0 === o2) {
94 return [utcGuess, o0];
95 } // If not, change the ts by the difference in the offset
96
97
98 utcGuess -= (o2 - o0) * 60 * 1000; // If that gives us the local time we want, we're done
99
100 var o3 = tzOffset(utcGuess, tz);
101
102 if (o2 === o3) {
103 return [utcGuess, o2];
104 } // If it's different, we're in a hole time.
105 // The offset has changed, but the we don't adjust the time
106
107
108 return [localTS - Math.min(o2, o3) * 60 * 1000, Math.max(o2, o3)];
109 };
110
111 var proto = c.prototype;
112
113 proto.tz = function (timezone, keepLocalTime) {
114 if (timezone === void 0) {
115 timezone = defaultTimezone;
116 }
117
118 var oldOffset = this.utcOffset();
119 var target = this.toDate().toLocaleString('en-US', {
120 timeZone: timezone
121 });
122 var diff = Math.round((this.toDate() - new Date(target)) / 1000 / 60);
123 var ins = d(target).$set(MS, this.$ms).utcOffset(localUtcOffset - diff, true);
124
125 if (keepLocalTime) {
126 var newOffset = ins.utcOffset();
127 ins = ins.add(oldOffset - newOffset, MIN);
128 }
129
130 ins.$x.$timezone = timezone;
131 return ins;
132 };
133
134 proto.offsetName = function (type) {
135 // type: short(default) / long
136 var zone = this.$x.$timezone || d.tz.guess();
137 var result = makeFormatParts(this.valueOf(), zone, {
138 timeZoneName: type
139 }).find(function (m) {
140 return m.type.toLowerCase() === 'timezonename';
141 });
142 return result && result.value;
143 };
144
145 var oldStartOf = proto.startOf;
146
147 proto.startOf = function (units, startOf) {
148 if (!this.$x || !this.$x.$timezone) {
149 return oldStartOf.call(this, units, startOf);
150 }
151
152 var withoutTz = d(this.format('YYYY-MM-DD HH:mm:ss:SSS'));
153 var startOfWithoutTz = oldStartOf.call(withoutTz, units, startOf);
154 return startOfWithoutTz.tz(this.$x.$timezone, true);
155 };
156
157 d.tz = function (input, arg1, arg2) {
158 var parseFormat = arg2 && arg1;
159 var timezone = arg2 || arg1 || defaultTimezone;
160 var previousOffset = tzOffset(+d(), timezone);
161
162 if (typeof input !== 'string') {
163 // timestamp number || js Date || Day.js
164 return d(input).tz(timezone);
165 }
166
167 var localTs = d.utc(input, parseFormat).valueOf();
168
169 var _fixOffset = fixOffset(localTs, previousOffset, timezone),
170 targetTs = _fixOffset[0],
171 targetOffset = _fixOffset[1];
172
173 var ins = d(targetTs).utcOffset(targetOffset);
174 ins.$x.$timezone = timezone;
175 return ins;
176 };
177
178 d.tz.guess = function () {
179 return Intl.DateTimeFormat().resolvedOptions().timeZone;
180 };
181
182 d.tz.setDefault = function (timezone) {
183 defaultTimezone = timezone;
184 };
185});
\No newline at end of file