Skip to content

Commit ce17e95

Browse files
committed
Fill DateTimeWithZoneId Offset when unpack and use timeZoneOffsetSeconds instead of calculate
1 parent e5e9e40 commit ce17e95

File tree

2 files changed

+86
-20
lines changed

2 files changed

+86
-20
lines changed

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

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ function createDateTimeWithZoneIdTransformer (config) {
6767
localDateTime.minute,
6868
localDateTime.second,
6969
int(nano),
70-
null,
70+
localDateTime.timeZoneOffsetSeconds,
7171
timeZoneId
7272
)
7373
return convertIntegerPropsIfNeeded(result, disableLosslessIntegers, useBigInt)
@@ -83,7 +83,9 @@ function createDateTimeWithZoneIdTransformer (config) {
8383
value.nanosecond
8484
)
8585

86-
const offset = getOffsetFromZoneId(value.timeZoneId, epochSecond, value.nanosecond)
86+
const offset = value.timeZoneOffsetSeconds != null
87+
? value.timeZoneOffsetSeconds
88+
: getOffsetFromZoneId(value.timeZoneId, epochSecond, value.nanosecond)
8789
const utc = epochSecond.subtract(offset)
8890

8991
const nano = int(value.nanosecond)
@@ -159,27 +161,46 @@ function getTimeInZoneId (timeZoneId, epochSecond, nano) {
159161
hour: 'numeric',
160162
minute: 'numeric',
161163
second: 'numeric',
162-
hourCycle: 'h23'
164+
hourCycle: 'h23',
165+
timeZoneName: 'short'
163166
})
164167

165168
const l = epochSecondAndNanoToLocalDateTime(epochSecond, nano)
166-
167-
const formattedUtc = formatter.formatToParts(Date.UTC(
169+
const utc = Date.UTC(
168170
int(l.year).toNumber(),
169171
int(l.month).toNumber() - 1,
170172
int(l.day).toNumber(),
171173
int(l.hour).toNumber(),
172174
int(l.minute).toNumber(),
173175
int(l.second).toNumber()
174-
))
176+
)
177+
178+
const formattedUtcParts = formatter.formatToParts(utc)
179+
180+
const localDateTime = formattedUtcParts.reduce((obj, currentValue) => {
181+
if (currentValue.type === 'timeZoneName') {
182+
const parts = currentValue.value.replace('GMT', '').split(':')
183+
const divisor = 60
184+
const { offset } = parts.reduce((state, value) => {
185+
const part = int(value)
186+
const signal = part.isPositive() ? int(1) : int(-1)
175187

176-
const localDateTime = formattedUtc.reduce((obj, currentValue) => {
177-
if (currentValue.type !== 'literal') {
188+
const offset = part.multiply(state.factor).add(state.offset)
189+
const factor = state.factor.div(divisor).multiply(signal)
190+
191+
return {
192+
offset,
193+
factor
194+
}
195+
}, { factor: int(60 * 60), offset: int(0) })
196+
197+
obj.timeZoneOffsetSeconds = offset
198+
} else if (currentValue.type !== 'literal') {
178199
obj[currentValue.type] = int(currentValue.value)
179-
return obj
180200
}
181201
return obj
182202
}, {})
203+
183204
return localDateTime
184205
}
185206

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

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,42 @@ describe('#unit BoltProtocolV5x0', () => {
407407
['Time', new Time(1, 1, 1, 1, 1)],
408408
['Date', new Date(1, 1, 1)],
409409
['LocalDateTime', new LocalDateTime(1, 1, 1, 1, 1, 1, 1)],
410+
[
411+
'DateTimeWithZoneOffset',
412+
new DateTime(2022, 6, 14, 15, 21, 18, 183_000_000, 120 * 60)
413+
],
414+
[
415+
'DateTimeWithZoneId / Berlin 2:30 CET',
416+
new DateTime(2022, 10, 30, 2, 30, 0, 183_000_000, 2 * 60 * 60, 'Europe/Berlin')
417+
],
418+
[
419+
'DateTimeWithZoneId / Berlin 2:30 CEST',
420+
new DateTime(2022, 10, 30, 2, 30, 0, 183_000_000, 1 * 60 * 60, 'Europe/Berlin')
421+
],
422+
['Point2D', new Point(1, 1, 1)],
423+
['Point3D', new Point(1, 1, 1, 1)]
424+
])('should pack spatial types and temporal types (%s)', (_, object) => {
425+
const buffer = alloc(256)
426+
const protocol = new BoltProtocolV5x0(
427+
new utils.MessageRecordingConnection(),
428+
buffer,
429+
{
430+
disableLosslessIntegers: true
431+
}
432+
)
433+
434+
const packable = protocol.packable(object)
435+
436+
expect(packable).not.toThrow()
437+
438+
buffer.reset()
439+
440+
const unpacked = protocol.unpack(buffer)
441+
442+
expect(unpacked).toEqual(object)
443+
})
444+
445+
it.each([
410446
[
411447
'DateTimeWithZoneId / Australia',
412448
new DateTime(2022, 6, 15, 15, 21, 18, 183_000_000, undefined, 'Australia/Eucla')
@@ -478,14 +514,8 @@ describe('#unit BoltProtocolV5x0', () => {
478514
[
479515
'DateTimeWithZoneId / Sao Paulo just 1 after turn winter time',
480516
new DateTime(2019, 2, 18, 1, 0, 0, 183_000_000, undefined, 'America/Sao_Paulo')
481-
],
482-
[
483-
'DateTimeWithZoneOffset',
484-
new DateTime(2022, 6, 14, 15, 21, 18, 183_000_000, 120 * 60)
485-
],
486-
['Point2D', new Point(1, 1, 1)],
487-
['Point3D', new Point(1, 1, 1, 1)]
488-
])('should pack spatial types and temporal types (%s)', (_, object) => {
517+
]
518+
])('should pack and unpack DateTimeWithZoneId and without offset (%s)', (_, object) => {
489519
const buffer = alloc(256)
490520
const protocol = new BoltProtocolV5x0(
491521
new utils.MessageRecordingConnection(),
@@ -502,7 +532,22 @@ describe('#unit BoltProtocolV5x0', () => {
502532
buffer.reset()
503533

504534
const unpacked = protocol.unpack(buffer)
505-
expect(unpacked).toEqual(object)
535+
536+
expect(unpacked.timeZoneOffsetSeconds).toBeDefined()
537+
538+
const unpackedDateTimeWithoutOffset = new DateTime(
539+
unpacked.year,
540+
unpacked.month,
541+
unpacked.day,
542+
unpacked.hour,
543+
unpacked.minute,
544+
unpacked.second,
545+
unpacked.nanosecond,
546+
undefined,
547+
unpacked.timeZoneId
548+
)
549+
550+
expect(unpackedDateTimeWithoutOffset).toEqual(object)
506551
})
507552
})
508553

@@ -774,14 +819,14 @@ describe('#unit BoltProtocolV5x0', () => {
774819
new structure.Structure(0x69, [
775820
1655212878, 183_000_000, 'Europe/Berlin'
776821
]),
777-
new DateTime(2022, 6, 14, 15, 21, 18, 183_000_000, undefined, 'Europe/Berlin')
822+
new DateTime(2022, 6, 14, 15, 21, 18, 183_000_000, 2 * 60 * 60, 'Europe/Berlin')
778823
],
779824
[
780825
'DateTimeWithZoneId / Australia',
781826
new structure.Structure(0x69, [
782827
1655212878, 183_000_000, 'Australia/Eucla'
783828
]),
784-
new DateTime(2022, 6, 14, 22, 6, 18, 183_000_000, undefined, 'Australia/Eucla')
829+
new DateTime(2022, 6, 14, 22, 6, 18, 183_000_000, 8 * 60 * 60 + 45 * 60, 'Australia/Eucla')
785830
]
786831
])('should unpack spatial types and temporal types (%s)', (_, struct, object) => {
787832
const buffer = alloc(256)

0 commit comments

Comments
 (0)