diff --git a/common/time/consts.ts b/common/time/consts.ts index eeffaa5..6251e7c 100644 --- a/common/time/consts.ts +++ b/common/time/consts.ts @@ -1 +1,2 @@ export const dayInMs = 1000 * 60 * 60 * 24; +export const dayInMins = 60 * 24; diff --git a/common/time/cron.ts b/common/time/cron.ts index 7e26f6e..e947a64 100644 --- a/common/time/cron.ts +++ b/common/time/cron.ts @@ -1,16 +1,43 @@ import { type CronExpression, parseExpression } from "cron-parser"; +import { dayInMins } from "./consts"; import { formatShortOffset } from "./offset"; +import { getTzMinuteDiff } from "./timezone"; import type { Translator } from "@/common/i18n"; +import { parseNum } from "@/common/parsing"; export class Cron { - private readonly expression: CronExpression; + public static fromUtcString(utcCron: string): Cron | null { + const utcParts = utcCron.split(" "); + const utcMin = parseNum(utcParts[0] ?? ""); + const utcHour = parseNum(utcParts[1] ?? ""); - public constructor(cron: string) { - this.expression = parseExpression(cron); + if (utcMin === null || utcHour === null) { + return null; + } + + const utcTotalMins = utcHour * 60 + utcMin; + const localTotalMins = mod(utcTotalMins - getTzMinuteDiff(), dayInMins); + const localHour = Math.floor(localTotalMins / 60); + const localMin = localTotalMins % 60; + + return Cron.fromLocalString(`${localMin} ${localHour} * * *`); + } + + public static fromLocalString(localCron: string): Cron | null { + try { + return new Cron(parseExpression(localCron), localCron); + } catch { + return null; + } } + private constructor( + private readonly expression: CronExpression, + private readonly source: string, + ) {} + public nextDate(): Date { const next = this.expression.next(); this.expression.reset(); @@ -40,3 +67,5 @@ export class Cron { return formatShortOffset(tillPrev < tillNext ? prevDate : nextDate, t); } } + +const mod = (a: number, b: number): number => ((a % b) + b) % b; diff --git a/common/time/index.ts b/common/time/index.ts index d7a57e2..989fa51 100644 --- a/common/time/index.ts +++ b/common/time/index.ts @@ -1,3 +1,4 @@ export { Cron } from "./cron"; export { formatShortOffset, formatLongOffset } from "./offset"; export { toMinutesAndSeconds } from "./timer"; +export { getTzMinuteDiff } from "./timezone"; diff --git a/common/time/timezone.ts b/common/time/timezone.ts new file mode 100644 index 0000000..a9bfb75 --- /dev/null +++ b/common/time/timezone.ts @@ -0,0 +1 @@ +export const getTzMinuteDiff = () => new Date().getTimezoneOffset(); diff --git a/logic/medication/reminder.ts b/logic/medication/reminder.ts index 8611785..67f3249 100644 --- a/logic/medication/reminder.ts +++ b/logic/medication/reminder.ts @@ -36,7 +36,7 @@ export class Reminder { data.amountPerIntake, data.amountOwned ?? null, data.amountUnit ?? null, - data.cron ? new Cron(data.cron) : null, + data.cron ? Cron.fromUtcString(data.cron) : null, data.description ?? null, ); }