Packages
moar
1.14.0
5.0.0
4.3.0
4.2.0
4.1.0
4.0.0
3.2.0
3.1.0
3.0.0
2.7.0
2.6.0
2.5.0
2.4.2
2.4.1
2.4.0
2.3.0
2.2.0
2.1.0
2.0.1
2.0.0
1.64.0
1.63.1
1.63.0
1.62.0
1.61.2
1.61.1
1.61.0
1.60.0
1.59.2
1.59.1
1.59.0
1.58.0
1.57.0
1.56.2
1.56.1
1.56.0
1.55.0
1.54.0
1.53.0
1.52.1
1.52.0
1.51.0
1.50.0
1.49.0
1.48.0
1.47.0
1.46.0
1.45.1
1.45.0
1.44.0
1.43.0
1.42.0
1.41.0
1.40.0
1.39.0
1.38.0
1.37.0
1.36.0
1.35.0
1.34.0
1.33.0
1.32.0
1.31.0
1.30.0
1.29.0
1.28.0
1.27.0
1.26.0
1.25.0
1.24.1
1.24.0
1.23.0
1.22.0
1.21.0
1.20.0
1.19.3
1.19.2
1.19.1
1.19.0
1.18.1
1.18.0
1.17.0
1.16.0
1.15.0
1.14.0
1.13.1
1.13.0
1.12.0
1.11.0
1.10.0
1.9.0
1.8.0
1.7.0
1.6.0
1.5.0
1.4.0
1.3.0
1.2.0
1.1.0
1.0.0
0.1.0
A dependency-free utility library containing 100+ useful functions.
Current section
Files
Jump to
Current section
Files
lib/datetime.ex
defmodule Moar.DateTime do
# @related [test](/test/datetime_test.exs)
@moduledoc """
DateTime-related functions. See also `Moar.NaiveDateTime`.
"""
@doc """
Like `DateTime.add/2` but takes a `Moar.Duration`.
See also `Moar.NaiveDateTime.add/2`.
> #### Note {: .info}
>
> This function is naive and intentionally doesn't account for real-world calendars and all of their complexity,
> such as leap years, leap days, daylight saving time, past and future calendar oddities, etc.
>
> As ["Falsehoods programmers believe about time"](https://gist.github.com/timvisee/fcda9bbdff88d45cc9061606b4b923ca)
> says, "If you think you understand everything about time, you're probably doing it wrong."
>
> See [`Cldr.Calendar.plus/2`](https://hexdocs.pm/ex_cldr_calendars/Cldr.Calendar.html#plus/2) for one example
> of a function that is far more likely to be correct.
```elixir
iex> start = ~U[2022-01-01T00:00:00Z]
iex> Moar.DateTime.add(start, {3, :minute})
~U[2022-01-01T00:03:00Z]
```
"""
@spec add(DateTime.t(), Moar.Duration.t()) :: DateTime.t()
def add(date_time, duration),
do: DateTime.add(date_time, Moar.Duration.convert(duration, :millisecond), :millisecond)
@doc """
Like `DateTime.from_iso8601/1` but raises if the string cannot be parsed.
```elixir
iex> Moar.DateTime.from_iso8601!("2022-01-01T00:00:00Z")
~U[2022-01-01T00:00:00Z]
iex> Moar.DateTime.from_iso8601!("2022-01-01T00:00:00+0800")
** (ArgumentError) Expected \"2022-01-01T00:00:00+0800\" to have a UTC offset of 0, but was: 28800
iex> Moar.DateTime.from_iso8601!("Next Thursday after lunch")
** (ArgumentError) Invalid ISO8601 format: "Next Thursday after lunch"
```
"""
@spec from_iso8601!(date_time_string :: String.t()) :: DateTime.t()
def from_iso8601!(date_time_string) when is_binary(date_time_string) do
case DateTime.from_iso8601(date_time_string) do
{:ok, date_time, 0} ->
date_time
{:ok, _date_time, other_offset} ->
raise ArgumentError, ~s|Expected "#{date_time_string}" to have a UTC offset of 0, but was: #{other_offset}|
{:error, :invalid_format} ->
raise ArgumentError, ~s|Invalid ISO8601 format: "#{date_time_string}"|
end
end
@doc """
Like `DateTime.to_iso8601/1` but rounds to the nearest second first.
```elixir
iex> Moar.DateTime.to_iso8601_rounded(~U[2022-01-01T01:02:03.456789Z])
"2022-01-01T01:02:03Z"
```
"""
@spec to_iso8601_rounded(date_time :: DateTime.t()) :: String.t()
def to_iso8601_rounded(date), do: date |> DateTime.truncate(:second) |> DateTime.to_iso8601()
end