Skip to content

cycleDate

cycleDate(value: string, field: DateCycleField, amount: number, options?: { round?: boolean; overflow?: Overflow; }): string
import { cycleDate } from "@northguild/gmt/plain/calculate";

Return a PlainDate ISO string with field cycled by amount, wrapping at that field’s own

  • min/max instead of carrying into the next larger field.
  • cycleDate is not addDate: cycling December’s month by +1 stays in the same year ("2024-12-15""2024-01-15"), where addDate(value, { months: 1 }) would correctly overflow into January of the next year. Reach for addDate when you want calendar arithmetic; reach for cycleDate when a single field (e.g. a datepicker segment) must stay isolated from the others.
  • year has no upper/lower wrap — cycling it is plain addition (or rounding, see below). month wraps 1–12. day wraps 1–the current month’s day count, so cycling day never changes month.
  • Cycling month or year can still shift day via overflow — e.g. cycling month from a 31st into a shorter month clamps under the default "constrain" (or returns "" under "reject") exactly the way setDate’s own .with() call does; this is the same clamping addDate’s Jan 31 + 1 month case produces, not new behavior.
  • options.round does not round to the nearest increment — it steps to the next multiple of amount in the direction of its sign (ceiling for positive, floor for negative), matching @internationalized/date’s CycleOptions.round. E.g. cycling year 2022 by +5 with round: true lands on 2025 (the next multiple of 5 above 2022), not 2020 (the nearest multiple).
  • Returns “” for an invalid value or an invalid field.
Parameter Type Description
value string ISO PlainDate string
field DateCycleField the field to cycle: “year” | “month” | “day”
amount number signed amount to cycle by

options

Option Type Default
round? boolean
overflow? Overflow

ISO PlainDate string with field cycled, or “” on invalid input

cycleDate("2024-06-15", "month", 1) // "2024-07-15"
cycleDate("2024-12-15", "month", 1) // "2024-01-15" (wraps, stays in the same year)
cycleDate("2024-12-31", "day", 1) // "2024-12-01" (wraps within the same month)
cycleDate("2024-01-15", "month", 13) // "2024-02-15" (amount larger than the range)
cycleDate("2024-01-31", "month", 1) // "2024-02-29" (constrain clamps the day)
cycleDate("2024-01-31", "month", 1, { overflow: "reject" }) // ""
cycleDate("2022-02-03", "year", 5, { round: true }) // "2025-02-03"
cycleDate("2024-06-15", "week", 1) // "" ("week" is not a cyclable date field)
cycleDate("invalid", "month", 1) // ""

plain/calculate/cycleDate.ts