tick

repository·master·Indexed 20 days ago

https://github.com/juxt/tick

A Clojure(Script) and Babashka library for date and time manipulation. It serves as a cross-platform replacement for clj-time, providing a concise API based on java.time on the JVM and js-joda on JavaScript runtimes. The library provides abstractions for temporals (dates, instants, zoned-date-times) and temporal-amounts (durations and periods), along with utilities for parsing, formatting, and clock manipulation for predictable testing.

Tokens
17K
Snippets
81
Records
94
Agent score
69%

What's inside tick

  1. Overview of Tick

    master

    Tick is a comprehensive Clojure(Script) library for date and time calculations. It provides a cross-platform API (identical for Clojure and ClojureScript) designed to make date-heavy business logic portable.

    Key features include:

    • Succinct functions for manipulating time (stable).
    • Powerful functions for slicing and dicing time intervals (stable).
    • Implementation of Allen's interval algebra (alpha).
    • Support for iCalendar serialization (work-in-progress).

    Because Tick is built on java.time, it is highly interoperable with the Java 8+ date-time API. Tick entities are essentially java.time entities (such as Instant, LocalTime, etc.).

  2. Understand the core concepts of tick

    master

    Tick is built around two primary abstractions:

    1. temporal: An entity relating to a specific point or period on the timeline (e.g., date, instant, zoned-date-time).
    2. temporal-amount: An entity representing a quantity of time, categorized as either a Duration or a Period (e.g., hours, days).

    Note on Naming Convention: Functions relating to temporals use singular names (e.g., t/hour), while functions relating to temporal-amounts use plural names (e.g., t/hours).

    If tick does not provide a specific API you need, you can use cljc.java-time as a fallback.

  3. Understand Tick stability and API status

    master

    Tick's features are categorized by stability:

    • tick.core: The main API, which is stable.
    • tick.alpha.* (e.g., tick.alpha.interval): These namespaces are in alpha status, meaning the API may change in future versions.
  4. What are Intervals in tick

    master

    In tick, an interval is a span of time defined by two points in time, where the first point must be before the second.

    Intervals are implemented as Clojure maps containing two specific keys:

    • :tick/beginning
    • :tick/end

    Because they are maps, any Clojure map containing these keys can be treated as an interval. For consistency, the start and end points should share the same type.

    Note: Interval functions are currently in alpha status and are located in the tick.alpha.interval namespace.

  5. How Instants and calendar-awareness work in Tick

    master

    In tick, Instants are not calendar-aware; they represent a point on the timeline (millis+nanos from the Unix epoch) without a specific timezone or calendar context. Consequently, you cannot directly call calendar-based methods like year or month on an Instant without context.

    To perform calendar-aware operations (like getting the year), you must first convert the Instant into a ZonedDateTime using a specific zone. If you do not specify a zone, tick will use the browser's or JVM's default timezone.

    Explicitly setting a zone

    To ensure predictable results, use t/in to specify the required zone (e.g., "UTC") before calling calendar functions.

    (-> (t/instant)
        (t/in "UTC")
        (t/year))
  6. Map java.time names to tick names

    master

    Tick uses a simplified naming convention compared to java.time. Use the following mappings when looking for specific types:

    java.time Typetick Name
    LocalDatedate
    LocalDateTimedate-time
    LocalTimetime
    java.util.Dateinst
    js/Dateinst

    Other names follow the camel-case equivalents of java.time names.

  7. Extracting dates and times from an Instant

    master

    You can extract specific components (like date or time) from an Instant.

    Caution: Extracting a date or time from an Instant results in a local value based on the system's or browser's default timezone. To ensure you get the date or time in a specific timezone (like UTC), you must first convert the Instant to a ZonedDateTime using t/in.

    To get the UTC date from an Instant:

    1. Convert the Instant to the UTC zone using t/in.
    2. Extract the date using t/date.
    (->
       (t/instant "1999-12-31T00:59:59Z")
       (t/in "UTC")
       (t/date))
  8. Use time-literals for serialization

    master

    Tick bundles the time-literals library, allowing you to use tagged literals for dates and periods in your code or REPL. For example, typing #time/period "P1D" will be read as a java.time.Period (in Clojure) or a js-joda Period (in ClojureScript).

    To read and write EDN data containing these literals, refer to the time-literals documentation.

    #time/period "P1D"
  9. Convert temporal values to Instants

    master

    An instant represents a UTC-based date-time. Use it when you don't care about local time zones. You can convert offset-date-time or zoned-date-time values into instants using (t/instant).

    To get the current UTC instant, use (t/instant) or (t/now).

    Caution: When converting between Instants (which are always UTC) and other data types, the result may be affected by the default time zone of your browser or JVM. To get a date from an Instant in UTC specifically, you should first convert it to a UTC ZonedDateTime using (t/in "UTC").

    ;; Convert offset-date-time to instant
    (t/instant (t/offset-date-time "1918-11-11T11:00:00+01:00"))
    
    ;; Get current instant
    (t/instant)
    (t/now)
    
    ;; Safe conversion from Instant to Date in UTC
    (-> (t/instant "1999-12-31T00:59:59Z")
        (t/in "UTC")
        (t/date))
  10. Understand the difference between Durations and Periods

    master

    Tick distinguishes between two types of time spans to handle the difference between fixed-length time and variable-length calendar units:

    • Duration (time-based): Stores time as a fixed amount of seconds. Use this for precise time spans that do not change based on calendar context (e.g., 48 hours).
    • Period (date-based): Stores amounts of years, months, and days. Use this for calendar-relative spans where units have variable lengths due to leap years or Daylight Saving Time (e.g., 2 days might not always be exactly 48 hours).

    Note: For combined entities, the threeten-extra library provides a PeriodDuration type.

  11. Reify date-times from partial components

    master

    You can combine a time or a date into a full date-time using reification functions:

    • (t/at time): Adds a time to a date.
    • (t/on date): Adds a date to a time.
    • (t/in zone): Adds a time zone to a local date-time, producing a zoned-date-time.
    • (t/offset-by offset): Adds a numeric offset to a local date-time, producing an offset-date-time.
    ;; Date + Time -> Date-Time
    (-> (t/date "1918-11-11") (t/at "11:00"))
    (-> (t/time "11:00") (t/on "1918-11-11"))
    
    ;; Local Date-Time + Zone -> Zoned Date-Time
    (-> (t/time "11:00") (t/on "1918-11-11") (t/in "Europe/Paris"))
    
    ;; Local Date-Time + Offset -> Offset Date-Time
    (-> (t/time "11:00") (t/on "1918-11-11") (t/offset-by 2))
  12. Understand Instants and Inst in tick

    master

    tick uses java.time.Instant as its default convention for representing points in time. However, it also supports Inst (a representation compatible with java.util.Date) to cater to older projects.

    Best Practice: It is recommended to keep time values as an Instant for as long as possible when using tick to ensure maximum compatibility with its core functions.