Tox.DateTime (tox v0.2.3)

A set of functions to work with DateTime.

All examples are using TimeZoneInfo.TimeZoneDatabase. But everything also works with any other time zone DB as long as the time zones are available in the DB.

Link to this section Summary

Functions

Returns true if datetime1 occurs after datetime2.

Returns true if datetime1 occurs after datetime2 or both datetimes are equal.

Returns true if datetime1 occurs before datetime2.

Returns true if datetime1 occurs before datetime2 or both datetimes are equal.

Returns a datetime representing the start of the day.

Returns a datetime representing the start of the week.

Returns a boolean indicating whether datetime occurs between from and to. The optional boundaries specifies whether from and to are included or not. The possible value for boundaries are

Returns datetime representing the end of the day.

Returns a datetime} representing the end of the month.

Returns a datetime representing the end of the week.

Returns a datetime representing the end of the year.

Returns true if both datetimes are equal.

Returns an {year, week} representing the ISO week number for the specified date.

Link to this section Functions

Link to this macro

after?(datetime1, datetime2)

(macro)

Returns true if datetime1 occurs after datetime2.

Examples

iex> Tox.DateTime.after?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.999999Z], "Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000001Z], "Etc/UTC")
...> )
true

iex> Tox.DateTime.after?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43Z], "Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43Z], "Etc/UTC")
...> )
false

iex> Tox.DateTime.after?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000001Z],"Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.999999Z],"Etc/UTC")
...> )
false

# with time zone Europe/London (UTC+1) and Europe/Berlin (UTC+2)
iex> Tox.DateTime.after?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000999], "Europe/Berlin"),
...>   DateTime.from_naive!(~N[2020-06-14 14:01:43.000001], "Europe/London")
...> )
true
Link to this macro

after_or_equal?(datetime1, datetime2)

(macro)

Returns true if datetime1 occurs after datetime2 or both datetimes are equal.

Examples

iex> Tox.DateTime.after_or_equal?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.999999Z],"Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000001Z],"Etc/UTC")
...> )
true

iex> Tox.DateTime.after_or_equal?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43Z],"Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43Z],"Etc/UTC" )
...> )
true

iex> Tox.DateTime.after_or_equal?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000001Z],"Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.999999Z],"Etc/UTC")
...> )
false

# with time zone Europe/London (UTC+1) and Europe/Berlin (UTC+2)
iex> Tox.DateTime.after_or_equal?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000999], "Europe/Berlin"),
...>   DateTime.from_naive!(~N[2020-06-14 14:01:43.000001], "Europe/London")
...> )
true
Link to this macro

before?(datetime1, datetime2)

(macro)

Returns true if datetime1 occurs before datetime2.

Examples

iex> Tox.DateTime.before?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000001Z],"Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.999999Z],"Etc/UTC")
...> )
true

iex> Tox.DateTime.before?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43Z],"Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43Z],"Etc/UTC")
...> )
false

iex> Tox.DateTime.before?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.999999Z],"Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000001Z],"Etc/UTC")
...> )
false

# with time zone Europe/London (UTC+1) and Europe/Berlin (UTC+2)
iex> Tox.DateTime.before?(
...>   DateTime.from_naive!(~N[2020-06-14 14:01:43.000001], "Europe/London"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000999], "Europe/Berlin")
...> )
true
Link to this macro

before_or_equal?(datetime1, datetime2)

(macro)

Returns true if datetime1 occurs before datetime2 or both datetimes are equal.

Examples

iex> Tox.DateTime.before_or_equal?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000001Z],"Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.999999Z],"Etc/UTC")
...> )
true

iex> Tox.DateTime.before_or_equal?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43Z],"Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43Z],"Etc/UTC")
...> )
true

iex> Tox.DateTime.before_or_equal?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.999999Z],"Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000001Z],"Etc/UTC")
...> )
false

# with time zone Europe/London (UTC+1) and Europe/Berlin (UTC+2)
iex> Tox.DateTime.before_or_equal?(
...>   DateTime.from_naive!(~N[2020-06-14 14:01:43.000000], "Europe/London"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.999999], "Europe/Berlin")
...> )
true
Link to this function

beginning_of_day(map, time_zone_database \\ Calendar.get_time_zone_database())

Specs

Returns a datetime representing the start of the day.

Examples

iex> ~N[2020-03-29 12:00:00]
...> |> DateTime.from_naive!("Europe/Berlin")
...> |> Tox.DateTime.beginning_of_day()
#DateTime<2020-03-29 00:00:00+01:00 CET Europe/Berlin>

On a day starting with a gap

iex> ~N[2011-04-03 12:00:00]
iex> |> DateTime.from_naive!("Africa/El_Aaiun")
iex> |> Tox.DateTime.beginning_of_day()
#DateTime<2011-04-03 01:00:00+01:00 +01 Africa/El_Aaiun>

On a day starting with an ambiguous period

iex> datetime = DateTime.from_naive!(~N[2020-10-25 12:00:00], "America/Scoresbysund")
#DateTime<2020-10-25 12:00:00-01:00 -01 America/Scoresbysund>
iex> Tox.DateTime.beginning_of_day(datetime)
#DateTime<2020-10-25 00:00:00+00:00 +00 America/Scoresbysund>
Link to this function

beginning_of_month(datetime, time_zone_database \\ Calendar.get_time_zone_database())

Specs

Returns datetime representing the start of the month.

Examples

iex> ~N[2020-11-11 11:11:11]
iex> |> DateTime.from_naive!("Europe/Berlin")
iex> |> Tox.DateTime.beginning_of_month()
#DateTime<2020-11-01 00:00:00+01:00 CET Europe/Berlin>

iex> ~N[1969-01-11 12:00:00]
iex> |> DateTime.from_naive!("Antarctica/Casey")
iex> |> Tox.DateTime.beginning_of_month()
#DateTime<1969-01-01 08:00:00+08:00 +08 Antarctica/Casey>
Link to this function

beginning_of_week(datetime, time_zone_database \\ Calendar.get_time_zone_database())

Specs

Returns a datetime representing the start of the week.

Examples

iex> ~N[2020-07-22 11:11:11]
iex> |> DateTime.from_naive!("Europe/Berlin")
iex> |> Tox.DateTime.beginning_of_week()
#DateTime<2020-07-20 00:00:00+02:00 CEST Europe/Berlin>
Link to this function

beginning_of_year(datetime, time_zone_database \\ Calendar.get_time_zone_database())

Specs

Returns datetime representing the start of the year.

Examples

iex> ~N[2020-11-11 11:11:11]
iex> |> DateTime.from_naive!("Europe/Berlin")
iex> |> Tox.DateTime.beginning_of_year()
#DateTime<2020-01-01 00:00:00+01:00 CET Europe/Berlin>

iex> ~N[1969-11-11 12:00:00]
iex> |> DateTime.from_naive!("Antarctica/Casey")
iex> |> Tox.DateTime.beginning_of_year()
#DateTime<1969-01-01 08:00:00+08:00 +08 Antarctica/Casey>
Link to this function

between?(datetime, from, to, boundaries \\ :right_open)

Specs

Returns a boolean indicating whether datetime occurs between from and to. The optional boundaries specifies whether from and to are included or not. The possible value for boundaries are:

  • :open: from and to are excluded
  • :closed: from and to are included
  • :left_open: from is excluded and to is included
  • :right_open: from is included and to is excluded

Examples

iex> from     = DateTime.from_naive!(~N[2020-04-05 12:30:00], "Asia/Omsk")
iex> to       = DateTime.from_naive!(~N[2020-04-15 12:30:00], "Asia/Omsk")
iex> datetime = DateTime.from_naive!(~N[2020-04-01 12:30:00], "Asia/Omsk")
iex> Tox.DateTime.between?(datetime, from, to)
false
iex> datetime = DateTime.from_naive!(~N[2020-04-11 12:30:00], "Asia/Omsk")
iex> Tox.DateTime.between?(datetime, from, to)
true
iex> datetime = DateTime.from_naive!(~N[2020-04-21 12:30:00], "Asia/Omsk")
iex> Tox.DateTime.between?(datetime, from, to)
false
iex> Tox.DateTime.between?(from, from, to)
true
iex> Tox.DateTime.between?(to, from, to)
false
iex> Tox.DateTime.between?(from, from, to, :open)
false
iex> Tox.DateTime.between?(to, from, to, :open)
false
iex> Tox.DateTime.between?(from, from, to, :closed)
true
iex> Tox.DateTime.between?(to, from, to, :closed)
true
iex> Tox.DateTime.between?(from, from, to, :left_open)
false
iex> Tox.DateTime.between?(to, from, to, :left_open)
true
iex> Tox.DateTime.between?(datetime, to, from)
** (ArgumentError) from is equal or greater as to
Link to this function

end_of_day(datetime, time_zone_database \\ Calendar.get_time_zone_database())

Specs

Returns datetime representing the end of the day.

Examples

iex> ~N[2020-03-29 01:00:00]
...> |> DateTime.from_naive!("Europe/Berlin")
...> |> Tox.DateTime.end_of_day()
#DateTime<2020-03-29 23:59:59.999999+02:00 CEST Europe/Berlin>

On a day ending with a gap.

iex> ~N[1916-06-14 12:00:00]
...> |> DateTime.from_naive!("Africa/Algiers")
...> |> Tox.DateTime.end_of_day()
#DateTime<1916-06-14 22:59:59.999999+00:00 WET Africa/Algiers>
Link to this function

end_of_month(datetime, time_zone_database \\ Calendar.get_time_zone_database())

Specs

Returns a datetime} representing the end of the month.

Examples

iex> ~N[2020-11-11 11:11:11]
...> |> DateTime.from_naive!("Europe/Amsterdam")
...> |> Tox.DateTime.end_of_month()
#DateTime<2020-11-30 23:59:59.999999+01:00 CET Europe/Amsterdam>
Link to this function

end_of_week(datetime, time_zone_database \\ Calendar.get_time_zone_database())

Specs

Returns a datetime representing the end of the week.

Examples

iex> ~N[2020-07-22 11:11:11]
...> |> DateTime.from_naive!("Europe/Berlin")
...> |> Tox.DateTime.end_of_week()
#DateTime<2020-07-26 23:59:59.999999+02:00 CEST Europe/Berlin>
Link to this function

end_of_year(datetime, time_zone_database \\ Calendar.get_time_zone_database())

Specs

Returns a datetime representing the end of the year.

Examples

iex> ~N[2020-03-29 01:00:00]
iex> |> DateTime.from_naive!("Europe/Berlin")
iex> |> Tox.DateTime.end_of_year()
#DateTime<2020-12-31 23:59:59.999999+01:00 CET Europe/Berlin>

With the Ethiopic calendar.

iex> datetime =
...>   ~N[2020-10-26 02:30:00]
...>   |> DateTime.from_naive!("Africa/Nairobi")
...>   |> DateTime.convert!(Cldr.Calendar.Ethiopic)
...>
...> to_string(datetime)
"2013-02-16 02:30:00+03:00 EAT Africa/Nairobi"
iex> datetime |> Tox.DateTime.end_of_year() |> to_string()
"2013-13-05 23:59:59.999999+03:00 EAT Africa/Nairobi"
Link to this macro

equal?(datetime1, datetime2)

(macro)

Returns true if both datetimes are equal.

Examples

iex> Tox.DateTime.equal?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.999999Z],"Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000001Z],"Etc/UTC")
...> )
false

iex> Tox.DateTime.equal?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43Z],"Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43Z],"Etc/UTC")
...> )
true

iex> Tox.DateTime.equal?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000001Z],"Etc/UTC"),
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.999999Z],"Etc/UTC")
...> )
false

# with time zone Europe/London (UTC+1) and Europe/Berlin (UTC+2)
iex> Tox.DateTime.equal?(
...>   DateTime.from_naive!(~N[2020-06-14 15:01:43.000999], "Europe/Berlin"),
...>   DateTime.from_naive!(~N[2020-06-14 14:01:43.000999], "Europe/London")
...> )
true
Link to this function

shift(datetime, durations, time_zone_database \\ Calendar.get_time_zone_database())

Specs

Shifts the datetime by the given duration.

The durations is a keyword list of one or more durations of the type Tox.duration e.g. [year: 1, day: 5, minute: 500]. All values will be shifted from the largest to the smallest unit.

Examples

iex> datetime = DateTime.from_naive!(~N[1980-11-01 00:00:00], "Europe/Oslo")
iex> Tox.DateTime.shift(datetime, year: 2)
#DateTime<1982-11-01 00:00:00+01:00 CET Europe/Oslo>
iex> Tox.DateTime.shift(datetime, year: -2, month: 1, hour: 48)
#DateTime<1978-12-03 00:00:00+01:00 CET Europe/Oslo>
iex> Tox.DateTime.shift(datetime, hour: 10, minute: 10, second: 10)
#DateTime<1980-11-01 10:10:10+01:00 CET Europe/Oslo>

Adding a month at the end of the month can update the day too.

iex> datetime = DateTime.from_naive!(~N[2000-01-31 00:00:00], "Europe/Oslo")
iex> Tox.DateTime.shift(datetime, month: 1)
#DateTime<2000-02-29 00:00:00+01:00 CET Europe/Oslo>

For that reason it is important to know that all values will be shifted from the largest to the smallest unit.

iex> datetime = DateTime.from_naive!(~N[2000-01-30 00:00:00], "Europe/Oslo")
iex> Tox.DateTime.shift(datetime, month: 1, day: 1)
#DateTime<2000-03-01 00:00:00+01:00 CET Europe/Oslo>
iex> datetime |> Tox.DateTime.shift(month: 1) |> Tox.DateTime.shift(day: 1)
#DateTime<2000-03-01 00:00:00+01:00 CET Europe/Oslo>
iex> datetime |> Tox.DateTime.shift(day: 1) |> Tox.DateTime.shift(month: 1)
#DateTime<2000-02-29 00:00:00+01:00 CET Europe/Oslo>

Treatment of time gaps. Usually, a transition to a daily-saving-time causing a time gap. For example, in the time-zone Europe/Berlin, the clocks are advanced by one hour on the last Sunday in March at 02:00. Therefore there is a gap between 02:00 and 03:00. The shift/3 function will adjust this by adding or subtracting the difference from the calculated date.

# adding a day
iex> datetime = DateTime.from_naive!(~N[2020-03-28 02:30:00], "Europe/Berlin")
iex> result = Tox.DateTime.shift(datetime, day: 1)
#DateTime<2020-03-29 03:30:00+02:00 CEST Europe/Berlin>
iex> DateTime.diff(result, datetime) == 24 * 60 * 60
true
iex> Tox.DateTime.shift(result, day: -1)
#DateTime<2020-03-28 03:30:00+01:00 CET Europe/Berlin>

# subtracting a day
iex> datetime = DateTime.from_naive!(~N[2020-03-30 02:30:00], "Europe/Berlin")
iex> result = Tox.DateTime.shift(datetime, day: -1)
#DateTime<2020-03-29 01:30:00+01:00 CET Europe/Berlin>
iex> DateTime.diff(datetime, result) == 24 * 60 * 60
true
iex> Tox.DateTime.shift(result, day: 1)
#DateTime<2020-03-30 01:30:00+02:00 CEST Europe/Berlin>

Treatment of ambiguous times. Usually, a transition from daily-saving-time causing an ambiguous period. For example, in the time-zone Europe/Berlin, the clocks are set back one hour on the last Sunday in October. Therefore the period from 02:00 to 03:00 exists twice on this day. The shift/3 function will adjust this by checking if the original datetime later or earlier.

# adding a day
iex> datetime = DateTime.from_naive!(~N[2020-10-24 02:30:00], "Europe/Berlin")
iex> result = Tox.DateTime.shift(datetime, day: 1)
#DateTime<2020-10-25 02:30:00+02:00 CEST Europe/Berlin>
iex> DateTime.diff(result, datetime) == 24 * 60 * 60
true

# subtracting a day
iex> datetime = DateTime.from_naive!(~N[2020-10-26 02:30:00], "Europe/Berlin")
iex> result = Tox.DateTime.shift(datetime, day: -1)
#DateTime<2020-10-25 02:30:00+01:00 CET Europe/Berlin>
iex> DateTime.diff(datetime, result) == 24 * 60 * 60
true

Using shift/3 with a different calendar.

iex> datetime =
...>   ~N[2020-10-26 02:30:00]
...>   |> DateTime.from_naive!("Africa/Nairobi")
...>   |> DateTime.convert!(Cldr.Calendar.Ethiopic)
...>
...> to_string(datetime)
"2013-02-16 02:30:00+03:00 EAT Africa/Nairobi"
iex> datetime |> Tox.DateTime.shift(month: 13) |> to_string()
"2014-02-16 02:30:00+03:00 EAT Africa/Nairobi"

Specs

Returns an {year, week} representing the ISO week number for the specified date.

This function is just defined for datetimes with Calendar.ISO.

Example

iex> ~N[2017-01-01 01:00:00]
...> |> DateTime.from_naive!("Europe/Berlin")
...> |> Tox.DateTime.week()
{2016, 52}

iex> ~N[2020-01-01 01:00:00]
...> |> DateTime.from_naive!("Europe/Berlin")
...> |> Tox.DateTime.week()
{2020, 1}

iex> ~N[2019-12-31 01:00:00]
...> |> DateTime.from_naive!("Europe/Berlin")
...> |> Tox.DateTime.week()
{2020, 1}

iex> ~N[2020-06-04 11:12:13]
...> |> DateTime.from_naive!("Etc/UTC")
...> |> DateTime.convert(Cldr.Calendar.Coptic)
...> |> Tox.DateTime.week()
** (FunctionClauseError) no function clause matching in Tox.DateTime.week/1