This module defines a timezone-independent Date type which can represent any date of the proleptic Gregorian calendar.
Date is the opaque type for all Date values. Values of this type are guaranteed to represent valid proleptic Gregorian calendar dates.
date : Basics.Int -> Basics.Int -> Basics.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
fromTuple : ( Basics.Int, Basics.Int, Basics.Int ) -> Date
fromTuple converts a (year, month, day) tuple into a Date value.
(2018, 5, 26)
|> fromTuple
--> date 2018 5 26
toTuple : Date -> ( Basics.Int, Basics.Int, Basics.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)
year : Date -> Basics.Int
year returns a Date's year as an Int.
year (date 2018 5 26)
--> 2018
month : Date -> Basics.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 -> Basics.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
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
setYear : Basics.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 : Basics.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 : Basics.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 : Basics.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 : Basics.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 : Basics.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
compare : Date -> Date -> Basics.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
{ years : Basics.Int
, months : Basics.Int
, days : Basics.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
--> }
isValidDate : Basics.Int -> Basics.Int -> Basics.Int -> Basics.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 : Basics.Int -> Basics.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 : Basics.Int -> Basics.Int -> Basics.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 --> 29
daysInMonth 2018 2 --> 28