Skip to content

Tempo version 2.1.0

Choose a tag to compare

@kipcole9 kipcole9 released this 28 Oct 05:26
· 4 commits to main since this release

[v2.1.0] — 2026-10-28

Added

  • Tempo.count/3 — how many values of a unit an expression holds, the values Tempo.walk/3 gives counted (Tempo.count(business_days, :day)), a clock unit without walking it. Takes :within for an expression with no end.

  • Tempo.DateRule.parse/2 reads a yearly date written in date-holidays' rule grammar (4th Thursday in November, easter -2, 15 Nisan, chinese 01-0-01) into the Tempo recurrence it means. Observed days, bridges and if is holiday moves read to members of a Tempo.RecurrenceSet; the date rules guide takes the grammar part by part.

Changed

  • Tempo.walk/3 and Tempo.count/3 at a clock unit give each unit the span touches, as at a calendar unit: half past ten to half past twelve is ten, eleven and twelve o'clock, where a clock with no named zone stepped one unit from the start and stopped at eleven.

  • The values of a set in a unit come in the order of time, each once (decision 88): 2026Y6M{6,7}K is each weekend day in turn and 2026Y6M{15,1}D the 1st before the 15th, where they came member by member in the order written.

  • Tempo.intersection/3, and Tempo.difference/3 from an operand with a year, place an operand with no year on the other operand's stretch when no :within is given (Tempo.difference(fortnight, ~o"{6,7}K")), where it was a Tempo.FrameError.

  • Requires Calendrical 2.2, whose lunisolar calendars give the year a sexagenary cycle and its year name, as a date rule written with them (chinese 78-32-08-0-15) is read.

Fixed

  • Tempo.walk/3 of a duration is a Tempo.ConversionError (:bare_duration), where it raised.

  • A value with no year a window places is the part of each occurrence within the window (Tempo.to_interval(~o"6M", within: ~o"2026-06-10/2026-07-05") is the 10th to the 30th), where a window holding part of one placed none, one within a day placed the whole day, and a day of the month could be placed outside the window.

  • An open end a window places at an edge finer than the span is written to that edge (2026Y6M/3DT0H), where it was written to the span's own unit and read back longer (2026Y6M/2026Y6M).

  • A span with no year placed by a window is placed from each start the window holds (decision 72) whole, where a window finer than its unit raised (to_interval(~o"6M/8M", within: ~o"2026-06-01T00/2026-06-03T00")), and its open end is cut at the window's edge, as a span with a year's is (complement(~o"6M/..", within: ~o"2026")).

  • Tempo.to_interval/2 with no window refuses at once a rule over years with no end (R/{1973Y/..}/…), or a set holding one, where it walked to a limit for seconds and listed an equinox to the end of the ephemeris.

  • Tempo.bounded?/1 is true of a rule over years that end (R/{2020Y..2024Y}/…), which to_interval/2 lists with no window, and asks a conditional member about what it holds.

  • A set operation's :within places an operand with no year on each period of a window that is a range (within: ~o"2026-01-02/2026-03-31" with ~o"{6,7}K"), where it was a Tempo.FrameError, and as Tempo.to_interval/2 places it, so a span that wraps past a one-value window (12M/2M in June) is outside it.