chronokinesis 5.0.2 → 7.0.0
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/README.md +75 -19
- package/dist/chronokinesis.cjs +43 -37
- package/dist/index.cjs +43 -37
- package/index.d.ts +17 -6
- package/index.js +42 -38
- package/package.json +20 -11
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
chronokinesis
|
|
2
|
-
|
|
1
|
+
# chronokinesis
|
|
2
|
+
|
|
3
3
|
[](https://github.com/paed01/chronokinesis/actions/workflows/build.yaml) [](https://coveralls.io/github/paed01/chronokinesis?branch=master)
|
|
4
4
|
|
|
5
5
|
Mock time and date for traveling and freezing. Inspired and borrowed from [timekeeper](https://github.com/vesln/timekeeper).
|
|
@@ -13,11 +13,12 @@ Mock time and date for traveling and freezing. Inspired and borrowed from [timek
|
|
|
13
13
|
- [`defrost()`](#defrost)
|
|
14
14
|
- [`reset()`](#reset)
|
|
15
15
|
- [`isKeepingTime()`](#iskeepingtime)
|
|
16
|
-
- [`timezone(timeZone)`](#timezonetimezone)
|
|
17
|
-
|
|
18
|
-
- [timezone
|
|
19
|
-
- [timezone
|
|
20
|
-
- [timezone
|
|
16
|
+
- [`timezone(timeZone[, ...args])`](#timezonetimezone-args)
|
|
17
|
+
- [`new TimeZoneTraveller(timeZone)`](#new-timezonetravellertimezone)
|
|
18
|
+
- [`timezone.freeze([...args])`](#timezonefreezeargs)
|
|
19
|
+
- [`timezone.travel([...args])`](#timezonetravelargs)
|
|
20
|
+
- [`timezone.reset()`](#timezonereset)
|
|
21
|
+
- [`timezone.defrost()`](#timezonedefrost)
|
|
21
22
|
- [Distributions](#distributions)
|
|
22
23
|
- [Nodejs require](#nodejs-require)
|
|
23
24
|
- [Browser (UMD)](#browser-umd)
|
|
@@ -42,6 +43,35 @@ setTimeout(() => {
|
|
|
42
43
|
}, 2000);
|
|
43
44
|
```
|
|
44
45
|
|
|
46
|
+
With arguments:
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
import * as ck from 'chronokinesis';
|
|
50
|
+
import assert from 'node:assert';
|
|
51
|
+
|
|
52
|
+
ck.freeze(1980, 0, 1);
|
|
53
|
+
|
|
54
|
+
assert.equal(true, ck.isKeepingTime());
|
|
55
|
+
assert.deepEqual(new Date(), new Date(1980, 0, 1));
|
|
56
|
+
|
|
57
|
+
ck.reset();
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
or use with [`luxon`](https://moment.github.io/luxon):
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
import { DateTime } from 'luxon';
|
|
64
|
+
import * as ck from 'chronokinesis';
|
|
65
|
+
|
|
66
|
+
ck.travel(DateTime.now().plus({ year: 1 }).toMillis());
|
|
67
|
+
|
|
68
|
+
setTimeout(() => {
|
|
69
|
+
console.log('Traveled with Luxon DateTime one year and some', new Date());
|
|
70
|
+
|
|
71
|
+
ck.reset();
|
|
72
|
+
}, 2000);
|
|
73
|
+
```
|
|
74
|
+
|
|
45
75
|
or use with [`moment`](http://momentjs.com):
|
|
46
76
|
|
|
47
77
|
```javascript
|
|
@@ -51,8 +81,7 @@ import * as ck from 'chronokinesis';
|
|
|
51
81
|
ck.travel(moment().add(1, 'year'));
|
|
52
82
|
|
|
53
83
|
setTimeout(() => {
|
|
54
|
-
|
|
55
|
-
console.log(new Date());
|
|
84
|
+
console.log('Traveled with Moment Date one year and some', new Date());
|
|
56
85
|
|
|
57
86
|
ck.reset();
|
|
58
87
|
}, 2000);
|
|
@@ -91,7 +120,7 @@ let date = new Date(2018, 0, 31);
|
|
|
91
120
|
|
|
92
121
|
ck.travel(date);
|
|
93
122
|
|
|
94
|
-
setTimeout(function() {
|
|
123
|
+
setTimeout(function () {
|
|
95
124
|
console.log(new Date());
|
|
96
125
|
ck.reset();
|
|
97
126
|
}, 1500);
|
|
@@ -109,7 +138,7 @@ ck.freeze(date);
|
|
|
109
138
|
|
|
110
139
|
ck.travel(moment().add(1, 'year'));
|
|
111
140
|
|
|
112
|
-
setTimeout(function() {
|
|
141
|
+
setTimeout(function () {
|
|
113
142
|
console.log(`Still frozen but one year ahead ${new Date()}`);
|
|
114
143
|
|
|
115
144
|
ck.reset();
|
|
@@ -147,12 +176,12 @@ Resets Date to current glory.
|
|
|
147
176
|
import * as ck from 'chronokinesis';
|
|
148
177
|
|
|
149
178
|
ck.freeze(2060, 0, 1);
|
|
150
|
-
console.log(`end of time is reached at ${new Date()} according to Newton`)
|
|
179
|
+
console.log(`end of time is reached at ${new Date()} according to Newton`);
|
|
151
180
|
|
|
152
181
|
ck.reset();
|
|
153
182
|
|
|
154
183
|
// Today
|
|
155
|
-
console.log(new Date())
|
|
184
|
+
console.log(new Date());
|
|
156
185
|
```
|
|
157
186
|
|
|
158
187
|
## `isKeepingTime()`
|
|
@@ -165,33 +194,60 @@ import * as ck from 'chronokinesis';
|
|
|
165
194
|
console.log(ck.isKeepingTime() ? 'Is' : 'Not', 'keeping time');
|
|
166
195
|
ck.travel(1893448800000);
|
|
167
196
|
console.log(ck.isKeepingTime() ? 'Is' : 'Not', 'keeping time');
|
|
197
|
+
|
|
198
|
+
ck.reset();
|
|
168
199
|
```
|
|
169
200
|
|
|
170
|
-
## `timezone(timeZone)`
|
|
201
|
+
## `timezone(timeZone[, ...args])`
|
|
171
202
|
|
|
172
|
-
|
|
203
|
+
Travel to time zone.
|
|
204
|
+
|
|
205
|
+
- `timeZone`: IANA time zone string
|
|
206
|
+
- `...args`: Optional travel to date arguments
|
|
207
|
+
|
|
208
|
+
Returns [`TimeZoneTraveller` api](#new-timezonetravellertimezone)
|
|
173
209
|
|
|
174
210
|
```javascript
|
|
175
211
|
import * as ck from 'chronokinesis';
|
|
176
212
|
|
|
213
|
+
ck.reset();
|
|
214
|
+
|
|
177
215
|
const tz = ck.timezone('Asia/Shanghai');
|
|
178
216
|
|
|
217
|
+
console.log('Now in Shanghai', new Date());
|
|
218
|
+
|
|
179
219
|
tz.freeze();
|
|
220
|
+
|
|
221
|
+
ck.reset();
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## `new TimeZoneTraveller(timeZone)`
|
|
225
|
+
|
|
226
|
+
Time zone traveller api.
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
import { TimeZoneTraveller, reset } from 'chronokinesis';
|
|
230
|
+
|
|
231
|
+
const timezone = new TimeZoneTraveller('Asia/Shanghai');
|
|
232
|
+
|
|
233
|
+
timezone.freeze();
|
|
234
|
+
|
|
235
|
+
reset();
|
|
180
236
|
```
|
|
181
237
|
|
|
182
|
-
### timezone
|
|
238
|
+
### `timezone.freeze([...args])`
|
|
183
239
|
|
|
184
240
|
Freeze at the specific timezone.
|
|
185
241
|
|
|
186
|
-
### timezone
|
|
242
|
+
### `timezone.travel([...args])`
|
|
187
243
|
|
|
188
244
|
Start traveling in the specific timezone.
|
|
189
245
|
|
|
190
|
-
### timezone
|
|
246
|
+
### `timezone.reset()`
|
|
191
247
|
|
|
192
248
|
Same as [#reset](#reset)
|
|
193
249
|
|
|
194
|
-
### timezone
|
|
250
|
+
### `timezone.defrost()`
|
|
195
251
|
|
|
196
252
|
Same as [#defrost](#defrost)
|
|
197
253
|
|
package/dist/chronokinesis.cjs
CHANGED
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
* Veselin Todorov <hi@vesln.com>
|
|
11
11
|
* MIT License.
|
|
12
12
|
*/
|
|
13
|
-
const
|
|
13
|
+
const kNativeDate = Symbol.for('chronokinesis native date');
|
|
14
|
+
|
|
15
|
+
const NativeDate = Date[kNativeDate] || Date;
|
|
14
16
|
const nativeGetTimezoneOffset = NativeDate.prototype.getTimezoneOffset;
|
|
15
17
|
|
|
16
18
|
let freezedAt = null;
|
|
@@ -33,7 +35,7 @@
|
|
|
33
35
|
const curr = nativeGetTimezoneOffset.call(this);
|
|
34
36
|
if (!iana) return curr;
|
|
35
37
|
|
|
36
|
-
const tz =
|
|
38
|
+
const tz = new TimeZoneTraveller(iana).getTime(this);
|
|
37
39
|
return Math.round((tz - this.getTime()) / 60000) + curr;
|
|
38
40
|
},
|
|
39
41
|
});
|
|
@@ -41,12 +43,14 @@
|
|
|
41
43
|
return dt;
|
|
42
44
|
}
|
|
43
45
|
|
|
46
|
+
FakeDate[kNativeDate] = NativeDate;
|
|
47
|
+
|
|
44
48
|
FakeDate.UTC = NativeDate.UTC;
|
|
45
49
|
FakeDate.parse = NativeDate.parse;
|
|
46
50
|
|
|
47
51
|
FakeDate.prototype = NativeDate.prototype;
|
|
48
52
|
|
|
49
|
-
FakeDate.now = function() {
|
|
53
|
+
FakeDate.now = function fakeNow() {
|
|
50
54
|
if (freezedAt) return freezedAt.getTime();
|
|
51
55
|
return time();
|
|
52
56
|
};
|
|
@@ -95,7 +99,8 @@
|
|
|
95
99
|
return Date === FakeDate;
|
|
96
100
|
}
|
|
97
101
|
|
|
98
|
-
function
|
|
102
|
+
function TimeZoneTraveller(timeZone) {
|
|
103
|
+
this.timeZone = timeZone;
|
|
99
104
|
const options = {
|
|
100
105
|
year: 'numeric',
|
|
101
106
|
month: 'numeric',
|
|
@@ -105,52 +110,51 @@
|
|
|
105
110
|
second: 'numeric',
|
|
106
111
|
hour12: false,
|
|
107
112
|
};
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
timeZone: timeZone,
|
|
113
|
+
this.localFormatter = Intl.DateTimeFormat('UTC', options);
|
|
114
|
+
this.timeZoneFormatter = Intl.DateTimeFormat('UTC', {
|
|
115
|
+
timeZone,
|
|
112
116
|
...options,
|
|
113
117
|
});
|
|
118
|
+
}
|
|
114
119
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
reset,
|
|
119
|
-
isKeepingTime,
|
|
120
|
-
getTime,
|
|
121
|
-
freeze: freezeInTimezone,
|
|
122
|
-
travel: travelInTimezone,
|
|
123
|
-
};
|
|
120
|
+
TimeZoneTraveller.prototype.defrost = defrost;
|
|
121
|
+
TimeZoneTraveller.prototype.reset = reset;
|
|
122
|
+
TimeZoneTraveller.prototype.isKeepingTime = isKeepingTime;
|
|
124
123
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return freeze(getTime(...args));
|
|
129
|
-
}
|
|
124
|
+
TimeZoneTraveller.prototype.getTime = function timeZoneGetTime(...args) {
|
|
125
|
+
const realDate = instantiate(Date, args);
|
|
126
|
+
const tz = new NativeDate(toUTC(this.timeZoneFormatter, realDate));
|
|
130
127
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
iana = timeZone;
|
|
134
|
-
return travel(getTime(...args));
|
|
135
|
-
}
|
|
128
|
+
if (!args.length) return tz.getTime();
|
|
129
|
+
const currentTz = new NativeDate(toUTC(this.localFormatter, realDate));
|
|
136
130
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const tz = new NativeDate(toUTC(formatter, realDate));
|
|
131
|
+
return realDate.getTime() + currentTz.getTime() - tz.getTime();
|
|
132
|
+
};
|
|
140
133
|
|
|
141
|
-
|
|
142
|
-
|
|
134
|
+
TimeZoneTraveller.prototype.freeze = function freezeInTimezone(...args) {
|
|
135
|
+
if (!args.length && iana === this.timeZone) return freeze();
|
|
136
|
+
iana = this.timeZone;
|
|
137
|
+
return freeze(this.getTime(...args));
|
|
138
|
+
};
|
|
143
139
|
|
|
144
|
-
|
|
145
|
-
|
|
140
|
+
TimeZoneTraveller.prototype.travel = function timeZoneTravel(...args) {
|
|
141
|
+
if (!args.length && iana === this.timeZone) return travel();
|
|
142
|
+
iana = this.timeZone;
|
|
143
|
+
return travel(this.getTime(...args));
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
function timezone(timeZone, ...args) {
|
|
147
|
+
const tz = new TimeZoneTraveller(timeZone);
|
|
148
|
+
tz.travel(...args);
|
|
149
|
+
return tz;
|
|
146
150
|
}
|
|
147
151
|
|
|
148
152
|
function useFakeDate() {
|
|
149
|
-
Date = FakeDate;
|
|
153
|
+
Date = FakeDate;
|
|
150
154
|
}
|
|
151
155
|
|
|
152
156
|
function useNativeDate() {
|
|
153
|
-
Date =
|
|
157
|
+
Date = FakeDate[kNativeDate];
|
|
154
158
|
}
|
|
155
159
|
|
|
156
160
|
function time() {
|
|
@@ -166,7 +170,7 @@
|
|
|
166
170
|
function toUTC(formatter, dt) {
|
|
167
171
|
let year, month, day, hour, minute, second;
|
|
168
172
|
|
|
169
|
-
for (const {type, value} of formatter.formatToParts(dt)) {
|
|
173
|
+
for (const { type, value } of formatter.formatToParts(dt)) {
|
|
170
174
|
switch (type) {
|
|
171
175
|
case 'year':
|
|
172
176
|
year = parseInt(value);
|
|
@@ -192,6 +196,8 @@
|
|
|
192
196
|
return NativeDate.UTC(year, month, day, hour, minute, second, dt.getMilliseconds());
|
|
193
197
|
}
|
|
194
198
|
|
|
199
|
+
exports.FakeDate = FakeDate;
|
|
200
|
+
exports.TimeZoneTraveller = TimeZoneTraveller;
|
|
195
201
|
exports.defrost = defrost;
|
|
196
202
|
exports.freeze = freeze;
|
|
197
203
|
exports.isKeepingTime = isKeepingTime;
|
package/dist/index.cjs
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
* Veselin Todorov <hi@vesln.com>
|
|
7
7
|
* MIT License.
|
|
8
8
|
*/
|
|
9
|
-
const
|
|
9
|
+
const kNativeDate = Symbol.for('chronokinesis native date');
|
|
10
|
+
|
|
11
|
+
const NativeDate = Date[kNativeDate] || Date;
|
|
10
12
|
const nativeGetTimezoneOffset = NativeDate.prototype.getTimezoneOffset;
|
|
11
13
|
|
|
12
14
|
let freezedAt = null;
|
|
@@ -29,7 +31,7 @@ function FakeDate(...args) {
|
|
|
29
31
|
const curr = nativeGetTimezoneOffset.call(this);
|
|
30
32
|
if (!iana) return curr;
|
|
31
33
|
|
|
32
|
-
const tz =
|
|
34
|
+
const tz = new TimeZoneTraveller(iana).getTime(this);
|
|
33
35
|
return Math.round((tz - this.getTime()) / 60000) + curr;
|
|
34
36
|
},
|
|
35
37
|
});
|
|
@@ -37,12 +39,14 @@ function FakeDate(...args) {
|
|
|
37
39
|
return dt;
|
|
38
40
|
}
|
|
39
41
|
|
|
42
|
+
FakeDate[kNativeDate] = NativeDate;
|
|
43
|
+
|
|
40
44
|
FakeDate.UTC = NativeDate.UTC;
|
|
41
45
|
FakeDate.parse = NativeDate.parse;
|
|
42
46
|
|
|
43
47
|
FakeDate.prototype = NativeDate.prototype;
|
|
44
48
|
|
|
45
|
-
FakeDate.now = function() {
|
|
49
|
+
FakeDate.now = function fakeNow() {
|
|
46
50
|
if (freezedAt) return freezedAt.getTime();
|
|
47
51
|
return time();
|
|
48
52
|
};
|
|
@@ -91,7 +95,8 @@ function isKeepingTime() {
|
|
|
91
95
|
return Date === FakeDate;
|
|
92
96
|
}
|
|
93
97
|
|
|
94
|
-
function
|
|
98
|
+
function TimeZoneTraveller(timeZone) {
|
|
99
|
+
this.timeZone = timeZone;
|
|
95
100
|
const options = {
|
|
96
101
|
year: 'numeric',
|
|
97
102
|
month: 'numeric',
|
|
@@ -101,52 +106,51 @@ function timezone(timeZone) {
|
|
|
101
106
|
second: 'numeric',
|
|
102
107
|
hour12: false,
|
|
103
108
|
};
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
timeZone: timeZone,
|
|
109
|
+
this.localFormatter = Intl.DateTimeFormat('UTC', options);
|
|
110
|
+
this.timeZoneFormatter = Intl.DateTimeFormat('UTC', {
|
|
111
|
+
timeZone,
|
|
108
112
|
...options,
|
|
109
113
|
});
|
|
114
|
+
}
|
|
110
115
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
reset,
|
|
115
|
-
isKeepingTime,
|
|
116
|
-
getTime,
|
|
117
|
-
freeze: freezeInTimezone,
|
|
118
|
-
travel: travelInTimezone,
|
|
119
|
-
};
|
|
116
|
+
TimeZoneTraveller.prototype.defrost = defrost;
|
|
117
|
+
TimeZoneTraveller.prototype.reset = reset;
|
|
118
|
+
TimeZoneTraveller.prototype.isKeepingTime = isKeepingTime;
|
|
120
119
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return freeze(getTime(...args));
|
|
125
|
-
}
|
|
120
|
+
TimeZoneTraveller.prototype.getTime = function timeZoneGetTime(...args) {
|
|
121
|
+
const realDate = instantiate(Date, args);
|
|
122
|
+
const tz = new NativeDate(toUTC(this.timeZoneFormatter, realDate));
|
|
126
123
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
iana = timeZone;
|
|
130
|
-
return travel(getTime(...args));
|
|
131
|
-
}
|
|
124
|
+
if (!args.length) return tz.getTime();
|
|
125
|
+
const currentTz = new NativeDate(toUTC(this.localFormatter, realDate));
|
|
132
126
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const tz = new NativeDate(toUTC(formatter, realDate));
|
|
127
|
+
return realDate.getTime() + currentTz.getTime() - tz.getTime();
|
|
128
|
+
};
|
|
136
129
|
|
|
137
|
-
|
|
138
|
-
|
|
130
|
+
TimeZoneTraveller.prototype.freeze = function freezeInTimezone(...args) {
|
|
131
|
+
if (!args.length && iana === this.timeZone) return freeze();
|
|
132
|
+
iana = this.timeZone;
|
|
133
|
+
return freeze(this.getTime(...args));
|
|
134
|
+
};
|
|
139
135
|
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
TimeZoneTraveller.prototype.travel = function timeZoneTravel(...args) {
|
|
137
|
+
if (!args.length && iana === this.timeZone) return travel();
|
|
138
|
+
iana = this.timeZone;
|
|
139
|
+
return travel(this.getTime(...args));
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
function timezone(timeZone, ...args) {
|
|
143
|
+
const tz = new TimeZoneTraveller(timeZone);
|
|
144
|
+
tz.travel(...args);
|
|
145
|
+
return tz;
|
|
142
146
|
}
|
|
143
147
|
|
|
144
148
|
function useFakeDate() {
|
|
145
|
-
Date = FakeDate;
|
|
149
|
+
Date = FakeDate;
|
|
146
150
|
}
|
|
147
151
|
|
|
148
152
|
function useNativeDate() {
|
|
149
|
-
Date =
|
|
153
|
+
Date = FakeDate[kNativeDate];
|
|
150
154
|
}
|
|
151
155
|
|
|
152
156
|
function time() {
|
|
@@ -162,7 +166,7 @@ function instantiate(type, args) {
|
|
|
162
166
|
function toUTC(formatter, dt) {
|
|
163
167
|
let year, month, day, hour, minute, second;
|
|
164
168
|
|
|
165
|
-
for (const {type, value} of formatter.formatToParts(dt)) {
|
|
169
|
+
for (const { type, value } of formatter.formatToParts(dt)) {
|
|
166
170
|
switch (type) {
|
|
167
171
|
case 'year':
|
|
168
172
|
year = parseInt(value);
|
|
@@ -188,6 +192,8 @@ function toUTC(formatter, dt) {
|
|
|
188
192
|
return NativeDate.UTC(year, month, day, hour, minute, second, dt.getMilliseconds());
|
|
189
193
|
}
|
|
190
194
|
|
|
195
|
+
exports.FakeDate = FakeDate;
|
|
196
|
+
exports.TimeZoneTraveller = TimeZoneTraveller;
|
|
191
197
|
exports.defrost = defrost;
|
|
192
198
|
exports.freeze = freeze;
|
|
193
199
|
exports.isKeepingTime = isKeepingTime;
|
package/index.d.ts
CHANGED
|
@@ -22,11 +22,21 @@ export function reset(): void;
|
|
|
22
22
|
*/
|
|
23
23
|
export function isKeepingTime(): boolean;
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Fake date
|
|
27
|
+
*/
|
|
28
|
+
export class FakeDate extends Date {}
|
|
29
|
+
|
|
25
30
|
/**
|
|
26
31
|
* Timezone traveling
|
|
27
32
|
*/
|
|
28
|
-
|
|
29
|
-
/**
|
|
33
|
+
export class TimeZoneTraveller {
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @param timeZone IANA time zone
|
|
37
|
+
*/
|
|
38
|
+
constructor(timeZone: string);
|
|
39
|
+
/** IANA time zone */
|
|
30
40
|
readonly timeZone: string;
|
|
31
41
|
defrost: typeof defrost;
|
|
32
42
|
reset: typeof reset;
|
|
@@ -38,11 +48,12 @@ interface TimezoneTraveling {
|
|
|
38
48
|
* @param args Same arguments as Date constructor.
|
|
39
49
|
* @returns number of milliseconds since the epoch (January 1, 1970, UTC)
|
|
40
50
|
*/
|
|
41
|
-
getTime
|
|
51
|
+
getTime(...args: any[]): number;
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
/**
|
|
45
|
-
*
|
|
46
|
-
* @param timeZone
|
|
55
|
+
* Travel to time zone.
|
|
56
|
+
* @param timeZone IANA time zone
|
|
57
|
+
* @param args Optional travel to date arguments
|
|
47
58
|
*/
|
|
48
|
-
export function timezone(timeZone: string):
|
|
59
|
+
export function timezone(timeZone: string, ...args: any[]): TimeZoneTraveller;
|
package/index.js
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* Veselin Todorov <hi@vesln.com>
|
|
5
5
|
* MIT License.
|
|
6
6
|
*/
|
|
7
|
-
const
|
|
7
|
+
const kNativeDate = Symbol.for('chronokinesis native date');
|
|
8
|
+
|
|
9
|
+
const NativeDate = Date[kNativeDate] || Date;
|
|
8
10
|
const nativeGetTimezoneOffset = NativeDate.prototype.getTimezoneOffset;
|
|
9
11
|
|
|
10
12
|
let freezedAt = null;
|
|
@@ -12,7 +14,7 @@ let traveledTo = null;
|
|
|
12
14
|
let started = null;
|
|
13
15
|
let iana = null;
|
|
14
16
|
|
|
15
|
-
function FakeDate(...args) {
|
|
17
|
+
export function FakeDate(...args) {
|
|
16
18
|
const length = args.length;
|
|
17
19
|
if (!length) {
|
|
18
20
|
if (freezedAt) args = [freezedAt];
|
|
@@ -27,7 +29,7 @@ function FakeDate(...args) {
|
|
|
27
29
|
const curr = nativeGetTimezoneOffset.call(this);
|
|
28
30
|
if (!iana) return curr;
|
|
29
31
|
|
|
30
|
-
const tz =
|
|
32
|
+
const tz = new TimeZoneTraveller(iana).getTime(this);
|
|
31
33
|
return Math.round((tz - this.getTime()) / 60000) + curr;
|
|
32
34
|
},
|
|
33
35
|
});
|
|
@@ -35,12 +37,14 @@ function FakeDate(...args) {
|
|
|
35
37
|
return dt;
|
|
36
38
|
}
|
|
37
39
|
|
|
40
|
+
FakeDate[kNativeDate] = NativeDate;
|
|
41
|
+
|
|
38
42
|
FakeDate.UTC = NativeDate.UTC;
|
|
39
43
|
FakeDate.parse = NativeDate.parse;
|
|
40
44
|
|
|
41
45
|
FakeDate.prototype = NativeDate.prototype;
|
|
42
46
|
|
|
43
|
-
FakeDate.now = function() {
|
|
47
|
+
FakeDate.now = function fakeNow() {
|
|
44
48
|
if (freezedAt) return freezedAt.getTime();
|
|
45
49
|
return time();
|
|
46
50
|
};
|
|
@@ -89,7 +93,8 @@ export function isKeepingTime() {
|
|
|
89
93
|
return Date === FakeDate;
|
|
90
94
|
}
|
|
91
95
|
|
|
92
|
-
export function
|
|
96
|
+
export function TimeZoneTraveller(timeZone) {
|
|
97
|
+
this.timeZone = timeZone;
|
|
93
98
|
const options = {
|
|
94
99
|
year: 'numeric',
|
|
95
100
|
month: 'numeric',
|
|
@@ -99,52 +104,51 @@ export function timezone(timeZone) {
|
|
|
99
104
|
second: 'numeric',
|
|
100
105
|
hour12: false,
|
|
101
106
|
};
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
timeZone: timeZone,
|
|
107
|
+
this.localFormatter = Intl.DateTimeFormat('UTC', options);
|
|
108
|
+
this.timeZoneFormatter = Intl.DateTimeFormat('UTC', {
|
|
109
|
+
timeZone,
|
|
106
110
|
...options,
|
|
107
111
|
});
|
|
112
|
+
}
|
|
108
113
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
reset,
|
|
113
|
-
isKeepingTime,
|
|
114
|
-
getTime,
|
|
115
|
-
freeze: freezeInTimezone,
|
|
116
|
-
travel: travelInTimezone,
|
|
117
|
-
};
|
|
114
|
+
TimeZoneTraveller.prototype.defrost = defrost;
|
|
115
|
+
TimeZoneTraveller.prototype.reset = reset;
|
|
116
|
+
TimeZoneTraveller.prototype.isKeepingTime = isKeepingTime;
|
|
118
117
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return freeze(getTime(...args));
|
|
123
|
-
}
|
|
118
|
+
TimeZoneTraveller.prototype.getTime = function timeZoneGetTime(...args) {
|
|
119
|
+
const realDate = instantiate(Date, args);
|
|
120
|
+
const tz = new NativeDate(toUTC(this.timeZoneFormatter, realDate));
|
|
124
121
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
iana = timeZone;
|
|
128
|
-
return travel(getTime(...args));
|
|
129
|
-
}
|
|
122
|
+
if (!args.length) return tz.getTime();
|
|
123
|
+
const currentTz = new NativeDate(toUTC(this.localFormatter, realDate));
|
|
130
124
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const tz = new NativeDate(toUTC(formatter, realDate));
|
|
125
|
+
return realDate.getTime() + currentTz.getTime() - tz.getTime();
|
|
126
|
+
};
|
|
134
127
|
|
|
135
|
-
|
|
136
|
-
|
|
128
|
+
TimeZoneTraveller.prototype.freeze = function freezeInTimezone(...args) {
|
|
129
|
+
if (!args.length && iana === this.timeZone) return freeze();
|
|
130
|
+
iana = this.timeZone;
|
|
131
|
+
return freeze(this.getTime(...args));
|
|
132
|
+
};
|
|
137
133
|
|
|
138
|
-
|
|
139
|
-
|
|
134
|
+
TimeZoneTraveller.prototype.travel = function timeZoneTravel(...args) {
|
|
135
|
+
if (!args.length && iana === this.timeZone) return travel();
|
|
136
|
+
iana = this.timeZone;
|
|
137
|
+
return travel(this.getTime(...args));
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export function timezone(timeZone, ...args) {
|
|
141
|
+
const tz = new TimeZoneTraveller(timeZone);
|
|
142
|
+
tz.travel(...args);
|
|
143
|
+
return tz;
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
function useFakeDate() {
|
|
143
|
-
Date = FakeDate;
|
|
147
|
+
Date = FakeDate;
|
|
144
148
|
}
|
|
145
149
|
|
|
146
150
|
function useNativeDate() {
|
|
147
|
-
Date =
|
|
151
|
+
Date = FakeDate[kNativeDate];
|
|
148
152
|
}
|
|
149
153
|
|
|
150
154
|
function time() {
|
|
@@ -160,7 +164,7 @@ function instantiate(type, args) {
|
|
|
160
164
|
function toUTC(formatter, dt) {
|
|
161
165
|
let year, month, day, hour, minute, second;
|
|
162
166
|
|
|
163
|
-
for (const {type, value} of formatter.formatToParts(dt)) {
|
|
167
|
+
for (const { type, value } of formatter.formatToParts(dt)) {
|
|
164
168
|
switch (type) {
|
|
165
169
|
case 'year':
|
|
166
170
|
year = parseInt(value);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chronokinesis",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"description": "Module for testing time-dependent code",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Pål Edman",
|
|
@@ -15,14 +15,20 @@
|
|
|
15
15
|
"sideEffects": true,
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|
|
18
|
-
"url": "git://github.com/paed01/chronokinesis"
|
|
18
|
+
"url": "git://github.com/paed01/chronokinesis.git"
|
|
19
|
+
},
|
|
20
|
+
"exports": {
|
|
21
|
+
"import": "./index.js",
|
|
22
|
+
"require": "./dist/index.cjs",
|
|
23
|
+
"types": "./index.d.ts"
|
|
19
24
|
},
|
|
20
25
|
"scripts": {
|
|
21
26
|
"toc": "node generate-api-toc.cjs",
|
|
22
27
|
"test": "mocha",
|
|
23
|
-
"lint": "eslint . --cache",
|
|
28
|
+
"lint": "eslint . --cache && prettier . --check --cache",
|
|
24
29
|
"test:lcov": "c8 -r lcov -r text mocha && npm run lint",
|
|
25
|
-
"
|
|
30
|
+
"cov:html": "c8 mocha -R dot && c8 report --reporter html",
|
|
31
|
+
"posttest": "npm run lint && npm run dist && texample -g",
|
|
26
32
|
"prepack": "npm run dist",
|
|
27
33
|
"dist": "npm run toc && rollup -c"
|
|
28
34
|
},
|
|
@@ -48,14 +54,17 @@
|
|
|
48
54
|
"fake now"
|
|
49
55
|
],
|
|
50
56
|
"devDependencies": {
|
|
51
|
-
"@rollup/plugin-commonjs": "^
|
|
52
|
-
"c8": "^
|
|
53
|
-
"chai": "^
|
|
54
|
-
"eslint": "^
|
|
57
|
+
"@rollup/plugin-commonjs": "^28.0.2",
|
|
58
|
+
"c8": "^10.1.2",
|
|
59
|
+
"chai": "^5.1.0",
|
|
60
|
+
"eslint": "^9.3.0",
|
|
55
61
|
"lodash.clonedeep": "^4.5.0",
|
|
62
|
+
"luxon": "^3.7.1",
|
|
56
63
|
"markdown-toc": "^1.2.0",
|
|
57
|
-
"mocha": "^
|
|
58
|
-
"moment": "^2.
|
|
59
|
-
"
|
|
64
|
+
"mocha": "^11.0.1",
|
|
65
|
+
"moment": "^2.30.1",
|
|
66
|
+
"prettier": "^3.2.5",
|
|
67
|
+
"rollup": "^4.12.1",
|
|
68
|
+
"texample": "^0.0.8"
|
|
60
69
|
}
|
|
61
70
|
}
|