diff --git a/CHANGELOG.md b/CHANGELOG.md index 110e55b..f759baf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # deverything +## 1.11.1 + +### Patch Changes + +- fix parseDate to be always local + ## 1.11.0 ### Minor Changes diff --git a/package.json b/package.json index 9aebf9c..5e681da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "deverything", - "version": "1.11.0", + "version": "1.11.1", "description": "Everything you need for Dev", "main": "./dist/index.js", "module": "./dist/index.mjs", diff --git a/src/helpers/getUrlSearchParams.test.ts b/src/helpers/getUrlSearchParams.test.ts index 389210b..348b616 100644 --- a/src/helpers/getUrlSearchParams.test.ts +++ b/src/helpers/getUrlSearchParams.test.ts @@ -2,6 +2,17 @@ import { describe, expect, test } from "@jest/globals"; import { getUrlSearchParams } from "./getUrlSearchParams"; describe("getUrlSearchParams", () => { + test("no domain", async () => { + expect(getUrlSearchParams("/")).toStrictEqual({}); + expect(getUrlSearchParams("/?param=")).toStrictEqual({ + param: "", + }); + expect(getUrlSearchParams("/?param1=123¶m2=asd")).toStrictEqual({ + param1: "123", + param2: "asd", + }); + }); + test("found", async () => { expect(getUrlSearchParams("https")).toStrictEqual({}); expect(getUrlSearchParams("https://www.ciao.com")).toStrictEqual({}); diff --git a/src/helpers/getUrlSearchParams.ts b/src/helpers/getUrlSearchParams.ts index c5a8f10..f1cfd63 100644 --- a/src/helpers/getUrlSearchParams.ts +++ b/src/helpers/getUrlSearchParams.ts @@ -5,7 +5,12 @@ export const getUrlSearchParams = ( ): Record => { if (!urlString) return {}; try { - const url = new URL(urlString); + const isRelativeUrl = urlString.startsWith("/"); + const url = new URL( + urlString, + isRelativeUrl ? "https://deverything.dev/" : undefined // add base to make relative urls work + ); + return Object.fromEntries(url.searchParams); } catch (_e) { return {}; diff --git a/src/helpers/parseDate.test.ts b/src/helpers/parseDate.test.ts index 1dc5bbd..70cb706 100644 --- a/src/helpers/parseDate.test.ts +++ b/src/helpers/parseDate.test.ts @@ -1,6 +1,7 @@ -import { describe, expect, test } from "@jest/globals"; +import { afterAll, beforeAll, describe, expect, test } from "@jest/globals"; import { MAX_DATE_MILLISECONDS } from "../constants/time"; import { parseDate } from "./parseDate"; +import timezoneMock from "timezone-mock"; // TODO: add string with millis 1678792327650170902 describe("parseDate", () => { @@ -17,12 +18,76 @@ describe("parseDate", () => { expect(parseDate(MAX_DATE_MILLISECONDS + 1)).toBeUndefined(); }); - test("date", async () => { - expect(parseDate(new Date("2000-01-01"))).toStrictEqual( - new Date("2000-01-01") - ); + describe("ISO date with non UTC timezone", () => { + beforeAll(() => { + // If this test is run in UTC, it will always pass! + timezoneMock.register("Australia/Adelaide"); + }); + afterAll(() => { + timezoneMock.unregister(); + }); + test("year", async () => { + expect(parseDate("2000")!.toISOString()).toStrictEqual( + new Date("2000-01-01T00:00:00.000+10:30").toISOString() + ); + }); - expect(parseDate(new Date("2000-00-00"))).toBeUndefined(); - expect(parseDate(new Date("2000-02-32"))).toBeUndefined(); + test("month", async () => { + expect(parseDate("2000-14")).toBeUndefined(); + + expect(parseDate("2000-02")).toStrictEqual( + new Date("2000-02-01T00:00:00.000+10:30") + ); + }); + + test("day", async () => { + expect(parseDate("2000-00-00")).toBeUndefined(); + expect(parseDate("2000-02-32")).toBeUndefined(); + + expect(parseDate("2000-02-21")).toStrictEqual( + new Date("2000-02-21T00:00:00.000+10:30") + ); + }); + + test("time", async () => { + expect(parseDate("2000-02-02T40:00:00")).toBeUndefined(); + + expect(parseDate("2000-02-21T00:00:00")).toStrictEqual( + new Date("2000-02-21T00:00:00.000+10:30") + ); + }); + }); + + describe("ISO date UTC (servers default)", () => { + test("year", async () => { + expect(parseDate("2000")).toStrictEqual( + new Date("2000-01-01T00:00:00.000Z") + ); + }); + + test("month", async () => { + expect(parseDate("2000-14")).toBeUndefined(); + + expect(parseDate("2000-02")).toStrictEqual( + new Date("2000-02-01T00:00:00.000Z") + ); + }); + + test("day", async () => { + expect(parseDate("2000-00-00")).toBeUndefined(); + expect(parseDate("2000-02-32")).toBeUndefined(); + + expect(parseDate("2000-02-21")).toStrictEqual( + new Date("2000-02-21T00:00:00.000Z") + ); + }); + + test("time", async () => { + expect(parseDate("2000-02-02T40:00:00")).toBeUndefined(); + + expect(parseDate("2000-02-21T00:00:00")).toStrictEqual( + new Date("2000-02-21T00:00:00.000Z") + ); + }); }); }); diff --git a/src/helpers/parseDate.ts b/src/helpers/parseDate.ts index 4aff04a..e3f3608 100644 --- a/src/helpers/parseDate.ts +++ b/src/helpers/parseDate.ts @@ -1,11 +1,23 @@ import { DateLike, Maybe } from "../types"; import { isEmpty } from "../validators/isEmpty"; import { isJsDate } from "../validators/isJsDate"; +import { isString } from "../validators/isString"; + +const partialDateRegex = /^\d{4}(-\d{2})?(-\d{2})?$/; export const parseDate = (arg?: Maybe) => { if (isEmpty(arg)) return; - const date = new Date(arg!); + if (isString(arg) && partialDateRegex.test(arg)) { + // Add time to date string because it will be interpreted + // as UTC date instead of local time, and there is no + // circumstance where UTC as default is desired. + arg = `${ + arg + "-01-01".slice(arg.length - 4) // fill missing month and day if needed + }T00:00:00`; + } + + const date = new Date(arg!); // ! => isEmpty cannot narrow type if (!isJsDate(date)) return;