Skip to content

A Roc package for parsing ISO Date/Time strings. πŸ“† ⏰ πŸ“¦

License

Notifications You must be signed in to change notification settings

imclerran/roc-isodate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Roc IsoDate

Roc-Lang GitHub last commit CI status

Roc-IsoDate is a universal date and time package for Roc. It Features several useful types for working with dates and times. Its primary types (Date/Time/DateTime) store dates and times in a human friendly manner, but allow easy conversion to and from computer friendly types like Utc as well as web web friendly ISO 8601 strings. Roc IsoDate is intended to be a one-stop-shop for all things date and time. πŸ“† ⏰ πŸ“¦

Implementation

Roc IsoDate's API revolves around its types, primarily Date, Time, and DateTime. These types provide useful functions for such as fromIsoStr, fromIsoStr, as well as functions for parsing directly from a list of Utf8 bytes. The types are based on records containing some of the most common data fields a user might want for working with dates and times in a human friendly manner, IE: year, month, dayOfMonth, dayOfYear, hour, minute, second and nanosecond. It also provides functions for performing math operations on these dates, as well as various constructors, and functions to convert to and from nanoseconds since the epoch for dates or since midnght for time.

Note that due to the expense of purchasing the ISO 8601-2:2019 standard document, my implementation of ISO string parsing is based on a 2016 pre-release copy of the 8601-1 standard, so my implementation may not fully conform to the latest revision to the standard.

Progress

  • Full support for parsing all date representations.
  • Full support for parseing local time representations.
  • Full support for offset from UTC time representations.
  • Full support for combined date/time representations.
  • Can Parse from Str or from a List U8 of Utf-8 bytes.
  • Unify API around Date/Time/DateTime types
    • This means converting to and from ISO strings is as simple as:
    • DateTime.fromIsoStr str or Time.toIsoStr date
    • Similarly, converting to and from Utc is easy:
    • Date.toNanosSinceEpoch date |> Utc.fromNanosSinceEpoch or DateTime.toNanosSinceEpoch utc |> Utc.fromNanosSinceEpoch

Future Plans

  • Time interval representations will be added once the parsing to Date/Time/DateTime is complete [DONE πŸš€].
  • Once Parsing is complete, add formatting dates and times to ISO strings.
  • Research adding custom encoding/decoding for json parsers.

Unified API

To extend functionality and simplify the API, library now simply provides a collection of types for working with dates. Each of these types provide all the necessary functions for interacting with it, including functions for converting to and from ISO strings, and converting to and from Utc types, as well as various other constructors and math functions.

Thus, an application might look like the following:

app [main] {
    pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.14.0/dC5ceT962N_4jmoyoffVdphJ_4GlW3YMhAPyGPr-nU0.tar.br",
    dt: "https://github.com/imclerran/roc-isodate/releases/download/v0.5.0/ptg0ElRLlIqsxMDZTTvQHgUSkNrUSymQaGwTfv0UEmk.tar.br",
}

import dt.DateTime
import dt.Duration
import pf.Utc
import pf.Stdout
import pf.Task exposing [Task]

main =
    utcNow = Utc.now!
    dtNow = utcNow |> Utc.toNanosSinceEpoch |> DateTime.fromNanosSinceEpoch # Convert Utc to DateTime easily
    dtEpoch = DateTime.unixEpoch # Constructor for the epoch
    dtSomeTime = DateTime.fromIsoStr "2024-04-19T11:31:41.329515-05:00" |> unwrap "This is a valid datetime" # parse a DateTime from ISO str easily
    dtLaterDate = dtSomeTime |> DateTime.addDateTimeAndDuration (Duration.fromHours 25 |> unwrap "25 hours cannot overflow") # Add a duration to a DateTime easily
    utcLaterDate = DateTime.toNanosSinceEpoch dtLaterDate |> Utc.fromNanosSinceEpoch # Convert parsed date to Utc
    nanosLaterDate = Utc.toNanosSinceEpoch utcLaterDate

    Stdout.line! "ISO epoch: $(DateTime.toIsoStr dtEpoch)"
    Stdout.line! "Time now: $(Num.toStr dtNow.time.hour):$(Num.toStr dtNow.time.minute):$(Num.toStr dtNow.time.second)"
    Stdout.line! "Day some time: $(Num.toStr dtSomeTime.date.dayOfMonth)"
    Stdout.line! "Utc nanos later date: $(Num.toStr nanosLaterDate)"

unwrap : Result a _, Str -> a
unwrap = \x, message ->
    when x is
        Ok v -> v
        Err _ -> crash message

This is just a small sample of the available functionality, but meant to demonstrate the general design of the API. Moving to and from computer-friendly representations like Utc, web-friendly representations like ISO Strs, and human friendly representations like DateTime are all just a single function call away. Durations and TimeIntervals also add quality of life functionality for easily manipulating dates and times.

Known Issues

  • Missing features mentioned above.
  • ISO Requirement for combined date-time strings to have only non-reduced accuracy dates is not enforced
  • ISO Requirement for combined date-time strings to be in completely basic or completely extended format are not enforced.

ISO 8601 Date/Time Format

Description of ISO date/time format (WIP)