From 3d741f435fc7439e495a613ab3851b3cdf76952f Mon Sep 17 00:00:00 2001 From: Dion Date: Tue, 5 Nov 2024 12:57:24 +0100 Subject: [PATCH 1/6] #1508 invalid date time --- .../starsky/clientapp/src/shared/data.spec.ts | 16 +++++++++++----- starsky/starsky/clientapp/src/shared/date.ts | 7 +++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/starsky/starsky/clientapp/src/shared/data.spec.ts b/starsky/starsky/clientapp/src/shared/data.spec.ts index 5de76fb9cb..c7009f7fdd 100644 --- a/starsky/starsky/clientapp/src/shared/data.spec.ts +++ b/starsky/starsky/clientapp/src/shared/data.spec.ts @@ -10,7 +10,7 @@ import { parseTimeHour, SecondsToHours } from "./date"; -import { SupportedLanguages } from "./language"; +import {SupportedLanguages} from "./language"; describe("date", () => { describe("parseDate", () => { @@ -24,6 +24,12 @@ describe("date", () => { // NOT Invalid! expect(result).not.toBe("Invalid Date"); }); + + it("Timezone time", () => { + const result = parseDate("2020-04-28T10:44:43.123456+01:00", SupportedLanguages.nl); + expect(result).not.toBe("Invalid Date"); + }); + it("wrong format", () => { const result = parseDate("2020-30", SupportedLanguages.nl); expect(result).toBe("Invalid Date"); @@ -219,11 +225,11 @@ describe("date", () => { let dayBeforeYesterday = `${dayBeforeYesterdayDate.getFullYear()}- ${leftPad(dayBeforeYesterdayDate.getMonth() + 1)}-${leftPad( - dayBeforeYesterdayDate.getDate() - )}T + dayBeforeYesterdayDate.getDate() + )}T ${leftPad(dayBeforeYesterdayDate.getHours())}:${leftPad( - dayBeforeYesterdayDate.getMinutes() - )}: + dayBeforeYesterdayDate.getMinutes() + )}: ${leftPad(dayBeforeYesterdayDate.getSeconds())}`; // remove space and newlines from prev variable diff --git a/starsky/starsky/clientapp/src/shared/date.ts b/starsky/starsky/clientapp/src/shared/date.ts index 1112cfd1a4..13718c104e 100644 --- a/starsky/starsky/clientapp/src/shared/date.ts +++ b/starsky/starsky/clientapp/src/shared/date.ts @@ -1,4 +1,4 @@ -import { SupportedLanguages } from "./language"; +import {SupportedLanguages} from "./language"; /** * Is the date Valid? @@ -77,8 +77,11 @@ const parseRelativeDate = ( */ const parseDate = (dateTime: string | undefined, locate: SupportedLanguages): string => { if (!dateTime) return ""; + const timeZoneRegex = /\+\d{2}:\d{2}/; + const isIncludeTimezone = timeZoneRegex.test(dateTime); + // UTC DateTime already ends with Z - const dateTimeObject = new Date(!dateTime.endsWith("Z") ? `${dateTime}Z` : dateTime); + const dateTimeObject = new Date(!dateTime.endsWith("Z") && !isIncludeTimezone ? `${dateTime}Z` : dateTime); // We prefer British English, uses day-month-year order const locateString = locate === SupportedLanguages.en ? "en-GB" : locate.toString(); if (dateTime.endsWith("Z")) { From a3c3ca3512251ce646f6c4fa72628d613329be84 Mon Sep 17 00:00:00 2001 From: Dion Date: Tue, 5 Nov 2024 13:03:04 +0100 Subject: [PATCH 2/6] #1508 update jsdoc --- starsky/starsky/clientapp/src/shared/date.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starsky/starsky/clientapp/src/shared/date.ts b/starsky/starsky/clientapp/src/shared/date.ts index 13718c104e..c302a03519 100644 --- a/starsky/starsky/clientapp/src/shared/date.ts +++ b/starsky/starsky/clientapp/src/shared/date.ts @@ -72,7 +72,7 @@ const parseRelativeDate = ( }; /** * Get Date complete parsed for example: Monday, 4 May 2020 - * @param dateTime 2018-09-11T11:23:19 or 2018-09-11T11:23:19Z + * @param dateTime 2018-09-11T11:23:19, 2018-09-11T11:23:19Z or 2020-04-28T10:44:43.123456+01:00 * @param locate Language */ const parseDate = (dateTime: string | undefined, locate: SupportedLanguages): string => { From 6b0c98ac1d88cf140b1cc4be8c168ff7ddffc290 Mon Sep 17 00:00:00 2001 From: Dion Date: Tue, 5 Nov 2024 13:11:03 +0100 Subject: [PATCH 3/6] #1508 test more cases --- .../starsky/clientapp/src/shared/data.spec.ts | 38 ++++++++++++++++++- starsky/starsky/clientapp/src/shared/date.ts | 20 ++++++---- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/starsky/starsky/clientapp/src/shared/data.spec.ts b/starsky/starsky/clientapp/src/shared/data.spec.ts index c7009f7fdd..0f8cf2792e 100644 --- a/starsky/starsky/clientapp/src/shared/data.spec.ts +++ b/starsky/starsky/clientapp/src/shared/data.spec.ts @@ -27,7 +27,7 @@ describe("date", () => { it("Timezone time", () => { const result = parseDate("2020-04-28T10:44:43.123456+01:00", SupportedLanguages.nl); - expect(result).not.toBe("Invalid Date"); + expect(result).toBe("dinsdag 28 april 2020"); }); it("wrong format", () => { @@ -57,6 +57,11 @@ describe("date", () => { expect(result).toBe("01:01:01"); }); + it("Timezone time (parseTime)", () => { + const result = parseTime("2020-04-28T10:44:43.123456+01:00"); + expect(result).toBe("09:44:43"); + }); + it("right formatted summer time (nl)", () => { const result = parseTime("2020-04-10T23:40:33"); expect(result).toBe("23:40:33"); @@ -79,6 +84,11 @@ describe("date", () => { expect(result).toBe(1); }); + it("Timezone time (parseTimeHour)", () => { + const result = parseTimeHour("2020-04-28T10:44:43.123456+01:00"); + expect(result).toBe(9); + }); + it("right formatted summer time (nl)", () => { const result = parseTimeHour("2020-04-10T23:40:33"); expect(result).toBe(23); @@ -101,6 +111,11 @@ describe("date", () => { expect(result).toBe(1); }); + it("Timezone time (parseDateDate)", () => { + const result = parseDateDate("2020-04-28T10:44:43.123456+01:00"); + expect(result).toBe(28); + }); + it("right formatted summer time (nl)", () => { const result = parseDateDate("2020-04-10T23:40:33"); expect(result).toBe(10); @@ -123,6 +138,11 @@ describe("date", () => { expect(result).toBe(1); }); + it("Timezone time (parseDateMonth)", () => { + const result = parseDateMonth("2020-04-28T10:44:43.123456+01:00"); + expect(result).toBe(4); + }); + it("right formatted summer time (nl)", () => { const result = parseDateMonth("2020-12-10T23:40:33"); expect(result).toBe(12); @@ -145,6 +165,11 @@ describe("date", () => { expect(result).toBe(2020); }); + it("Timezone time (parseDateYear)", () => { + const result = parseDateYear("2020-04-28T10:44:43.123456+01:00"); + expect(result).toBe(2020); + }); + it("right formatted summer time (nl)", () => { const result = parseDateYear("2020-12-10T23:40:33"); expect(result).toBe(2020); @@ -166,6 +191,12 @@ describe("date", () => { const result = isValidDate("2019-10-12 14:12:00"); expect(result).toBeTruthy(); }); + + it("Timezone time (isValidDate)", () => { + const result = isValidDate("2020-04-28T10:44:43.123456+01:00"); + expect(result).toBe(true); + }); + }); describe("parseRelativeDate", () => { @@ -184,6 +215,11 @@ describe("date", () => { expect(result).toBe(""); }); + it("Timezone time (isValidDate)", () => { + const result = parseRelativeDate("2020-04-28T10:44:43.123456+01:00", SupportedLanguages.en); + expect(result).toBe("Tuesday, 28 April 2020"); + }); + it("yesterday", () => { const yesterdayDate = new Date(); diff --git a/starsky/starsky/clientapp/src/shared/date.ts b/starsky/starsky/clientapp/src/shared/date.ts index c302a03519..6f373e8feb 100644 --- a/starsky/starsky/clientapp/src/shared/date.ts +++ b/starsky/starsky/clientapp/src/shared/date.ts @@ -70,6 +70,12 @@ const parseRelativeDate = ( return parseDate(inputDateTime, locate); } }; + +const IsIncludeTimezone = (dateTime: string): boolean => { + const timeZoneRegex = /\+\d{2}:\d{2}/; + return timeZoneRegex.test(dateTime); +} + /** * Get Date complete parsed for example: Monday, 4 May 2020 * @param dateTime 2018-09-11T11:23:19, 2018-09-11T11:23:19Z or 2020-04-28T10:44:43.123456+01:00 @@ -77,11 +83,9 @@ const parseRelativeDate = ( */ const parseDate = (dateTime: string | undefined, locate: SupportedLanguages): string => { if (!dateTime) return ""; - const timeZoneRegex = /\+\d{2}:\d{2}/; - const isIncludeTimezone = timeZoneRegex.test(dateTime); // UTC DateTime already ends with Z - const dateTimeObject = new Date(!dateTime.endsWith("Z") && !isIncludeTimezone ? `${dateTime}Z` : dateTime); + const dateTimeObject = new Date(!dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime); // We prefer British English, uses day-month-year order const locateString = locate === SupportedLanguages.en ? "en-GB" : locate.toString(); if (dateTime.endsWith("Z")) { @@ -110,7 +114,7 @@ const parseDateDate = (dateTime: string | undefined): number => { if (!isValidDate(dateTime) || !dateTime) { return 1; } - const dateTimeObject = new Date(!dateTime.endsWith("Z") ? `${dateTime}Z` : dateTime); + const dateTimeObject = new Date(!dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime); // toLocaleDateString assumes that the input is UTC, which is usually not the case const numberValue = dateTimeObject.toLocaleDateString([], { timeZone: !dateTime.endsWith("Z") ? "UTC" : undefined, @@ -127,7 +131,7 @@ const parseDateYear = (dateTime: string | undefined): number => { if (!isValidDate(dateTime) || !dateTime) { return 1; } - const dateTimeObject = new Date(!dateTime.endsWith("Z") ? `${dateTime}Z` : dateTime); + const dateTimeObject = new Date(!dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime); // toLocaleDateString assumes that the input is UTC, which is usually not the case const numberValue = dateTimeObject.toLocaleDateString([], { timeZone: !dateTime.endsWith("Z") ? "UTC" : undefined, @@ -144,7 +148,7 @@ const parseDateMonth = (dateTime: string | undefined): number => { if (!isValidDate(dateTime) || !dateTime) { return 1; } - const dateTimeObject = new Date(!dateTime.endsWith("Z") ? `${dateTime}Z` : dateTime); + const dateTimeObject = new Date(!dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime); // toLocaleDateString assumes that the input is UTC, which is usually not the case const numberValue = dateTimeObject.toLocaleDateString([], { timeZone: !dateTime.endsWith("Z") ? "UTC" : undefined, @@ -161,7 +165,7 @@ const parseTime = (dateTime: string | undefined): string => { if (!isValidDate(dateTime) || !dateTime) { return ""; } - const dateTimeObject = new Date(!dateTime.endsWith("Z") ? `${dateTime}Z` : dateTime); + const dateTimeObject = new Date(!dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime); // toLocaleDateString assumes that the input is UTC, which is usually not the case return dateTimeObject.toLocaleTimeString([], { @@ -181,7 +185,7 @@ const parseTimeHour = (dateTime: string | undefined): number => { if (!isValidDate(dateTime) || !dateTime) { return 1; } - const dateTimeObject = new Date(!dateTime.endsWith("Z") ? `${dateTime}Z` : dateTime); + const dateTimeObject = new Date(!dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime); // toLocaleDateString assumes that the input is UTC, which is usually not the case const numberValue = dateTimeObject.toLocaleTimeString([], { timeZone: !dateTime.endsWith("Z") ? "UTC" : undefined, From 4464d122a6e30033799bcd6f12d97012f7c60ae9 Mon Sep 17 00:00:00 2001 From: Dion Date: Tue, 5 Nov 2024 13:12:54 +0100 Subject: [PATCH 4/6] #1508 lint fix --- .../starsky/clientapp/src/shared/data.spec.ts | 11 ++++---- starsky/starsky/clientapp/src/shared/date.ts | 28 +++++++++++++------ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/starsky/starsky/clientapp/src/shared/data.spec.ts b/starsky/starsky/clientapp/src/shared/data.spec.ts index 0f8cf2792e..8fe858c310 100644 --- a/starsky/starsky/clientapp/src/shared/data.spec.ts +++ b/starsky/starsky/clientapp/src/shared/data.spec.ts @@ -10,7 +10,7 @@ import { parseTimeHour, SecondsToHours } from "./date"; -import {SupportedLanguages} from "./language"; +import { SupportedLanguages } from "./language"; describe("date", () => { describe("parseDate", () => { @@ -196,7 +196,6 @@ describe("date", () => { const result = isValidDate("2020-04-28T10:44:43.123456+01:00"); expect(result).toBe(true); }); - }); describe("parseRelativeDate", () => { @@ -261,11 +260,11 @@ describe("date", () => { let dayBeforeYesterday = `${dayBeforeYesterdayDate.getFullYear()}- ${leftPad(dayBeforeYesterdayDate.getMonth() + 1)}-${leftPad( - dayBeforeYesterdayDate.getDate() - )}T + dayBeforeYesterdayDate.getDate() + )}T ${leftPad(dayBeforeYesterdayDate.getHours())}:${leftPad( - dayBeforeYesterdayDate.getMinutes() - )}: + dayBeforeYesterdayDate.getMinutes() + )}: ${leftPad(dayBeforeYesterdayDate.getSeconds())}`; // remove space and newlines from prev variable diff --git a/starsky/starsky/clientapp/src/shared/date.ts b/starsky/starsky/clientapp/src/shared/date.ts index 6f373e8feb..caaf546b93 100644 --- a/starsky/starsky/clientapp/src/shared/date.ts +++ b/starsky/starsky/clientapp/src/shared/date.ts @@ -1,4 +1,4 @@ -import {SupportedLanguages} from "./language"; +import { SupportedLanguages } from "./language"; /** * Is the date Valid? @@ -74,7 +74,7 @@ const parseRelativeDate = ( const IsIncludeTimezone = (dateTime: string): boolean => { const timeZoneRegex = /\+\d{2}:\d{2}/; return timeZoneRegex.test(dateTime); -} +}; /** * Get Date complete parsed for example: Monday, 4 May 2020 @@ -85,7 +85,9 @@ const parseDate = (dateTime: string | undefined, locate: SupportedLanguages): st if (!dateTime) return ""; // UTC DateTime already ends with Z - const dateTimeObject = new Date(!dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime); + const dateTimeObject = new Date( + !dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime + ); // We prefer British English, uses day-month-year order const locateString = locate === SupportedLanguages.en ? "en-GB" : locate.toString(); if (dateTime.endsWith("Z")) { @@ -114,7 +116,9 @@ const parseDateDate = (dateTime: string | undefined): number => { if (!isValidDate(dateTime) || !dateTime) { return 1; } - const dateTimeObject = new Date(!dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime); + const dateTimeObject = new Date( + !dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime + ); // toLocaleDateString assumes that the input is UTC, which is usually not the case const numberValue = dateTimeObject.toLocaleDateString([], { timeZone: !dateTime.endsWith("Z") ? "UTC" : undefined, @@ -131,7 +135,9 @@ const parseDateYear = (dateTime: string | undefined): number => { if (!isValidDate(dateTime) || !dateTime) { return 1; } - const dateTimeObject = new Date(!dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime); + const dateTimeObject = new Date( + !dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime + ); // toLocaleDateString assumes that the input is UTC, which is usually not the case const numberValue = dateTimeObject.toLocaleDateString([], { timeZone: !dateTime.endsWith("Z") ? "UTC" : undefined, @@ -148,7 +154,9 @@ const parseDateMonth = (dateTime: string | undefined): number => { if (!isValidDate(dateTime) || !dateTime) { return 1; } - const dateTimeObject = new Date(!dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime); + const dateTimeObject = new Date( + !dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime + ); // toLocaleDateString assumes that the input is UTC, which is usually not the case const numberValue = dateTimeObject.toLocaleDateString([], { timeZone: !dateTime.endsWith("Z") ? "UTC" : undefined, @@ -165,7 +173,9 @@ const parseTime = (dateTime: string | undefined): string => { if (!isValidDate(dateTime) || !dateTime) { return ""; } - const dateTimeObject = new Date(!dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime); + const dateTimeObject = new Date( + !dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime + ); // toLocaleDateString assumes that the input is UTC, which is usually not the case return dateTimeObject.toLocaleTimeString([], { @@ -185,7 +195,9 @@ const parseTimeHour = (dateTime: string | undefined): number => { if (!isValidDate(dateTime) || !dateTime) { return 1; } - const dateTimeObject = new Date(!dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime); + const dateTimeObject = new Date( + !dateTime.endsWith("Z") && !IsIncludeTimezone(dateTime) ? `${dateTime}Z` : dateTime + ); // toLocaleDateString assumes that the input is UTC, which is usually not the case const numberValue = dateTimeObject.toLocaleTimeString([], { timeZone: !dateTime.endsWith("Z") ? "UTC" : undefined, From 752d91838f71d3f96ed4e27d23dd3465f7b67782 Mon Sep 17 00:00:00 2001 From: Dion Date: Tue, 5 Nov 2024 13:19:25 +0100 Subject: [PATCH 5/6] #1508 comma issue --- starsky/starsky/clientapp/src/shared/data.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/starsky/starsky/clientapp/src/shared/data.spec.ts b/starsky/starsky/clientapp/src/shared/data.spec.ts index 8fe858c310..9a36cb8a19 100644 --- a/starsky/starsky/clientapp/src/shared/data.spec.ts +++ b/starsky/starsky/clientapp/src/shared/data.spec.ts @@ -216,7 +216,8 @@ describe("date", () => { it("Timezone time (isValidDate)", () => { const result = parseRelativeDate("2020-04-28T10:44:43.123456+01:00", SupportedLanguages.en); - expect(result).toBe("Tuesday, 28 April 2020"); + expect(result).toContain("Tuesday"); // with or without comma + expect(result).toContain("28 April 2020"); }); it("yesterday", () => { From 0778d9ebe1c91cc2f3639a240c810eb81515fb9c Mon Sep 17 00:00:00 2001 From: Dion Date: Tue, 5 Nov 2024 13:23:57 +0100 Subject: [PATCH 6/6] keep a changelog --- history.md | 1 + 1 file changed, 1 insertion(+) diff --git a/history.md b/history.md index 7ab49baacc..cba6c481af 100644 --- a/history.md +++ b/history.md @@ -51,6 +51,7 @@ Semantic Versioning 2.0.0 is from version 0.1.6+ - [x] (Fixed) _Back-end_ Suggest API gives 200 when no suggestions are found (PR #1797) - [x] (Fixed) _Back-end_ Timeout in Thumbnail cleaner fixed (PR #1798) - [x] (Fixed) _Back-end_ Add logging for thumbnail background scanning (PR #1798) +- [x] (Fixed) _Front-end_ Invalid date parsing (PR #1802, Issue #1508) ## version 0.6.2 - 2024-10-11 {#v0.6.2}