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
* @returns {Date | undefined}
@ -65,15 +66,15 @@ export function parseDate(dateString)
}
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)
if (
if(
year > 0 &&
month > 0 &&
day > 0 &&
parsedDate.getDate() === day &&
parsedDate.getMonth() === month - 1
parsedDate.getUTCDate() === day &&
parsedDate.getUTCMonth() === month - 1
)
{
return parsedDate;
@ -82,8 +83,8 @@ export function parseDate(dateString)
}
/**
* To parse a time into the right format
* Date will be 1970-01-01
* To parse a time into a Date object
* Date will be 1970-01-01, time is in UTC to avoid browser issues
*
* @param {string} timeString
* @returns {Date | undefined}
@ -108,8 +109,16 @@ export function parseTime(timeString)
}
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");
parsedDate.setUTCHours(hour + am_pm);
@ -128,6 +137,7 @@ export function parseTime(timeString)
/**
* To parse a date+time into an object
* Time is in UTC to avoid browser issues
*
* @param {string} dateTimeString
* @returns {Date | undefined}
@ -180,7 +190,7 @@ export function parseDateTime(dateTimeString)
* set 'dateFormat': "Y-m-d" to specify a particular format
* @returns {string}
*/
export function formatDate(date : Date, options) : string
export function formatDate(date : Date, options = {dateFormat: ""}) : string
{
if(!date || !(date instanceof Date))
{
@ -213,7 +223,7 @@ export function formatDate(date : Date, options) : string
* set 'timeFormat': "12" to specify a particular format
* @returns {string}
*/
export function formatTime(date : Date, options) : string
export function formatTime(date : Date, options = {timeFormat: ""}) : string
{
if(!date || !(date instanceof Date))
{
@ -221,7 +231,7 @@ export function formatTime(date : Date, options) : string
}
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();
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
* @returns {string}
*/
export function formatDateTime(date : Date, options) : string
export function formatDateTime(date : Date, options = {dateFormat: "", timeFormat: ""}) : string
{
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
*/
import {assert, fixture} from '@open-wc/testing';
import {Et2Date, parseDate} from "../Et2Date";
import {html} from "lit-element";
import * as sinon from 'sinon';
import {assert} from '@open-wc/testing';
import {parseDate, parseTime} from "../Et2Date";
describe("Date parsing", () =>
{
@ -36,7 +34,7 @@ describe("Date parsing", () =>
it("Handles Y-m-d", () =>
{
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);
@ -46,7 +44,7 @@ describe("Date parsing", () =>
it("Handles Y.d.m", () =>
{
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
window.egw = {
@ -57,3 +55,77 @@ describe("Date parsing", () =>
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());
}
}
});
});