justinmimbs / time-extra / Time.Extra

Create


type alias Parts =
{ year : Basics.Int
, month : Time.Month
, day : Basics.Int
, hour : Basics.Int
, minute : Basics.Int
, second : Basics.Int
, millisecond : Basics.Int 
}

Represents a time abstractly by describing its calendar date and clock time. Given a time zone, this information can be converted to a Posix, i.e. a concrete moment in time.

partsToPosix : Time.Zone -> Parts -> Time.Posix

Create a Posix from a description of a time and a specific time zone.

import Time exposing (Month(..), utc)
import Time.Extra exposing (Parts, partsToPosix)

partsToPosix utc (Parts 2018 Sep 26 14 30 0 0)

Any out-of-range day or time values will be clamped within range.

partsToPosix utc (Parts 2018 Sep 31 24 60 -60 -500)
    == partsToPosix utc (Parts 2018 Sep 30 23 59 0 0)

Convert

posixToParts : Time.Zone -> Time.Posix -> Parts

Convert a Posix to a description of a time in a specific time zone. This is a convenience function for extracting parts of a time into a single record.

import Time exposing (Month(..), utc)
import Time.Extra exposing (Parts, partsToPosix, posixToParts)

posixToParts
    utc
    (partsToPosix utc (Parts 2018 Sep 26 14 30 0 0))
    == { year = 2018
       , month = Sep
       , day = 26
       , hour = 14
       , minute = 30
       , second = 0
       , millisecond = 0
       }

Intervals


type Interval
    = Year
    | Quarter
    | Month
    | Week
    | Monday
    | Tuesday
    | Wednesday
    | Thursday
    | Friday
    | Saturday
    | Sunday
    | Day
    | Hour
    | Minute
    | Second
    | Millisecond

Represents an interval of time.

Comparison

compare : Time.Posix -> Time.Posix -> Basics.Order

Compare the first time to the second time.

import Time
import Time.Extra as Time

Time.compare (Time.millisToPosix 0) (Time.millisToPosix 1000)
    == LT

Difference

diff : Interval -> Time.Zone -> Time.Posix -> Time.Posix -> Basics.Int

Get the difference, as a number of whole intervals, between two times.

import Time exposing (Month(..), utc)
import Time.Extra exposing (Interval(..), Parts, partsToPosix, diff)

diff Month utc
    (partsToPosix utc (Parts 2020 Jan 2 0 0 0 0))
    (partsToPosix utc (Parts 2020 Apr 1 0 0 0 0))
    == 2

Shift

add : Interval -> Basics.Int -> Time.Zone -> Time.Posix -> Time.Posix

Shift a time into the past or future by adding a number of whole intervals.

import Time exposing (Month(..), utc)
import Time.Extra exposing (Interval(..), Parts, partsToPosix, add)

add Week 2 utc (partsToPosix utc (Parts 2018 Sep 1 11 55 0 0))
    == partsToPosix utc (Parts 2018 Sep 15 11 55 0 0)

When adding Month, Quarter, or Year intervals, day values are clamped to the end of the month if necessary.

add Month 1 utc (partsToPosix utc (Parts 2020 Jan 31 0 0 0 0))
    == partsToPosix utc (Parts 2020 Feb 29 0 0 0 0)

floor : Interval -> Time.Zone -> Time.Posix -> Time.Posix

Round down a time to the beginning of the closest interval. The resulting time will be less than or equal to the one provided.

import Time exposing (Month(..), utc)
import Time.Extra exposing (Interval(..), Parts, partsToPosix, floor)

floor Hour utc
    (partsToPosix utc (Parts 1999 Dec 31 23 59 59 999))
    == (partsToPosix utc (Parts 1999 Dec 31 23 0 0 0))

ceiling : Interval -> Time.Zone -> Time.Posix -> Time.Posix

Round up a time to the beginning of the closest interval. The resulting time will be greater than or equal to the one provided.

import Time exposing (Month(..), utc)
import Time.Extra exposing (Interval(..), Parts, partsToPosix, ceiling)

ceiling Hour utc
    (partsToPosix utc (Parts 1999 Dec 31 23 59 59 999))
    == (partsToPosix utc (Parts 2000 Jan 1 0 0 0 0))

Lists

range : Interval -> Basics.Int -> Time.Zone -> Time.Posix -> Time.Posix -> List Time.Posix

Create a list of times, at rounded intervals, increasing by a step value, between two times. The list will start on or after the first time, and end before the second time.

import Time exposing (Month(..), utc)
import Time.Extra exposing (Interval(..), Parts, partsToPosix, range)

start = Parts 2020 Jan 1 12 0 0 0
until = Parts 2020 Jan 8 0 0 0 0

range Day 2 utc (partsToPosix utc start) (partsToPosix utc until)
    == List.map (partsToPosix utc)
        [ Parts 2020 Jan 2 0 0 0 0
        , Parts 2020 Jan 4 0 0 0 0
        , Parts 2020 Jan 6 0 0 0 0
        ]

Time zone offset

toOffset : Time.Zone -> Time.Posix -> Basics.Int

What is the offset from UTC, in minutes, for this Zone at this Posix time?

import Time exposing (Month(..))
import Time.Extra exposing (Parts, partsToPosix, toOffset)

toOffset nyc
    (partsToPosix nyc (Parts 2018 Sep 26 10 30 0 0))
    == -240

-- assuming `nyc` is a `Zone` for America/New_York

Note: It's possible to verify the example above by using time zone data from the package justinmimbs/timezone-data to define nyc:

import TimeZone

nyc =
    TimeZone.america__new_york ()