diff --git a/src/services/time-until.test.ts b/src/services/time-until.test.ts index af402a8..2e58a03 100644 --- a/src/services/time-until.test.ts +++ b/src/services/time-until.test.ts @@ -1,7 +1,68 @@ -import { describe, it, expect } from "vitest" +import { describe, it, expect, vi, afterEach, beforeEach } from "vitest" +import { hasPassed, timeUntil } from "./time-until" -describe("time until service", () => { - it("test", () => { - expect(true).toBe(true) +const noTime = () => ({ + days: 0, + hours: 0, + months: 0, + seconds: 0, + years: 0, +}) + +describe("time until", () => { + beforeEach(() => { + vi.useFakeTimers() + }) + + afterEach(() => { + vi.useRealTimers() + }) + + it("tells the time until a simple target date", () => { + const fakeNow = new Date("2023-03-13T09:00:00.000Z") + vi.setSystemTime(fakeNow) + + expect(timeUntil("2024-03-13T09:00:00.000Z")).toStrictEqual({ + years: 1, + months: 0, + days: 0, + hours: 0, + seconds: 0, + }) + }) + + it("tells the time until a more complex target date", () => { + const fakeNow = new Date("2023-03-13T09:00:00.000Z") + vi.setSystemTime(fakeNow) + + expect(timeUntil("2024-02-12T19:34:22.200Z")).toStrictEqual({ + days: 30, + hours: 10, + months: 10, + seconds: 2062, + years: 0, + }) + }) + + it("tells 0 if the target date is passed", () => { + const fakeNow = new Date("2023-03-13T09:00:00.000Z") + vi.setSystemTime(fakeNow) + + expect(timeUntil("2022-03-13T09:00:00.000Z")).toStrictEqual(noTime()) + }) +}) + +describe("has passed", () => { + it("tells if the targed has passed", () => { + expect(hasPassed(noTime())).toBeTruthy() + expect( + hasPassed({ + years: 0, + months: 0, + days: 0, + hours: 0, + seconds: 1, + }) + ).toBeFalsy() }) }) diff --git a/src/services/time-until.ts b/src/services/time-until.ts index e69de29..4adc08c 100644 --- a/src/services/time-until.ts +++ b/src/services/time-until.ts @@ -0,0 +1,39 @@ +import { DateTime } from "luxon" + +interface TimeUntilReturn { + years: number + months: number + days: number + hours: number + seconds: number +} + +export const timeUntil = (target: string): TimeUntilReturn => { + const now = DateTime.now() + const dateTimeTarget = DateTime.fromISO(target) + + if (dateTimeTarget <= now) { + return { + years: 0, + months: 0, + days: 0, + hours: 0, + seconds: 0, + } + } + + const interval = dateTimeTarget + .diff(now, ["years", "months", "days", "hours", "seconds"]) + .toObject() + + return { + years: interval.years ? Math.round(interval.years) : 0, + months: interval.months ? Math.round(interval.months) : 0, + days: interval.days ? Math.round(interval.days) : 0, + hours: interval.hours ? Math.round(interval.hours) : 0, + seconds: interval.seconds ? Math.round(interval.seconds) : 0, + } +} + +export const hasPassed = (timeUntil: TimeUntilReturn): boolean => + Object.entries(timeUntil).every(([_, value]) => value === 0)