mirror of
https://github.com/wkulhanek/bonob.git
synced 2025-12-21 17:33:29 +01:00
Improve date handling (#94)
This commit is contained in:
44
src/clock.ts
44
src/clock.ts
@@ -1,13 +1,38 @@
|
|||||||
import dayjs, { Dayjs } from "dayjs";
|
import dayjs, { Dayjs } from "dayjs";
|
||||||
|
|
||||||
export const isChristmas = (clock: Clock = SystemClock) => clock.now().month() == 11 && clock.now().date() == 25;
|
function fixedDateMonthEvent(dateMonth: string) {
|
||||||
export const isMay4 = (clock: Clock = SystemClock) => clock.now().month() == 4 && clock.now().date() == 4;
|
const date = Number.parseInt(dateMonth.split("/")[0]!);
|
||||||
export const isHalloween = (clock: Clock = SystemClock) => clock.now().month() == 9 && clock.now().date() == 31
|
const month = Number.parseInt(dateMonth.split("/")[1]!);
|
||||||
export const isHoli = (clock: Clock = SystemClock) => ["2022/03/18", "2023/03/07", "2024/03/25", "2025/03/14"].map(dayjs).find(it => it.isSame(clock.now())) != undefined
|
return (clock: Clock = SystemClock) => {
|
||||||
export const isCNY = (clock: Clock = SystemClock) => ["2022/02/01", "2023/01/22", "2024/02/10", "2025/02/29"].map(dayjs).find(it => it.isSame(clock.now())) != undefined
|
return clock.now().date() == date && clock.now().month() == month - 1;
|
||||||
export const isCNY_2022 = (clock: Clock = SystemClock) => clock.now().isSame(dayjs("2022/02/01"))
|
};
|
||||||
export const isCNY_2023 = (clock: Clock = SystemClock) => clock.now().isSame(dayjs("2023/01/22"))
|
}
|
||||||
export const isCNY_2024 = (clock: Clock = SystemClock) => clock.now().isSame(dayjs("2024/02/10"))
|
|
||||||
|
function fixedDateEvent(date: string) {
|
||||||
|
const dayjsDate = dayjs(date);
|
||||||
|
return (clock: Clock = SystemClock) => {
|
||||||
|
return clock.now().isSame(dayjsDate, "day");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function anyOf(rules: ((clock: Clock) => boolean)[]) {
|
||||||
|
return (clock: Clock = SystemClock) => {
|
||||||
|
return rules.find((rule) => rule(clock)) != undefined;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isChristmas = fixedDateMonthEvent("25/12");
|
||||||
|
export const isMay4 = fixedDateMonthEvent("04/05");
|
||||||
|
export const isHalloween = fixedDateMonthEvent("31/10");
|
||||||
|
export const isHoli = anyOf(
|
||||||
|
["2022/03/18", "2023/03/07", "2024/03/25", "2025/03/14"].map(fixedDateEvent)
|
||||||
|
)
|
||||||
|
|
||||||
|
export const isCNY_2022 = fixedDateEvent("2022/02/01");
|
||||||
|
export const isCNY_2023 = fixedDateEvent("2023/01/22");
|
||||||
|
export const isCNY_2024 = fixedDateEvent("2024/02/10");
|
||||||
|
export const isCNY_2025 = fixedDateEvent("2025/02/29");
|
||||||
|
export const isCNY = anyOf([isCNY_2022, isCNY_2023, isCNY_2024, isCNY_2025]);
|
||||||
|
|
||||||
export interface Clock {
|
export interface Clock {
|
||||||
now(): Dayjs;
|
now(): Dayjs;
|
||||||
@@ -22,7 +47,8 @@ export class FixedClock implements Clock {
|
|||||||
this.time = time;
|
this.time = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
add = (t: number, unit: dayjs.UnitTypeShort) => this.time = this.time.add(t, unit)
|
add = (t: number, unit: dayjs.UnitTypeShort) =>
|
||||||
|
(this.time = this.time.add(t, unit));
|
||||||
|
|
||||||
now = () => this.time;
|
now = () => this.time;
|
||||||
}
|
}
|
||||||
@@ -1,58 +1,85 @@
|
|||||||
import dayjs from "dayjs";
|
import { randomInt } from "crypto";
|
||||||
import { isChristmas, isCNY, isHalloween, isHoli } from "../src/clock";
|
import dayjs, { Dayjs } from "dayjs";
|
||||||
|
import timezone from "dayjs/plugin/timezone";
|
||||||
|
dayjs.extend(timezone);
|
||||||
|
|
||||||
describe("isChristmas", () => {
|
import { Clock, isChristmas, isCNY, isCNY_2022, isCNY_2023, isCNY_2024, isCNY_2025, isHalloween, isHoli, isMay4 } from "../src/clock";
|
||||||
["2000/12/25", "2022/12/25", "2030/12/25"].forEach((date) => {
|
|
||||||
it(`should return true for ${date} regardless of year`, () => {
|
|
||||||
expect(isChristmas({ now: () => dayjs(date) })).toEqual(true);
|
|
||||||
|
const randomDate = () => dayjs().subtract(randomInt(1, 1000), 'days');
|
||||||
|
const randomDates = (count: number, exclude: string[]) => {
|
||||||
|
const result: Dayjs[] = [];
|
||||||
|
while(result.length < count) {
|
||||||
|
const next = randomDate();
|
||||||
|
if(!exclude.find(it => dayjs(it).isSame(next, 'date'))) {
|
||||||
|
result.push(next)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
function describeFixedDateMonthEvent(
|
||||||
|
name: string,
|
||||||
|
dateMonth: string,
|
||||||
|
f: (clock: Clock) => boolean
|
||||||
|
) {
|
||||||
|
const randomYear = randomInt(2020, 3000);
|
||||||
|
const date = dateMonth.split("/")[0];
|
||||||
|
const month = dateMonth.split("/")[1];
|
||||||
|
|
||||||
|
describe(name, () => {
|
||||||
|
it(`should return true for ${randomYear}-${month}-${date}T00:00:00 ragardless of year`, () => {
|
||||||
|
expect(f({ now: () => dayjs(`${randomYear}-${month}-${date}T00:00:00Z`) })).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should return true for ${randomYear}-${month}-${date}T12:00:00 regardless of year`, () => {
|
||||||
|
expect(f({ now: () => dayjs(`${randomYear}-${month}-${date}T12:00:00Z`) })).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should return true for ${randomYear}-${month}-${date}T23:59:00 regardless of year`, () => {
|
||||||
|
expect(f({ now: () => dayjs(`${randomYear}-${month}-${date}T23:59:00`) })).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
["2000/12/24", "2000/12/26", "2021/01/01"].forEach((date) => {
|
||||||
|
it(`should return false for ${date}`, () => {
|
||||||
|
expect(f({ now: () => dayjs(date) })).toEqual(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
["2000/12/24", "2000/12/26", "2021/01/01"].forEach((date) => {
|
function describeFixedDateEvent(
|
||||||
it(`should return false for ${date} regardless of year`, () => {
|
name: string,
|
||||||
expect(isChristmas({ now: () => dayjs(date) })).toEqual(false);
|
dates: string[],
|
||||||
|
f: (clock: Clock) => boolean
|
||||||
|
) {
|
||||||
|
describe(name, () => {
|
||||||
|
dates.forEach((date) => {
|
||||||
|
it(`should return true for ${date}T00:00:00`, () => {
|
||||||
|
expect(f({ now: () => dayjs(`${date}T00:00:00`) })).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should return true for ${date}T23:59:59`, () => {
|
||||||
|
expect(f({ now: () => dayjs(`${date}T23:59:59`) })).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
randomDates(10, dates).forEach((date) => {
|
||||||
|
it(`should return false for ${date}`, () => {
|
||||||
|
expect(f({ now: () => dayjs(date) })).toEqual(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
describe("isHalloween", () => {
|
describeFixedDateMonthEvent("christmas", "25/12", isChristmas);
|
||||||
["2000/10/31", "2022/10/31", "2030/10/31"].forEach((date) => {
|
describeFixedDateMonthEvent("halloween", "31/10", isHalloween);
|
||||||
it(`should return true for ${date} regardless of year`, () => {
|
describeFixedDateMonthEvent("may4", "04/05", isMay4);
|
||||||
expect(isHalloween({ now: () => dayjs(date) })).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
["2000/09/31", "2000/10/30", "2021/01/01"].forEach((date) => {
|
describeFixedDateEvent("holi", ["2022-03-18", "2023-03-07", "2024-03-25", "2025-03-14"], isHoli);
|
||||||
it(`should return false for ${date} regardless of year`, () => {
|
describeFixedDateEvent("cny", ["2022-02-01", "2023-01-22", "2024-02-10", "2025-02-29"], isCNY);
|
||||||
expect(isHalloween({ now: () => dayjs(date) })).toEqual(false);
|
describeFixedDateEvent("cny 2022", ["2022-02-01"], isCNY_2022);
|
||||||
});
|
describeFixedDateEvent("cny 2023", ["2023/01/22"], isCNY_2023);
|
||||||
});
|
describeFixedDateEvent("cny 2024", ["2024/02/10"], isCNY_2024);
|
||||||
});
|
describeFixedDateEvent("cny 2025", ["2025/02/29"], isCNY_2025);
|
||||||
|
|
||||||
describe("isHoli", () => {
|
|
||||||
["2022/03/18", "2023/03/07", "2024/03/25", "2025/03/14"].forEach((date) => {
|
|
||||||
it(`should return true for ${date} regardless of year`, () => {
|
|
||||||
expect(isHoli({ now: () => dayjs(date) })).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
["2000/09/31", "2000/10/30", "2021/01/01"].forEach((date) => {
|
|
||||||
it(`should return false for ${date} regardless of year`, () => {
|
|
||||||
expect(isHoli({ now: () => dayjs(date) })).toEqual(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("isCNY", () => {
|
|
||||||
["2022/02/01", "2023/01/22", "2024/02/10", "2025/02/29"].forEach((date) => {
|
|
||||||
it(`should return true for ${date} regardless of year`, () => {
|
|
||||||
expect(isCNY({ now: () => dayjs(date) })).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
["2000/09/31", "2000/10/30", "2021/01/01"].forEach((date) => {
|
|
||||||
it(`should return false for ${date} regardless of year`, () => {
|
|
||||||
expect(isCNY({ now: () => dayjs(date) })).toEqual(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
]
|
]
|
||||||
/* List of folders to include type definitions from. */,
|
/* List of folders to include type definitions from. */,
|
||||||
// "types": ["src/customTypes/scale-that-svg.d.ts"], /* Type declaration files to be included in compilation. */
|
// "types": ["src/customTypes/scale-that-svg.d.ts"], /* Type declaration files to be included in compilation. */
|
||||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
||||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
|||||||
Reference in New Issue
Block a user