(cron: Cron, startFrom: DateTime.DateTime.Input | undefined, direction: "next" | "prev")
| 474 | |
| 475 | /** @internal */ |
| 476 | const stepCron = (cron: Cron, startFrom: DateTime.DateTime.Input | undefined, direction: "next" | "prev"): Date => { |
| 477 | const tz = Option.getOrUndefined(cron.tz) |
| 478 | const zoned = dateTime.unsafeMakeZoned(startFrom ?? new Date(), { |
| 479 | timeZone: tz |
| 480 | }) |
| 481 | |
| 482 | const prev = direction === "prev" |
| 483 | const tick = prev ? -1 : 1 |
| 484 | const table = cron[direction] |
| 485 | const boundary = prev ? cron.last : cron.first |
| 486 | |
| 487 | const needsStep = prev |
| 488 | ? (next: number, current: number) => next < current |
| 489 | : (next: number, current: number) => next > current |
| 490 | |
| 491 | const utc = tz !== undefined && dateTime.isTimeZoneNamed(tz) && tz.id === "UTC" |
| 492 | const adjustDst = utc ? constVoid : (current: Date) => { |
| 493 | const adjusted = dateTime.unsafeMakeZoned(current, { |
| 494 | timeZone: zoned.zone, |
| 495 | adjustForTimeZone: true, |
| 496 | disambiguation: prev ? "later" : undefined |
| 497 | }).pipe(dateTime.toDate) |
| 498 | |
| 499 | const drift = current.getTime() - adjusted.getTime() |
| 500 | if (prev ? drift !== 0 : drift > 0) { |
| 501 | current.setTime(adjusted.getTime()) |
| 502 | } |
| 503 | } |
| 504 | |
| 505 | const result = dateTime.mutate(zoned, (current) => { |
| 506 | current.setUTCSeconds(current.getUTCSeconds() + tick, 0) |
| 507 | |
| 508 | for (let i = 0; i < 10_000; i++) { |
| 509 | if (cron.seconds.size !== 0) { |
| 510 | const currentSecond = current.getUTCSeconds() |
| 511 | const nextSecond = table.second[currentSecond] |
| 512 | if (nextSecond === undefined) { |
| 513 | current.setUTCMinutes(current.getUTCMinutes() + tick, boundary.second) |
| 514 | adjustDst(current) |
| 515 | continue |
| 516 | } |
| 517 | if (needsStep(nextSecond, currentSecond)) { |
| 518 | current.setUTCSeconds(nextSecond) |
| 519 | adjustDst(current) |
| 520 | continue |
| 521 | } |
| 522 | } |
| 523 | |
| 524 | if (cron.minutes.size !== 0) { |
| 525 | const currentMinute = current.getUTCMinutes() |
| 526 | const nextMinute = table.minute[currentMinute] |
| 527 | if (nextMinute === undefined) { |
| 528 | current.setUTCHours(current.getUTCHours() + tick, boundary.minute, boundary.second) |
| 529 | adjustDst(current) |
| 530 | continue |
| 531 | } |
| 532 | if (needsStep(nextMinute, currentMinute)) { |
| 533 | current.setUTCMinutes(nextMinute, boundary.second) |
no test coverage detected