Skip to content

Commit 20c16e5

Browse files
committed
Docs and add more test cases
1 parent 70a513d commit 20c16e5

File tree

2 files changed

+105
-27
lines changed

2 files changed

+105
-27
lines changed

packages/bolt-connection/src/bolt/bolt-protocol-v5x0.utc.transformer.js

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -83,33 +83,7 @@ function createDateTimeWithZoneIdTransformer (config) {
8383
value.nanosecond
8484
)
8585

86-
const dateTimeWithZoneAppliedTwice = getTimeInZoneId(value.timeZoneId, epochSecond, value.nanosecond)
87-
88-
// The wallclock form the current date time
89-
const epochWithZoneAppliedTwice = localDateTimeToEpochSecond(
90-
dateTimeWithZoneAppliedTwice.year,
91-
dateTimeWithZoneAppliedTwice.month,
92-
dateTimeWithZoneAppliedTwice.day,
93-
dateTimeWithZoneAppliedTwice.hour,
94-
dateTimeWithZoneAppliedTwice.minute,
95-
dateTimeWithZoneAppliedTwice.second,
96-
value.nanosecond)
97-
98-
const offsetOfZoneInTheFutureUtc = epochSecond.subtract(epochWithZoneAppliedTwice)
99-
const guessedUtc = epochSecond.add(offsetOfZoneInTheFutureUtc)
100-
101-
const zonedDateTimeFromGuessedUtc = getTimeInZoneId(value.timeZoneId, guessedUtc, value.nanosecond)
102-
103-
const zonedEpochFromGuessedUtc = localDateTimeToEpochSecond(
104-
zonedDateTimeFromGuessedUtc.year,
105-
zonedDateTimeFromGuessedUtc.month,
106-
zonedDateTimeFromGuessedUtc.day,
107-
zonedDateTimeFromGuessedUtc.hour,
108-
zonedDateTimeFromGuessedUtc.minute,
109-
zonedDateTimeFromGuessedUtc.second,
110-
value.nanosecond)
111-
112-
const offset = zonedEpochFromGuessedUtc.subtract(guessedUtc)
86+
const offset = getOffsetFromZoneId(value.timeZoneId, epochSecond, value.nanosecond)
11387
const utc = epochSecond.subtract(offset)
11488

11589
const nano = int(value.nanosecond)
@@ -120,6 +94,62 @@ function createDateTimeWithZoneIdTransformer (config) {
12094
})
12195
}
12296

97+
/**
98+
* Returns the offset for a given timezone id
99+
*
100+
* Javascript doesn't have support for direct getting the timezone offset from a given
101+
* TimeZoneId and DateTime in the given TimeZoneId. For solving this issue,
102+
*
103+
* 1. The ZoneId is applied to the timestamp, so we could make the difference between the
104+
* given timestamp and the new calculated one. This is the offset for the timezone
105+
* in the utc is equal to epoch (some time in the future or past)
106+
* 2. The offset is subtracted from the timestamp, so we have an estimated utc timestamp.
107+
* 3. The ZoneId is applied to the new timestamp, se we could could make the difference
108+
* between the new timestamp and the calculated one. This is the offset for the given timezone.
109+
*
110+
* Example:
111+
* Input: 2022-3-27 1:59:59 'Europe/Berlin'
112+
* Apply 1, 2022-3-27 1:59:59 => 2022-3-27 3:59:59 'Europe/Berlin' +2:00
113+
* Apply 2, 2022-3-27 1:59:59 - 2:00 => 2022-3-26 23:59:59
114+
* Apply 3, 2022-3-26 23:59:59 => 2022-3-27 00:59:59 'Europe/Berlin' +1:00
115+
* The offset is +1 hour.
116+
*
117+
* @param {string} timeZoneId The timezone id
118+
* @param {Integer} epochSecond The epoch second in the timezone id
119+
* @param {Integerable} nanosecond The nanoseconds in the timezone id
120+
* @returns The timezone offset
121+
*/
122+
function getOffsetFromZoneId (timeZoneId, epochSecond, nanosecond) {
123+
const dateTimeWithZoneAppliedTwice = getTimeInZoneId(timeZoneId, epochSecond, nanosecond)
124+
125+
// The wallclock form the current date time
126+
const epochWithZoneAppliedTwice = localDateTimeToEpochSecond(
127+
dateTimeWithZoneAppliedTwice.year,
128+
dateTimeWithZoneAppliedTwice.month,
129+
dateTimeWithZoneAppliedTwice.day,
130+
dateTimeWithZoneAppliedTwice.hour,
131+
dateTimeWithZoneAppliedTwice.minute,
132+
dateTimeWithZoneAppliedTwice.second,
133+
nanosecond)
134+
135+
const offsetOfZoneInTheFutureUtc = epochWithZoneAppliedTwice.subtract(epochSecond)
136+
const guessedUtc = epochSecond.subtract(offsetOfZoneInTheFutureUtc)
137+
138+
const zonedDateTimeFromGuessedUtc = getTimeInZoneId(timeZoneId, guessedUtc, nanosecond)
139+
140+
const zonedEpochFromGuessedUtc = localDateTimeToEpochSecond(
141+
zonedDateTimeFromGuessedUtc.year,
142+
zonedDateTimeFromGuessedUtc.month,
143+
zonedDateTimeFromGuessedUtc.day,
144+
zonedDateTimeFromGuessedUtc.hour,
145+
zonedDateTimeFromGuessedUtc.minute,
146+
zonedDateTimeFromGuessedUtc.second,
147+
nanosecond)
148+
149+
const offset = zonedEpochFromGuessedUtc.subtract(guessedUtc)
150+
return offset
151+
}
152+
123153
function getTimeInZoneId (timeZoneId, epochSecond, nano) {
124154
const formatter = new Intl.DateTimeFormat('en-US', {
125155
timeZone: timeZoneId,

packages/bolt-connection/test/bolt/bolt-protocol-v5x0.test.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,18 +419,66 @@ describe('#unit BoltProtocolV5x0', () => {
419419
'DateTimeWithZoneId / Europe just before turn CEST',
420420
new DateTime(2022, 3, 27, 1, 59, 59, 183_000_000, undefined, 'Europe/Berlin')
421421
],
422+
[
423+
'DateTimeWithZoneId / Europe just 1 before turn CEST',
424+
new DateTime(2022, 3, 27, 0, 59, 59, 183_000_000, undefined, 'Europe/Berlin')
425+
],
422426
[
423427
'DateTimeWithZoneId / Europe just after turn CEST',
424428
new DateTime(2022, 3, 27, 3, 0, 0, 183_000_000, undefined, 'Europe/Berlin')
425429
],
430+
[
431+
'DateTimeWithZoneId / Europe just 1 after turn CEST',
432+
new DateTime(2022, 3, 27, 4, 0, 0, 183_000_000, undefined, 'Europe/Berlin')
433+
],
426434
[
427435
'DateTimeWithZoneId / Europe just before turn CET',
428436
new DateTime(2022, 10, 30, 2, 59, 59, 183_000_000, undefined, 'Europe/Berlin')
429437
],
438+
[
439+
'DateTimeWithZoneId / Europe just 1 before turn CET',
440+
new DateTime(2022, 10, 30, 1, 59, 59, 183_000_000, undefined, 'Europe/Berlin')
441+
],
430442
[
431443
'DateTimeWithZoneId / Europe just after turn CET',
432444
new DateTime(2022, 10, 30, 3, 0, 0, 183_000_000, undefined, 'Europe/Berlin')
433445
],
446+
[
447+
'DateTimeWithZoneId / Europe just 1 after turn CET',
448+
new DateTime(2022, 10, 30, 4, 0, 0, 183_000_000, undefined, 'Europe/Berlin')
449+
],
450+
[
451+
'DateTimeWithZoneId / Sao Paulo just before turn summer time',
452+
new DateTime(2018, 11, 4, 11, 59, 59, 183_000_000, undefined, 'America/Sao_Paulo')
453+
],
454+
[
455+
'DateTimeWithZoneId / Sao Paulo just 1 before turn summer time',
456+
new DateTime(2018, 11, 4, 10, 59, 59, 183_000_000, undefined, 'America/Sao_Paulo')
457+
],
458+
[
459+
'DateTimeWithZoneId / Sao Paulo just after turn summer time',
460+
new DateTime(2018, 11, 5, 1, 0, 0, 183_000_000, undefined, 'America/Sao_Paulo')
461+
],
462+
[
463+
'DateTimeWithZoneId / Sao Paulo just 1 after turn summer time',
464+
new DateTime(2018, 11, 5, 2, 0, 0, 183_000_000, undefined, 'America/Sao_Paulo')
465+
],
466+
[
467+
'DateTimeWithZoneId / Sao Paulo just before turn winter time',
468+
new DateTime(2019, 2, 17, 11, 59, 59, 183_000_000, undefined, 'America/Sao_Paulo')
469+
],
470+
[
471+
'DateTimeWithZoneId / Sao Paulo just 1 before turn winter time',
472+
new DateTime(2019, 2, 17, 10, 59, 59, 183_000_000, undefined, 'America/Sao_Paulo')
473+
],
474+
[
475+
'DateTimeWithZoneId / Sao Paulo just after turn winter time',
476+
new DateTime(2019, 2, 18, 0, 0, 0, 183_000_000, undefined, 'America/Sao_Paulo')
477+
],
478+
[
479+
'DateTimeWithZoneId / Sao Paulo just 1 after turn winter time',
480+
new DateTime(2019, 2, 18, 1, 0, 0, 183_000_000, undefined, 'America/Sao_Paulo')
481+
],
434482
[
435483
'DateTimeWithZoneOffset',
436484
new DateTime(2022, 6, 14, 15, 21, 18, 183_000_000, 120 * 60)

0 commit comments

Comments
 (0)