From 968ea1747e5a4311ea757415960153c057120a90 Mon Sep 17 00:00:00 2001 From: Greta Dragan Date: Thu, 12 Jun 2025 15:34:50 +0200 Subject: [PATCH 1/2] ZincReader: fix parsing of timezones containing "-" --- spec/core/ZincReader.spec.ts | 106 +++++++++++++++++++++++++++++++++++ src/core/ZincReader.ts | 18 +----- 2 files changed, 109 insertions(+), 15 deletions(-) diff --git a/spec/core/ZincReader.spec.ts b/spec/core/ZincReader.spec.ts index a8b5fbd..18f4db0 100644 --- a/spec/core/ZincReader.spec.ts +++ b/spec/core/ZincReader.spec.ts @@ -443,6 +443,34 @@ describe('ZincReader', function (): void { HDateTime.make('2010-11-28T07:23:02.773-08:00 Los_Angeles') ) }) + + it('parses a date time with timezone containing -', function (): void { + expect( + makeReader( + '2010-11-28T07:23:02.773-04:00 Port-au-Prince' + ).readValue() + ).toEqual( + HDateTime.make( + '2010-11-28T07:23:02.773-04:00 Port-au-Prince' + ) + ) + }) + + it('parses a date time with GMT-n timezone', function (): void { + expect( + makeReader( + '2025-06-12T15:22:11.518+02:00 GMT-2' + ).readValue() + ).toEqual(HDateTime.make('2025-06-12T15:22:11.518+02:00 GMT-2')) + }) + + it('parses a date time with GMT+n timezone', function (): void { + expect( + makeReader( + '2025-06-12T11:23:32.488-02:00 GMT+2' + ).readValue() + ).toEqual(HDateTime.make('2025-06-12T11:23:32.488-02:00 GMT+2')) + }) }) // date time describe('null', function (): void { @@ -1325,6 +1353,84 @@ describe('ZincReader', function (): void { const value = ZincReader.readValue(zinc) expect(value && value.equals(grid)).toBe(true) }) + + it('parses a grid with a datetime and timezone containing -', function (): void { + const zinc = + '<>' + + const grid = HGrid.make({ + columns: [ + { + name: 'val', + }, + ], + rows: [ + HDict.make({ + val: HDateTime.make( + '2025-06-12T08:24:25.631-04:00 Port-au-Prince' + ), + }), + ], + }) + + const value = makeReader(zinc).readValue() + expect(value && value.equals(grid)).toBe(true) + }) + + it('parses a grid with a datetime and GMT-n timezone val', function (): void { + const zinc = + '<>' + + const grid = HGrid.make({ + columns: [ + { + name: 'val', + }, + ], + rows: [ + HDict.make({ + val: HDateTime.make( + '2025-06-12T14:54:00.88+02:00 GMT-2' + ), + }), + ], + }) + + const value = makeReader(zinc).readValue() + expect(value && value.equals(grid)).toBe(true) + }) + + it('parses a grid with a datetime and GMT+n timezone val', function (): void { + const zinc = + '<>' + + const grid = HGrid.make({ + columns: [ + { + name: 'val', + }, + ], + rows: [ + HDict.make({ + val: HDateTime.make( + '2025-06-12T14:54:00.88-02:00 GMT+2' + ), + }), + ], + }) + + const value = makeReader(zinc).readValue() + expect(value && value.equals(grid)).toBe(true) + }) }) // grid }) // #nextValue() diff --git a/src/core/ZincReader.ts b/src/core/ZincReader.ts index 9d31b9b..14bcbf4 100644 --- a/src/core/ZincReader.ts +++ b/src/core/ZincReader.ts @@ -555,21 +555,9 @@ export class ZincReader { while ( this.scanner.isLetter() || this.scanner.isDigit() || - this.scanner.is('_') - ) { - dateTime += this.scanner.current - this.scanner.consume() - - while (this.scanner.isDigit()) { - dateTime += this.scanner.current - this.scanner.consume() - } - } - - // handle GMT+xx or GMT-xx - if ( - (this.scanner.is('+') || this.scanner.is('-')) && - dateTime.endsWith('GMT') + this.scanner.is('_') || // Tz containing "_" (ex.: Los_Angeles) + this.scanner.is('-') || // GMT-n or tz containing "-" (ex.: Port-au-Prince) + this.scanner.is('+') // GMT+n ) { dateTime += this.scanner.current this.scanner.consume() From 5de7b6a7b149ae070e0ee2cb1b39e7ce8a49c3c7 Mon Sep 17 00:00:00 2001 From: Greta Dragan Date: Thu, 12 Jun 2025 16:15:32 +0200 Subject: [PATCH 2/2] ZincReader: improve tests explicitly checking timezone --- spec/core/ZincReader.spec.ts | 47 ++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/spec/core/ZincReader.spec.ts b/spec/core/ZincReader.spec.ts index 18f4db0..dfa036f 100644 --- a/spec/core/ZincReader.spec.ts +++ b/spec/core/ZincReader.spec.ts @@ -445,31 +445,42 @@ describe('ZincReader', function (): void { }) it('parses a date time with timezone containing -', function (): void { - expect( - makeReader( - '2010-11-28T07:23:02.773-04:00 Port-au-Prince' - ).readValue() - ).toEqual( - HDateTime.make( - '2010-11-28T07:23:02.773-04:00 Port-au-Prince' - ) + const parsedVal = makeReader( + '2010-11-28T07:23:02.773-04:00 Port-au-Prince' + ).readValue() + const expectedVal = HDateTime.make( + '2010-11-28T07:23:02.773-04:00 Port-au-Prince' + ) + expect(parsedVal).toEqual(expectedVal) + expect((parsedVal as HDateTime).timezone).toBe( + expectedVal.timezone ) }) it('parses a date time with GMT-n timezone', function (): void { - expect( - makeReader( - '2025-06-12T15:22:11.518+02:00 GMT-2' - ).readValue() - ).toEqual(HDateTime.make('2025-06-12T15:22:11.518+02:00 GMT-2')) + const parsedVal = makeReader( + '2025-06-12T15:22:11.518+02:00 GMT-2' + ).readValue() + const expectedVal = HDateTime.make( + '2025-06-12T15:22:11.518+02:00 GMT-2' + ) + expect(parsedVal).toEqual(expectedVal) + expect((parsedVal as HDateTime).timezone).toBe( + expectedVal.timezone + ) }) it('parses a date time with GMT+n timezone', function (): void { - expect( - makeReader( - '2025-06-12T11:23:32.488-02:00 GMT+2' - ).readValue() - ).toEqual(HDateTime.make('2025-06-12T11:23:32.488-02:00 GMT+2')) + const parsedVal = makeReader( + '2025-06-12T11:23:32.488-02:00 GMT+2' + ).readValue() + const expectedVal = HDateTime.make( + '2025-06-12T11:23:32.488-02:00 GMT+2' + ) + expect(parsedVal).toEqual(expectedVal) + expect((parsedVal as HDateTime).timezone).toBe( + expectedVal.timezone + ) }) }) // date time