From cbb4e1276ef40bfd1af4648c12ccbdb8e59509fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michele=20Masciav=C3=A8?= Date: Tue, 16 Jun 2026 14:17:36 +0200 Subject: [PATCH 1/6] solution --- CHANGELOG.md | 5 +++++ eslint.config.ts | 4 ++++ src/lib/date.spec.ts | 30 ++++++++++++++++++++++++++++++ src/lib/date.ts | 18 ++++++++++++++++++ 4 files changed, 57 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58adb25..6bf4f67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- `getDateWithoutTimeZone` utility function +- `getDateAddTimeZone` utility function + ## [2.4.0] - 2026-04-29 ### Added diff --git a/eslint.config.ts b/eslint.config.ts index ba8a24f..cfd0ed0 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -6,4 +6,8 @@ export default [ jest: true, jsdocRequireJsdoc: true, }), + { + files: ["src/lib/*.spec.ts"], + rules: { "max-lines": ["off"] }, + }, ]; diff --git a/src/lib/date.spec.ts b/src/lib/date.spec.ts index b2336f1..a09e9a2 100644 --- a/src/lib/date.spec.ts +++ b/src/lib/date.spec.ts @@ -12,6 +12,8 @@ import { getLastDayOfYear, addQuarters, getQuarter, + getDateAddTimeZone, + getDateWithoutTimeZone, } from "./date"; describe("date tests", () => { @@ -193,4 +195,32 @@ describe("date tests", () => { ])("addQuarters", (date, amount, expected) => { expect(addQuarters(date, amount).getTime()).toBe(expected.getTime()); }); + + test.each([ + [null as unknown as Date, new Date(Number.NaN)], + [undefined as unknown as Date, new Date(Number.NaN)], + [42 as unknown as Date, new Date(Number.NaN)], + ["2014-03-15" as unknown as Date, new Date(Number.NaN)], + [{ year: 2014, month: 2, day: 15 } as unknown as Date, new Date(Number.NaN)], + [new Date(2026, 6, 5, 0, 0, 0, 0), new Date(2026, 6, 5, 0, 0, 0, 0 + 120 * 60_000)], + [new Date(2026, 6, 5, 1, 12, 13, 1), new Date(2026, 6, 5, 1, 12, 13, 1 + 120 * 60_000)], + [new Date(2026, 12, 5, 0, 0, 0, 0), new Date(2026, 12, 5, 0, 0, 0, 0 + 60 * 60_000)], + [new Date(2026, 12, 5, 1, 12, 13, 1), new Date(2026, 12, 5, 1, 12, 13, 1 + 60 * 60_000)], + ])("getDateWithoutTimeZone", (date, expected) => { + expect(getDateWithoutTimeZone(date).getTime()).toBe(expected.getTime()); + }); + + test.each([ + [null as unknown as Date, new Date(Number.NaN)], + [undefined as unknown as Date, new Date(Number.NaN)], + [42 as unknown as Date, new Date(Number.NaN)], + ["2014-03-15" as unknown as Date, new Date(Number.NaN)], + [{ year: 2014, month: 2, day: 15 } as unknown as Date, new Date(Number.NaN)], + [new Date(2026, 6, 5, 0, 0, 0, 0), new Date(2026, 6, 5, 0, 0, 0, 0 - 120 * 60_000)], + [new Date(2026, 6, 5, 1, 12, 13, 1), new Date(2026, 6, 5, 1, 12, 13, 1 - 120 * 60_000)], + [new Date(2026, 12, 5, 0, 0, 0, 0), new Date(2026, 12, 5, 0, 0, 0, 0 - 60 * 60_000)], + [new Date(2026, 12, 5, 1, 12, 13, 1), new Date(2026, 12, 5, 1, 12, 13, 1 - 60 * 60_000)], + ])("getDateAddTimeZone", (date, expected) => { + expect(getDateAddTimeZone(date).getTime()).toBe(expected.getTime()); + }); }); diff --git a/src/lib/date.ts b/src/lib/date.ts index b91f628..63b8807 100644 --- a/src/lib/date.ts +++ b/src/lib/date.ts @@ -133,3 +133,21 @@ export function getQuarter(date: Date): number { export function addQuarters(date: Date, amount: number): Date { return dateIsValid(date) ? addQuartersInternal(date, amount) : new Date(Number.NaN); } + +/** + * Get the date removing the time-zone offset + * @param date The date + * @returns the given date removing the time-zone offset + */ +export function getDateWithoutTimeZone(date: Date): Date { + return dateIsValid(date) ? new Date(date.getTime() - date.getTimezoneOffset() * 60_000) : new Date(Number.NaN); +} + +/** + * Get the date adding the time-zone offset + * @param date The date + * @returns the given date adding the time-zone offset + */ +export function getDateAddTimeZone(date: Date): Date { + return dateIsValid(date) ? new Date(date.getTime() + date.getTimezoneOffset() * 60_000) : new Date(Number.NaN); +} From 87b6dd2a0c19f702a9fd14c715dd83a7c388ad2c Mon Sep 17 00:00:00 2001 From: Daniele Debernardi Date: Tue, 16 Jun 2026 14:36:25 +0200 Subject: [PATCH 2/6] fix timezone --- package.json | 3 ++- yarn.lock | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 03f7a6f..0432503 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "prettier-check": "prettier --check .", "prettier-write": "prettier --write .", "start": "rollup -c -w", - "test": "yarn jest", + "test": "cross-env TZ=Europe/Zurich yarn jest", "start-all": "concurrently \"yarn start\" \"yarn start-yalc\"", "start-yalc": "yarn nodemon --watch dist -x \"yarn yalc push\"" }, @@ -53,6 +53,7 @@ "@types/rollup-plugin-peer-deps-external": "^2.2.5", "@types/uuid": "^9.0.7", "concurrently": "^8.0.1", + "cross-env": "^10.1.0", "eslint": "^9.24.0", "jest": "^29.6.1", "jest-localstorage-mock": "^2.4.26", diff --git a/yarn.lock b/yarn.lock index a8b93d6..ae7d0ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -479,6 +479,11 @@ dependencies: tslib "^2.4.0" +"@epic-web/invariant@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@epic-web/invariant/-/invariant-1.0.0.tgz#1073e5dee6dd540410784990eb73e4acd25c9813" + integrity sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA== + "@es-joy/jsdoccomment@~0.49.0": version "0.49.0" resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz#e5ec1eda837c802eca67d3b29e577197f14ba1db" @@ -2401,6 +2406,14 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-env@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-10.1.0.tgz#cfd2a6200df9ed75bfb9cb3d7ce609c13ea21783" + integrity sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw== + dependencies: + "@epic-web/invariant" "^1.0.0" + cross-spawn "^7.0.6" + cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" From f729c026bfb44bc70d1a0d3eb8b34dea075d9d29 Mon Sep 17 00:00:00 2001 From: Daniele Debernardi Date: Tue, 16 Jun 2026 14:46:59 +0200 Subject: [PATCH 3/6] fix node version --- .nvmrc | 1 + package.json | 2 +- yarn.lock | 18 ++++++------------ 3 files changed, 8 insertions(+), 13 deletions(-) create mode 100644 .nvmrc diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..3c03207 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +18 diff --git a/package.json b/package.json index 0432503..8ed683b 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@types/rollup-plugin-peer-deps-external": "^2.2.5", "@types/uuid": "^9.0.7", "concurrently": "^8.0.1", - "cross-env": "^10.1.0", + "cross-env": "^7.0.3", "eslint": "^9.24.0", "jest": "^29.6.1", "jest-localstorage-mock": "^2.4.26", diff --git a/yarn.lock b/yarn.lock index ae7d0ed..060a91e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -479,11 +479,6 @@ dependencies: tslib "^2.4.0" -"@epic-web/invariant@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@epic-web/invariant/-/invariant-1.0.0.tgz#1073e5dee6dd540410784990eb73e4acd25c9813" - integrity sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA== - "@es-joy/jsdoccomment@~0.49.0": version "0.49.0" resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz#e5ec1eda837c802eca67d3b29e577197f14ba1db" @@ -2406,15 +2401,14 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-env@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-10.1.0.tgz#cfd2a6200df9ed75bfb9cb3d7ce609c13ea21783" - integrity sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw== +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== dependencies: - "@epic-web/invariant" "^1.0.0" - cross-spawn "^7.0.6" + cross-spawn "^7.0.1" -cross-spawn@^7.0.3, cross-spawn@^7.0.6: +cross-spawn@^7.0.1, cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== From ad4cb75717e599119566d36ba8b6f6c5a4a64092 Mon Sep 17 00:00:00 2001 From: Daniele Debernardi Date: Tue, 16 Jun 2026 14:54:24 +0200 Subject: [PATCH 4/6] fix timezone in pipeline --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a584a96..29b3f5d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,6 +89,8 @@ jobs: - run: yarn lint - run: yarn build - run: yarn jest + env: + TZ: Europe/Zurich - name: Code Coverage Summary Report uses: irongut/CodeCoverageSummary@v1.3.0 From 0fdca8195d8791511fb8b959ac688866a178acaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michele=20Masciav=C3=A8?= Date: Tue, 16 Jun 2026 14:58:24 +0200 Subject: [PATCH 5/6] Trigger checks From 8c6012d1980f6964d2e1c6c7be309654f6131a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michele=20Masciav=C3=A8?= Date: Tue, 16 Jun 2026 15:02:35 +0200 Subject: [PATCH 6/6] test --- src/lib/date.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/date.spec.ts b/src/lib/date.spec.ts index a09e9a2..2913f89 100644 --- a/src/lib/date.spec.ts +++ b/src/lib/date.spec.ts @@ -200,7 +200,7 @@ describe("date tests", () => { [null as unknown as Date, new Date(Number.NaN)], [undefined as unknown as Date, new Date(Number.NaN)], [42 as unknown as Date, new Date(Number.NaN)], - ["2014-03-15" as unknown as Date, new Date(Number.NaN)], + ["2015-03-15" as unknown as Date, new Date(Number.NaN)], [{ year: 2014, month: 2, day: 15 } as unknown as Date, new Date(Number.NaN)], [new Date(2026, 6, 5, 0, 0, 0, 0), new Date(2026, 6, 5, 0, 0, 0, 0 + 120 * 60_000)], [new Date(2026, 6, 5, 1, 12, 13, 1), new Date(2026, 6, 5, 1, 12, 13, 1 + 120 * 60_000)], @@ -214,7 +214,7 @@ describe("date tests", () => { [null as unknown as Date, new Date(Number.NaN)], [undefined as unknown as Date, new Date(Number.NaN)], [42 as unknown as Date, new Date(Number.NaN)], - ["2014-03-15" as unknown as Date, new Date(Number.NaN)], + ["2015-03-15" as unknown as Date, new Date(Number.NaN)], [{ year: 2014, month: 2, day: 15 } as unknown as Date, new Date(Number.NaN)], [new Date(2026, 6, 5, 0, 0, 0, 0), new Date(2026, 6, 5, 0, 0, 0, 0 - 120 * 60_000)], [new Date(2026, 6, 5, 1, 12, 13, 1), new Date(2026, 6, 5, 1, 12, 13, 1 - 120 * 60_000)],