Tests for date + time parsing & formatting, and fixing the bugs they revealed

This commit is contained in:
nathan 2021-11-03 13:49:39 -06:00
parent 672ed0aa0e
commit ca429d0fae
3 changed files with 198 additions and 19 deletions

View File

@ -16,7 +16,8 @@ import {Et2InputWidget} from "../Et2InputWidget/Et2InputWidget";
/** /**
* To parse a date into the right format * Parse a date string into a Date object
* Time will be 00:00:00 UTC
* *
* @param {string} dateString * @param {string} dateString
* @returns {Date | undefined} * @returns {Date | undefined}
@ -65,15 +66,15 @@ export function parseDate(dateString)
} }
const [year, month, day] = parsedString.split('/').map(Number); const [year, month, day] = parsedString.split('/').map(Number);
const parsedDate = new Date(year, month - 1, day); const parsedDate = new Date(`${year}-${month < 10 ? "0" + month : month}-${day < 10 ? "0" + day : day}T00:00:00Z`);
// Check if parsedDate is not `Invalid Date` or that the date has changed (e.g. the not existing 31.02.2020) // Check if parsedDate is not `Invalid Date` or that the date has changed (e.g. the not existing 31.02.2020)
if ( if(
year > 0 && year > 0 &&
month > 0 && month > 0 &&
day > 0 && day > 0 &&
parsedDate.getDate() === day && parsedDate.getUTCDate() === day &&
parsedDate.getMonth() === month - 1 parsedDate.getUTCMonth() === month - 1
) )
{ {
return parsedDate; return parsedDate;
@ -82,8 +83,8 @@ export function parseDate(dateString)
} }
/** /**
* To parse a time into the right format * To parse a time into a Date object
* Date will be 1970-01-01 * Date will be 1970-01-01, time is in UTC to avoid browser issues
* *
* @param {string} timeString * @param {string} timeString
* @returns {Date | undefined} * @returns {Date | undefined}
@ -108,8 +109,16 @@ export function parseTime(timeString)
} }
let am_pm = timeString.endsWith("pm") || timeString.endsWith("PM") ? 12 : 0; let am_pm = timeString.endsWith("pm") || timeString.endsWith("PM") ? 12 : 0;
timeString = timeString.replaceAll(/[^0-9:]/gi, '');
const [hour, minute] = timeString.split(':').map(Number); let strippedString = timeString.replaceAll(/[^0-9:]/gi, '');
if(timeString.startsWith("12") && strippedString != timeString)
{
// 12:xx am -> 0:xx, 12:xx pm -> 12:xx
am_pm -= 12;
}
const [hour, minute] = strippedString.split(':').map(Number);
const parsedDate = new Date("1970-01-01T00:00:00Z"); const parsedDate = new Date("1970-01-01T00:00:00Z");
parsedDate.setUTCHours(hour + am_pm); parsedDate.setUTCHours(hour + am_pm);
@ -128,6 +137,7 @@ export function parseTime(timeString)
/** /**
* To parse a date+time into an object * To parse a date+time into an object
* Time is in UTC to avoid browser issues
* *
* @param {string} dateTimeString * @param {string} dateTimeString
* @returns {Date | undefined} * @returns {Date | undefined}
@ -180,7 +190,7 @@ export function parseDateTime(dateTimeString)
* set 'dateFormat': "Y-m-d" to specify a particular format * set 'dateFormat': "Y-m-d" to specify a particular format
* @returns {string} * @returns {string}
*/ */
export function formatDate(date : Date, options) : string export function formatDate(date : Date, options = {dateFormat: ""}) : string
{ {
if(!date || !(date instanceof Date)) if(!date || !(date instanceof Date))
{ {
@ -213,7 +223,7 @@ export function formatDate(date : Date, options) : string
* set 'timeFormat': "12" to specify a particular format * set 'timeFormat': "12" to specify a particular format
* @returns {string} * @returns {string}
*/ */
export function formatTime(date : Date, options) : string export function formatTime(date : Date, options = {timeFormat: ""}) : string
{ {
if(!date || !(date instanceof Date)) if(!date || !(date instanceof Date))
{ {
@ -221,7 +231,7 @@ export function formatTime(date : Date, options) : string
} }
let _value = ''; let _value = '';
let timeformat = options.timeFormat || <string>window.egw.preference("timeformat") || '24'; let timeformat = options.timeFormat || <string>window.egw.preference("timeformat") || "24";
let hours = (timeformat == "12" && date.getUTCHours() > 12) ? (date.getUTCHours() - 12) : date.getUTCHours(); let hours = (timeformat == "12" && date.getUTCHours() > 12) ? (date.getUTCHours() - 12) : date.getUTCHours();
if(timeformat == "12" && hours == 0) if(timeformat == "12" && hours == 0)
{ {
@ -244,7 +254,7 @@ export function formatTime(date : Date, options) : string
* set 'dateFormat': "Y-m-d", 'timeFormat': "12" to specify a particular format * set 'dateFormat': "Y-m-d", 'timeFormat': "12" to specify a particular format
* @returns {string} * @returns {string}
*/ */
export function formatDateTime(date : Date, options) : string export function formatDateTime(date : Date, options = {dateFormat: "", timeFormat: ""}) : string
{ {
if(!date || !(date instanceof Date)) if(!date || !(date instanceof Date))
{ {

View File

@ -0,0 +1,97 @@
/**
* Test file for Etemplate date formatting
*/
import {assert} from '@open-wc/testing';
import {formatDate, formatTime} from "../Et2Date";
describe("Date formatting", () =>
{
// Function under test
let formatter = formatDate;
// Setup run before each test
beforeEach(async() =>
{
// Stub global egw for preference
// @ts-ignore
window.egw = {
preference: () => 'Y-m-d'
};
});
it("Handles Y-m-d", () =>
{
let test_string = '2021-09-22';
let test_date = new Date(2021, 8, 22, 0, 0, 0);
let formatted = formatter(test_date);
assert.equal(formatted, test_string);
});
it("Handles Y.d.m", () =>
{
let test_string = '2021.22.09';
let test_date = new Date(2021, 8, 22, 0, 0, 0);
//@ts-ignore
window.egw = {
preference: () => 'Y.d.m'
};
let formatted = formatter(test_date);
assert.equal(formatted, test_string);
});
});
describe("Time formatting", () =>
{
// Function under test
let formatter = formatTime;
// Setup run before each test
beforeEach(async() =>
{
// Stub global egw for preference
// @ts-ignore
window.egw = {
preference: () => 'Y-m-d'
};
});
it("Handles 12h", () =>
{
const test_data = {
"9:15 am": new Date('2021-09-22T09:15:00Z'),
"12:00 am": new Date('2021-09-22T00:00:00Z'),
"12:00 pm": new Date('2021-09-22T12:00:00Z'),
"5:00 pm": new Date('2021-09-22T17:00:00Z'),
};
for(let test_string of Object.keys(test_data))
{
let test_date = test_data[test_string];
let formatted = formatter(test_date, {timeFormat: "12"});
assert.equal(formatted, test_string);
}
});
it("Handles 24h", () =>
{
const test_data = {
"09:15": new Date('2021-09-22T09:15:00Z'),
"00:00": new Date('2021-09-22T00:00:00Z'),
"12:00": new Date('2021-09-22T12:00:00Z'),
"17:00": new Date('2021-09-22T17:00:00Z'),
};
for(let test_string of Object.keys(test_data))
{
let test_date = test_data[test_string];
let formatted = formatter(test_date, {timeFormat: "24"});
assert.equal(formatted, test_string);
}
});
});

View File

@ -1,10 +1,8 @@
/** /**
* Test file for Etemplate date parsing * Test file for Etemplate date parsing
*/ */
import {assert, fixture} from '@open-wc/testing'; import {assert} from '@open-wc/testing';
import {Et2Date, parseDate} from "../Et2Date"; import {parseDate, parseTime} from "../Et2Date";
import {html} from "lit-element";
import * as sinon from 'sinon';
describe("Date parsing", () => describe("Date parsing", () =>
{ {
@ -36,7 +34,7 @@ describe("Date parsing", () =>
it("Handles Y-m-d", () => it("Handles Y-m-d", () =>
{ {
let test_string = '2021-09-22'; let test_string = '2021-09-22';
let test_date = new Date(2021, 8, 22, 0, 0, 0); let test_date = new Date("2021-09-22T00:00:00Z");
let parsed = parser(test_string); let parsed = parser(test_string);
@ -46,7 +44,7 @@ describe("Date parsing", () =>
it("Handles Y.d.m", () => it("Handles Y.d.m", () =>
{ {
let test_string = '2021.22.09'; let test_string = '2021.22.09';
let test_date = new Date(2021, 8, 22, 0, 0, 0); let test_date = new Date("2021-09-22T00:00:00Z");
//@ts-ignore //@ts-ignore
window.egw = { window.egw = {
@ -56,4 +54,78 @@ describe("Date parsing", () =>
assert.equal(parsed.toJSON(), test_date.toJSON()); assert.equal(parsed.toJSON(), test_date.toJSON());
}); });
});
describe("Time parsing", () =>
{
// Setup run before each test
beforeEach(async() =>
{
// Stub global egw for preference
// @ts-ignore
window.egw = {
preference: () => 'Y-m-d'
};
});
it("Handles 12h", () =>
{
const test_data = {
// As expected
"9:15 am": new Date('1970-01-01T09:15:00Z'),
"12:00 am": new Date('1970-01-01T00:00:00Z'),
"12:00 pm": new Date('1970-01-01T12:00:00Z'),
"5:00 pm": new Date('1970-01-01T17:00:00Z'),
"11:59 pm": new Date('1970-01-01T23:59:00Z'),
// Not valid, should be undefined
"invalid": undefined,
"23:45 pm": undefined
};
for(let test_string of Object.keys(test_data))
{
let test_date = test_data[test_string];
let parsed = parseTime(test_string);
if(typeof test_date == "undefined")
{
assert.isUndefined(parsed);
}
else
{
assert.equal(parsed.toJSON(), test_date.toJSON());
}
}
});
it("Handles 24h", () =>
{
const test_data = {
"09:15": new Date('1970-01-01T09:15:00Z'),
"00:00": new Date('1970-01-01T00:00:00Z'),
"12:00": new Date('1970-01-01T12:00:00Z'),
"17:00": new Date('1970-01-01T17:00:00Z'),
"23:59": new Date('1970-01-01T23:59:00Z'),
// Not valid, should be undefined
"invalid": undefined,
"23:45 pm": undefined
};
for(let test_string of Object.keys(test_data))
{
let test_date = test_data[test_string];
let parsed = parseTime(test_string);
if(typeof test_date == "undefined")
{
assert.isUndefined(parsed);
}
else
{
assert.equal(parsed.toJSON(), test_date.toJSON());
}
}
});
}); });