*Preface* We currently have `add/2-3` to manipulate calendar types in the standard library. These functions allow adding a specified amount of time of given unit to a date/time. The standard library currently misses means to apply more complex, or logical *durations *to calendar types. e.g. adding a month, a week, or one month and 10 days to a date.
*Reasons for it* While similar functionality exists in libraries, such as CLDR, Timex, Tox, adding this functionality to the standard library has already been requested and discussed at multiple occasions over the past years. To list a few examples: - https://github.com/elixir-lang/elixir/pull/10199 - https://elixirforum.com/t/get-date-n-months-years-in-the-past/48346/3 - https://elixir-lang.slack.com/archives/C0HEX82NR/p1709581478427009?thread_ts=1709368588.334759&cid=C0HEX82NR Furthermore the shift behaviour in the extremely popular library Timex changed <https://github.com/bitwalker/timex/issues/731> in Elixir >= 1.14.3 which may have complicated the mostly lean and non-breaking language upgrade Elixir has to offer. Elixir has a great set of modules and functions that deal with date and time, the APIs are consistent and `shift/2-3` should fit right in, solving many standard needs of various industries, be it for reporting, appointments, events, finance... the list goes on, engineers probably face the need to shift time logically more often than not in their careers. *Technical details* Duration A date or time must be shifted by a *duration*. There is an ISO8601 for durations <https://en.wikipedia.org/wiki/ISO_8601#Durations>, which the initial implementation is loosely following. The structure of a Duration lives in its own module with its own set of functions to create and manipulate durations. One example of where it diverts from the ISO standard, is that it implements microseconds. Microseconds in a *duration* are stored in the same format as in the time calendar types, meaning they integrate well and provide consistency. Shift The shift behaviour is implemented as a callback on Calendar and supported by all calendar types: Date, DateTime, NaiveDateTime and Time. Date, Time and NaiveDateTime each have their own implementation of a "shift", while DateTime gets converted to a NaiveDateTime before applying the shift, and is then rebuilt to a DateTime in its original timezone. `shift/2-3` also has guaranteed output types (which isn't a given in many libraries) and follows the consistent API which is established in the calendar modules. Find the current state of the implementation here: https://github.com/elixir-lang/elixir/pull/13385 *Benchmarks* There are some benchmarks + StreamData tests in the PR description. *Outlook* *After *adding the Duration type and shift behaviour to the standard library, the following things could be explored and derived from the initial work: - Implementing a protocol that allows Duration to be applied to any data type, not just dates and times. - A range-like data type that allows us to do recurring constructs on any data type. For example, Duration.interval(~D[2000-01-01], month: 1), when iterated, would emit {:ok, date} | {:error, start, duration, reason} entries - A sigil for easy creation of durations: ~P[3 hours and 10 minutes] - Making it so add/2-3 reuses the shift_* functions *Reasons against it* While I am convinced that adding `shift/2-3` to the standard library would be very beneficial, nothing really speaks against the points mentioned above to be implemented in a library instead. However, something as crucial and central as date/time manipulation should still be part of the standard library, negating the risk of breaking changes, inconsistent behaviour and outdated or too unique ergonomics which aren't widely applicable, unlike what should be part of the standard library. Many thanks to @jose & @kip for the initial reviews and everyone in advance taking the time to read the proposal! Looking forward to hear other peoples ideas and opinions on the subject! -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/cb0ed628-3848-4de0-aa13-c0f4761e4d99n%40googlegroups.com.