Calendar behaviour
This module defines the responsibilities for working with calendars, dates, times and datetimes in Elixir.
Currently it defines types and the minimal implementation for a calendar behaviour in Elixir. The goal of the Calendar features in Elixir is to provide a base for interoperability instead of full-featured datetime API.
For the actual date, time and datetime structures, see Date
, Time
, NaiveDateTime
and DateTime
.
Note the year, month, day, etc. designations are overspecified (i.e. an integer instead of 1..12
for months) because different calendars may have a different number of days per month, months per year and so on.
Summary
Types
- calendar()
-
A calendar implementation
- date()
-
Any map/struct that contains the date fields
- datetime()
-
Any map/struct that contains the datetime fields
- day()
- day_fraction()
-
The internal time format is used when converting between calendars
- hour()
- iso_days()
-
The internal date format that is used when converting between calendars
- microsecond()
-
Microseconds with stored precision
- minute()
- month()
- naive_datetime()
-
Any map/struct that contains the naive_datetime fields
- second()
- std_offset()
-
The time zone standard offset in seconds (not zero in summer times)
- time()
-
Any map/struct that contains the time fields
- time_zone()
-
The time zone ID according to the IANA tz database (e.g. Europe/Zurich)
- utc_offset()
-
The time zone UTC offset in seconds
- year()
- zone_abbr()
-
The time zone abbreviation (e.g. CET or CEST or BST etc.)
Functions
- compatible_calendars?(calendar, calendar)
-
Returns
true
if two calendars have the same moment of starting a new day,false
otherwise - truncate(microsecond_tuple, atom)
-
Returns a microsecond tuple truncated to a given precision (
:microsecond
,:millisecond
or:second
)
Callbacks
- date_to_string(year, month, day)
-
Converts the date into a string according to the calendar
- datetime_to_string(year, month, day, hour, minute, second, microsecond, time_zone, zone_abbr, utc_offset, std_offset)
-
Converts the datetime (with time zone) into a string according to the calendar
- day_of_week(year, month, day)
-
Calculates the day of the week from the given
year
,month
, andday
- day_rollover_relative_to_midnight_utc()
-
Define the rollover moment for the given calendar
- days_in_month(year, month)
-
Returns how many days there are in the given year-month
- leap_year?(year)
-
Returns true if the given year is a leap year
- naive_datetime_from_iso_days(iso_days)
-
Converts
t:iso_days
to the Calendar’s datetime format - naive_datetime_to_iso_days(year, month, day, hour, minute, second, microsecond)
-
Converts the given datetime (with time zone) into the
t:iso_days
format - naive_datetime_to_string(year, month, day, hour, minute, second, microsecond)
-
Converts the datetime (without time zone) into a string according to the calendar
- time_from_day_fraction(day_fraction)
-
Converts
t:day_fraction
to the Calendar’s time format - time_to_day_fraction(hour, minute, second, microsecond)
-
Converts the given time to the
t:day_fraction
format - time_to_string(hour, minute, second, microsecond)
-
Converts the time into a string according to the calendar
- valid_date?(year, month, day)
-
Should return
true
if the given date describes a proper date in the calendar - valid_time?(hour, minute, second, microsecond)
-
Should return
true
if the given time describes a proper time in the calendar
Types
calendar()
calendar() :: module()
A calendar implementation
date()
date() :: %{ optional(any()) => any(), :calendar => calendar(), :year => year(), :month => month(), :day => day() }
Any map/struct that contains the date fields
datetime()
datetime() :: %{ optional(any()) => any(), :calendar => calendar(), :year => year(), :month => month(), :day => day(), :hour => hour(), :minute => minute(), :second => second(), :microsecond => microsecond(), :time_zone => time_zone(), :zone_abbr => zone_abbr(), :utc_offset => utc_offset(), :std_offset => std_offset() }
Any map/struct that contains the datetime fields
day()
day() :: integer()
day_fraction()
day_fraction() :: {parts_in_day :: non_neg_integer(), parts_per_day :: pos_integer()}
The internal time format is used when converting between calendars.
It represents time as a fraction of a day (starting from midnight). parts_in_day
specifies how much of the day is already passed, while parts_per_day
signifies how many parts there fit in a day.
hour()
hour() :: integer()
iso_days()
iso_days() :: {days :: integer(), day_fraction()}
The internal date format that is used when converting between calendars.
This is the number of days including the fractional part that has passed of the last day since 0000-01-01+00:00T00:00.00000 in ISO 8601 notation (also known as midnight 1 January BC 1 of the proleptic Gregorian calendar).
The parts_per_day
represent how many subparts the current day is subdivided in (for different calendars, picking a different parts_per_day
might make sense). The parts_in_day
represents how many of these parts_per_day
have passed in the last day.
microsecond()
microsecond() :: {0..999_999, 0..6}
Microseconds with stored precision.
The precision represents the number of digits that must be used when representing the microseconds to external format. If the precision is 0, it means microseconds must be skipped.
minute()
minute() :: integer()
month()
month() :: integer()
naive_datetime()
naive_datetime() :: %{ optional(any()) => any(), :calendar => calendar(), :year => year(), :month => month(), :day => day(), :hour => hour(), :minute => minute(), :second => second(), :microsecond => microsecond() }
Any map/struct that contains the naive_datetime fields
second()
second() :: integer()
std_offset()
std_offset() :: integer()
The time zone standard offset in seconds (not zero in summer times)
time()
time() :: %{ optional(any()) => any(), :hour => hour(), :minute => minute(), :second => second(), :microsecond => microsecond() }
Any map/struct that contains the time fields
time_zone()
time_zone() :: String.t()
The time zone ID according to the IANA tz database (e.g. Europe/Zurich)
utc_offset()
utc_offset() :: integer()
The time zone UTC offset in seconds
year()
year() :: integer()
zone_abbr()
zone_abbr() :: String.t()
The time zone abbreviation (e.g. CET or CEST or BST etc.)
Functions
compatible_calendars?(calendar, calendar)
compatible_calendars?(Calendar.calendar(), Calendar.calendar()) :: boolean()
Returns true
if two calendars have the same moment of starting a new day, false
otherwise.
If two calendars are not compatible, we can only convert datetimes and times between them. If they are compatible, this means that we can also convert dates as well as naive datetimes between them.
truncate(microsecond_tuple, atom)
truncate(Calendar.microsecond(), :microsecond | :millisecond | :second) :: Calendar.microsecond()
Returns a microsecond tuple truncated to a given precision (:microsecond
, :millisecond
or :second
).
Callbacks
date_to_string(year, month, day)
date_to_string(year(), month(), day()) :: String.t()
Converts the date into a string according to the calendar.
datetime_to_string(year, month, day, hour, minute, second, microsecond, time_zone, zone_abbr, utc_offset, std_offset)
datetime_to_string( year(), month(), day(), hour(), minute(), second(), microsecond(), time_zone(), zone_abbr(), utc_offset(), std_offset() ) :: String.t()
Converts the datetime (with time zone) into a string according to the calendar.
day_of_week(year, month, day)
day_of_week(year(), month(), day()) :: non_neg_integer()
Calculates the day of the week from the given year
, month
, and day
.
day_rollover_relative_to_midnight_utc()
day_rollover_relative_to_midnight_utc() :: day_fraction()
Define the rollover moment for the given calendar.
This is the moment, in your calendar, when the current day ends and the next day starts.
The result of this function is used to check if two calendars rollover at the same time of day. If they do not, we can only convert datetimes and times between them. If they do, this means that we can also convert dates as well as naive datetimes between them.
This day fraction should be in its most simplified form possible, to make comparisons fast.
Examples
- If, in your Calendar, a new day starts at midnight, return {0, 1}.
- If, in your Calendar, a new day starts at sunrise, return {1, 4}.
- If, in your Calendar, a new day starts at noon, return {1, 2}.
- If, in your Calendar, a new day starts at sunset, return {3, 4}.
days_in_month(year, month)
days_in_month(year(), month()) :: day()
Returns how many days there are in the given year-month.
leap_year?(year)
leap_year?(year()) :: boolean()
Returns true if the given year is a leap year.
A leap year is a year of a longer length than normal. The exact meaning is up to the calendar. A calendar must return false
if it does not support the concept of leap years.
naive_datetime_from_iso_days(iso_days)
naive_datetime_from_iso_days(iso_days()) :: {year(), month(), day(), hour(), minute(), second(), microsecond()}
Converts t:iso_days
to the Calendar’s datetime format.
naive_datetime_to_iso_days(year, month, day, hour, minute, second, microsecond)
naive_datetime_to_iso_days( year(), month(), day(), hour(), minute(), second(), microsecond() ) :: iso_days()
Converts the given datetime (with time zone) into the t:iso_days
format.
naive_datetime_to_string(year, month, day, hour, minute, second, microsecond)
naive_datetime_to_string( year(), month(), day(), hour(), minute(), second(), microsecond() ) :: String.t()
Converts the datetime (without time zone) into a string according to the calendar.
time_from_day_fraction(day_fraction)
time_from_day_fraction(day_fraction()) :: {hour(), minute(), second(), microsecond()}
Converts t:day_fraction
to the Calendar’s time format.
time_to_day_fraction(hour, minute, second, microsecond)
time_to_day_fraction(hour(), minute(), second(), microsecond()) :: day_fraction()
Converts the given time to the t:day_fraction
format.
time_to_string(hour, minute, second, microsecond)
time_to_string(hour(), minute(), second(), microsecond()) :: String.t()
Converts the time into a string according to the calendar.
valid_date?(year, month, day)
valid_date?(year(), month(), day()) :: boolean()
Should return true
if the given date describes a proper date in the calendar.
valid_time?(hour, minute, second, microsecond)
valid_time?(hour(), minute(), second(), microsecond()) :: boolean()
Should return true
if the given time describes a proper time in the calendar.
© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.6.6/Calendar.html