elm-community/elm-time/3.0.3

NOTE: this package is not compatible with Elm 0.19.1

Time.Date

This module defines a timezone-independent Date type which can represent any date of the proleptic Gregorian calendar.

Dates

type Date

Date is the opaque type for all Date values. Values of this type are guaranteed to represent valid proleptic Gregorian calendar dates.

date : Int -> Int -> Int -> Date

date constructs a Date value given a year, a month and a day. Invalid values are clamped to the nearest valid date.

d : Date
d =
    date 2018 5 29


year d --> 2018
month d --> 5
day d --> 29
year : Date -> Int

year returns a Date's year as an Int.

year (date 2018 5 26)
--> 2018
month : Date -> Int

month returns a Date's month as an Int. Guaranteed to be in the range [1, 12].

month (date 2018 13 26) -- Note month will be clamped
--> 12
day : Date -> Int

day returns a Date's year as an Int. Guaranteed to be valid for the Date's (year, month) pair and in the range [1, 31].

day (date 2018 2 28)
--> 28


day (date 2018 2 29)
--> 28    -- observed clamped


day (date 2000 2 29)
--> 29    -- leap year
type Weekday
= Mon
| Tue
| Wed
| Thu
| Fri
| Sat
| Sun

Data type used to represent the days of the week.

weekday : Date -> Weekday

weekday returns the day of week for a given Date.

This uses Sakamoto's method to determine the day of week.

weekday (date 2018 5 26)
--> Sat

Manipulating Dates

setYear : Int -> Date -> Date

setYear updates a Date's year. Invalid values are clamped to the nearest valid date.

date 2000 5 26
|> setYear 2016
|> year
--> 2016
setMonth : Int -> Date -> Date

setMonth updates a Date's month. Invalid values are clamped to the nearest valid date.

date 2016 5 26
|> setMonth 6
|> month
--> 6


date 2016 5 26
|> setMonth 13 -- will be clamped
|> month
--> 12
setDay : Int -> Date -> Date

setDay updates a Date's day. Invalid values are clamped to the nearest valid date.

date 2016 2 26
|> setDay 28
|> day
--> 28


date 2016 2 28
|> setDay 29    -- leap year
|> day
--> 29


date 2015 2 28
|> setDay 29    -- clamped
|> day
--> 28
addYears : Int -> Date -> Date

addYears adds a relative number (positive or negative) of years to a Date, ensuring that the return value represents a valid Date. If the new date is not valid, days are subtracted from it until a valid Date can be produced.

date 2000 2 29
|> addYears -1  -- will no longer be leap year
|> day
--> 28
addMonths : Int -> Date -> Date

addMonths adds a relative number (positive or negative) of months to a Date, ensuring that the return value represents a valid Date. Its semantics are the same as addYears.

date 2018 3 31
|> addMonths -1 -- Switch to Feb
|> day
--> 28
addDays : Int -> Date -> Date

days adds an exact number (positive or negative) of days to a Date. Adding or subtracting days always produces a valid Date so there is no fuzzing logic here like there is in add{Months,Years}.

date 2018 2 28
|> addDays 1
|> month
--> 3 -- March

Comparing Dates

compare : Date -> Date -> Order

compare two Dates.

Note: since this conflicts with Basics.compare, have to preface with Time.Date.; see this example:

date 2018 1 28
|> addYears -1
|> addMonths 1
|> Time.Date.compare (date 2017 2 29)
--> EQ

Subtracting Dates

type alias DateDelta =
{ years : Int
, months : Int
, days : Int
}

DateDelta represents a delta between two dates.

delta : Date -> Date -> DateDelta

delta returns the relative number of years, months and days between two Dates.

Each field is accumulative by itself. That is, days not only shows the difference caused by the two day entries in the two Date arguments, but also the added days caused by differences in months and years. For months and years, is the count across month and year change boundaries respectively; illustrated by last example below.

-- 3 examples showing that, if the `year` and `month`
-- are the same in the two `Date` values, then the
-- `years` and `months` result values remain constant
-- in spite of large differences in the two inputs'
-- `day` setting:


delta (date 2019 1 1) (date 2018 1 1)
--> { years = 1
--> , months = 12
--> , days = 365
--> }


delta (date 2019 1 31) (date 2018 1 1)
--> { years = 1
--> , months = 12
--> , days = 395
--> }


delta (date 2019 1 1) (date 2018 1 31)
--> { years = 1
--> , months = 12
--> , days = 335
--> }


-- 1 day apart but from last day of year to first
-- day of next year:


delta (date 2019 1 1) (date 2018 12 31)
--> { years = 1
--> , months = 1
--> , days = 1
--> }

Helper functions

toTuple : Date -> ( Int, Int, Int )

toTuple converts a Date value into a (year, month, day) tuple. This is useful if you want to use Dates as Dict keys.

date 2018 5 26
|> toTuple
--> (2018, 5, 26)
fromTuple : ( Int, Int, Int ) -> Date

fromTuple converts a (year, month, day) tuple into a Date value.

(2018, 5, 26)
|> fromTuple
--> date 2018 5 26
isValidDate : Int -> Int -> Int -> Bool

isValidDate returns True if the given year, month and day represent a valid date.

NOTE: when you create a Date using date, it does not validate the year, month, or day used; rather it just clamps out-of-range values to "legal" values without notifying you. If you are worried about complete validation, pass the 3 values to this method first and it will validate it. This gives you a chance to abort creating a "bad" Date.

isValidDate 2016 12 31
--> True


isValidDate 2016 12 32
--> False


isValidDate 2016 2 29 -- leap year
--> True


isValidDate 2018 2 29 -- not leap year
--> False
isLeapYear : Int -> Bool

isLeapYear returns True if the given year is a leap year. The rules for leap years are as follows:

  • A year that is a multiple of 400 is a leap year.

  • A year that is a multiple of 100 but not of 400 is not a leap year.

  • A year that is a multiple of 4 but not of 100 is a leap year.

    isLeapYear 2016 --> True

    isLeapYear 2018 --> False

    isLeapYear 400 --> True

    isLeapYear 500 --> False

    isLeapYear (500 + 4) --> True

daysInMonth : Int -> Int -> Maybe Int

daysInMonth returns the number of days in a month given a specific year, taking leap years into account.

  • A regular year has 365 days and the corresponding February has 28 days.

  • A leap year has 366 days and the corresponding February has 29 days.

    daysInMonth 2016 2 --> Just 29

    daysInMonth 2018 2 --> Just 28

    daysInMonth 2018 13 -- month out of range --> Nothing