-module(datebook@date). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/datebook/date.gleam"). -export([next/1, previous/1, range/2]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC(" Utility functions for `gleam/time`'s `calendar.Date`.\n"). -file("src/datebook/date.gleam", 16). ?DOC( " Returns the next `Date` for a given `Date`.\n" "\n" " # Examples\n" "\n" " ```gleam\n" " next(calendar.Date(2026, calendar.March, 22))\n" " // -> calendar.Date(2026, calendar.March, 23)\n" " ```\n" ). -spec next(gleam@time@calendar:date()) -> gleam@time@calendar:date(). next(Date) -> {Month, Day} = case erlang:element(4, Date) =:= datebook@month:last_day( erlang:element(3, Date), erlang:element(2, Date) ) of true -> {datebook@month:next(erlang:element(3, Date)), 1}; false -> {erlang:element(3, Date), erlang:element(4, Date) + 1} end, Year = case {Month, Day} of {january, 1} -> erlang:element(2, Date) + 1; {_, _} -> erlang:element(2, Date) end, {date, Year, Month, Day}. -file("src/datebook/date.gleam", 38). ?DOC( " Returns the previous `Date` for a given `Date`.\n" "\n" " # Examples\n" "\n" " ```gleam\n" " previous(calendar.Date(2026, calendar.March, 22))\n" " // -> calendar.Date(2026, calendar.March, 21)\n" " ```\n" ). -spec previous(gleam@time@calendar:date()) -> gleam@time@calendar:date(). previous(Date) -> {Month@1, Day} = case erlang:element(4, Date) =:= 1 of true -> Month = datebook@month:previous(erlang:element(3, Date)), {Month, datebook@month:last_day(Month, erlang:element(2, Date))}; false -> {erlang:element(3, Date), erlang:element(4, Date) - 1} end, Year = case {Month@1, Day} of {december, 31} -> erlang:element(2, Date) - 1; {_, _} -> erlang:element(2, Date) end, {date, Year, Month@1, Day}. -file("src/datebook/date.gleam", 55). -spec range_rec( gleam@time@calendar:date(), gleam@time@calendar:date(), list(gleam@time@calendar:date()) ) -> list(gleam@time@calendar:date()). range_rec(From, To, Acc) -> case From =:= To of true -> [From | Acc]; false -> range_rec(From, previous(To), [To | Acc]) end. -file("src/datebook/date.gleam", 88). ?DOC( " Returns the inclusive list of dates between `from` and `to`.\n" " \n" " Fails if `from` > `to`.\n" "\n" " # Examples\n" "\n" " ```gleam\n" " range(Date(2026, March, 29), Date(2026, April, 2))\n" " // -> Ok([\n" " // Date(2026, March, 29),\n" " // Date(2026, March, 30),\n" " // Date(2026, March, 31),\n" " // Date(2026, April, 1),\n" " // Date(2026, April, 2),\n" " // ])\n" " ```\n" "\n" " ```gleam\n" " range(Date(2026, March, 22), Date(2026, March, 22))\n" " // -> Ok([Date(2026, March, 22)])\n" " ```\n" "\n" " ```gleam\n" " range(Date(2026, March, 22), Date(2026, March, 21))\n" " // -> Error(Nil)\n" " ```\n" ). -spec range(gleam@time@calendar:date(), gleam@time@calendar:date()) -> {ok, list(gleam@time@calendar:date())} | {error, nil}. range(From, To) -> gleam@bool:guard( gleam@time@calendar:naive_date_compare(From, To) =:= gt, {error, nil}, fun() -> {ok, range_rec(From, To, [])} end ).