(cron: Cron, now: DateTime.DateTime.Input | undefined, direction: "next" | "prev")
| 817 | } |
| 818 | |
| 819 | const stepCron = (cron: Cron, now: DateTime.DateTime.Input | undefined, direction: "next" | "prev"): Date => { |
| 820 | const tz = Option.getOrUndefined(cron.tz) |
| 821 | const zoned = dateTime.makeZonedUnsafe(now ?? new Date(), { |
| 822 | timeZone: tz |
| 823 | }) |
| 824 | |
| 825 | const reverse = direction === "prev" |
| 826 | const tick = reverse ? -1 : 1 |
| 827 | const table = cron[direction] |
| 828 | const boundary = reverse ? cron.last : cron.first |
| 829 | |
| 830 | const needsStep = reverse ? |
| 831 | (next: number, current: number) => next < current : |
| 832 | (next: number, current: number) => next > current |
| 833 | |
| 834 | const utc = tz !== undefined && dateTime.isTimeZoneNamed(tz) && tz.id === "UTC" |
| 835 | const adjustDst = utc ? constVoid : (current: Date) => { |
| 836 | const adjusted = dateTime.makeZonedUnsafe(current, { |
| 837 | timeZone: zoned.zone, |
| 838 | adjustForTimeZone: true, |
| 839 | disambiguation: reverse ? "later" : undefined |
| 840 | }).pipe(dateTime.toDate) |
| 841 | |
| 842 | const drift = current.getTime() - adjusted.getTime() |
| 843 | if (reverse ? drift !== 0 : drift > 0) { |
| 844 | current.setTime(reverse ? adjusted.getTime() : current.getTime() + drift) |
| 845 | } |
| 846 | } |
| 847 | |
| 848 | const result = dateTime.mutate(zoned, (current) => { |
| 849 | current.setUTCSeconds(current.getUTCSeconds() + tick, 0) |
| 850 | |
| 851 | for (let i = 0; i < 10_000; i++) { |
| 852 | if (cron.seconds.size !== 0) { |
| 853 | const currentSecond = current.getUTCSeconds() |
| 854 | const nextSecond = table.second[currentSecond] |
| 855 | if (nextSecond === undefined) { |
| 856 | current.setUTCMinutes(current.getUTCMinutes() + tick, boundary.second) |
| 857 | adjustDst(current) |
| 858 | continue |
| 859 | } |
| 860 | if (needsStep(nextSecond, currentSecond)) { |
| 861 | current.setUTCSeconds(nextSecond) |
| 862 | adjustDst(current) |
| 863 | continue |
| 864 | } |
| 865 | } |
| 866 | |
| 867 | if (cron.minutes.size !== 0) { |
| 868 | const currentMinute = current.getUTCMinutes() |
| 869 | const nextMinute = table.minute[currentMinute] |
| 870 | if (nextMinute === undefined) { |
| 871 | current.setUTCHours(current.getUTCHours() + tick, boundary.minute, boundary.second) |
| 872 | adjustDst(current) |
| 873 | continue |
| 874 | } |
| 875 | if (needsStep(nextMinute, currentMinute)) { |
| 876 | current.setUTCMinutes(nextMinute, boundary.second) |
no test coverage detected