diff --git a/source/date/date.test.ts b/source/date/date.test.ts new file mode 100644 index 0000000..cb051e1 --- /dev/null +++ b/source/date/date.test.ts @@ -0,0 +1,48 @@ +// Third-party imports. +import {setup} from "@holllo/test"; +// First-party imports. +import {DateWrapper} from "./date.js"; + +await setup("DateWrapper", async (group) => { + group.test("Add Days", async (test) => { + const samples = [ + [1, 23], + [10, 1], + [-1, 21], + [-10, 12], + ]; + for (const [daysToAdd, expectedDay] of samples) { + const wrapper = new DateWrapper("2023-05-22T12:00:00Z"); + wrapper.addDays(daysToAdd); + test.equals(wrapper.date.getDate(), expectedDay, wrapper.iso()); + } + }); + + group.test("Constructor", async (test) => { + const stringConstructor = new DateWrapper("2023-05-22T12:00:00Z"); + test.true(stringConstructor.date instanceof Date, "String constructor"); + const dateConstructor = new DateWrapper(new Date("2023-05-22T12:00:00Z")); + test.true(dateConstructor.date instanceof Date, "Date constructor"); + }); + + group.test("Day of the Week", async (test) => { + const wrapper = new DateWrapper("2023-05-22T12:00:00Z"); + for (let expected = 1; expected <= 7; expected++) { + test.equals(wrapper.dayOfTheWeek(), expected, wrapper.iso()); + wrapper.addDays(1); + } + }); + + group.test("Padded Functions", async (test) => { + const samples: Array<[DateWrapper, string, string]> = [ + [new DateWrapper("2023-05-02T12:00:00Z"), "05", "02"], + [new DateWrapper("2023-05-22T12:00:00Z"), "05", "22"], + [new DateWrapper("2023-11-02T12:00:00Z"), "11", "02"], + [new DateWrapper("2023-11-22T12:00:00Z"), "11", "22"], + ]; + for (const [wrapper, month, day] of samples) { + test.equals(wrapper.paddedMonth(), month, wrapper.iso()); + test.equals(wrapper.paddedDay(), day, wrapper.iso()); + } + }); +}); diff --git a/source/date/date.ts b/source/date/date.ts new file mode 100644 index 0000000..963fe73 --- /dev/null +++ b/source/date/date.ts @@ -0,0 +1,68 @@ +export class DateWrapper { + public date: Date; + + constructor(date: Date | string) { + this.date = date instanceof Date ? date : new Date(date); + } + + /** + * Adds the specified number of days to the inner date. + * + * @param days The amount of days to add, can also be negative to subtract. + */ + public addDays(days: number): void { + this.date.setDate(this.date.getDate() + days); + } + + /** Clone the current date and return a completely new DateWrapper. */ + public clone(): DateWrapper { + return new DateWrapper(new Date(this.iso())); + } + + /** Get the day of the week with Monday starting as 1. */ + public dayOfTheWeek(): number { + const day = this.date.getDay(); + return day === 0 ? 7 : day; + } + + /** Get the date as an ISO-formatted string. */ + public iso(): string { + return this.date.toISOString(); + } + + /** Get the day padded with a leading zero when necessary. */ + public paddedDay(): string { + const day = this.date.getDate(); + return day.toString().padStart(2, "0"); + } + + /** Get the month padded with a leading zero when necessary. */ + public paddedMonth(): string { + const month = this.date.getMonth() + 1; + return month.toString().padStart(2, "0"); + } + + /** + * Get the week of the year the date is in. + * + * Code adapted from https://weeknumber.net/how-to/javascript. + * */ + public week(): number { + const date = new Date(this.date.getTime()); + date.setHours(0, 0, 0, 0); + + // Thursday in the current week decides the year. + date.setDate(date.getDate() + 3 - ((date.getDay() + 6) % 7)); + + // January 4 is always in week 1. + const firstWeek = new Date(date.getFullYear(), 0, 4); + + // Get the difference between the first week and the current date in days. + const dayDifference = (date.getTime() - firstWeek.getTime()) / 86_400_000; + + // Adjust the day difference to Thursday and then get the number of weeks. + return ( + 1 + Math.round((dayDifference - 3 + ((firstWeek.getDay() + 6) % 7)) / 7) + ); + } +}