Packages
moar
1.46.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/naive_datetime.ex
defmodule Moar.NaiveDateTime do
# @related [test](/test/naive_datetime_test.exs)
@moduledoc """
NaiveDateTime-related functions. See also `Moar.DateTime`.
"""
@doc """
Like `NaiveDateTime.add/2` but takes a `Moar.Duration`.
See also `subtract/1` and `Moar.DateTime.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 = ~N[2022-01-01T00:00:00.000]
iex> Moar.NaiveDateTime.add(start, {3, :minute})
~N[2022-01-01T00:03:00.000]
```
"""
@spec add(NaiveDateTime.t(), Moar.Duration.t()) :: NaiveDateTime.t()
def add(date_time, duration),
do: NaiveDateTime.add(date_time, Moar.Duration.convert(duration, :millisecond), :millisecond)
@doc """
Like `NaiveDateTime.from_iso8601/1` but raises if the string cannot be parsed.
```elixir
iex> Moar.NaiveDateTime.from_iso8601!("2022-01-01T00:00:00")
~N[2022-01-01T00:00:00]
iex> Moar.NaiveDateTime.from_iso8601!("2022-01-01T00:00:00+0800")
~N[2022-01-01T00:00:00]
iex> Moar.NaiveDateTime.from_iso8601!("Next Thursday after lunch")
** (ArgumentError) Invalid ISO8601 format: "Next Thursday after lunch"
```
"""
@spec from_iso8601!(date_time_string :: String.t()) :: NaiveDateTime.t()
def from_iso8601!(date_time_string) when is_binary(date_time_string) do
case NaiveDateTime.from_iso8601(date_time_string) do
{:ok, date_time} ->
date_time
{:error, :invalid_format} ->
raise ArgumentError, ~s|Invalid ISO8601 format: "#{date_time_string}"|
end
end
@doc """
Subtracts `duration` from `date_time`.
See also `add/1` and `Moar.DateTime.subtract/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.minus/4`](https://hexdocs.pm/ex_cldr_calendars/Cldr.Calendar.html#minus/4) for one example
> of a function that is far more likely to be correct.
```elixir
iex> start = ~N[2022-01-01T00:03:00.000]
iex> Moar.NaiveDateTime.subtract(start, {3, :minute})
~N[2022-01-01T00:00:00.000]
```
"""
@spec subtract(NaiveDateTime.t(), Moar.Duration.t()) :: NaiveDateTime.t()
def subtract(date_time, {time, unit} = _duration),
do: NaiveDateTime.add(date_time, Moar.Duration.convert({-1 * time, unit}, :millisecond), :millisecond)
@doc """
Like `NaiveDateTime.to_iso8601/1` but rounds to the nearest second first.
```elixir
iex> Moar.NaiveDateTime.to_iso8601_rounded(~N[2022-01-01T01:02:03.456789])
"2022-01-01T01:02:03"
```
"""
@spec to_iso8601_rounded(date_time :: NaiveDateTime.t()) :: String.t()
def to_iso8601_rounded(date), do: date |> NaiveDateTime.truncate(:second) |> NaiveDateTime.to_iso8601()
@doc """
Returns the current UTC time plus or minus the given duration.
```elixir
iex> Moar.NaiveDateTime.utc_now(plus: {10500, :millisecond})
...> |> Moar.Duration.format([:approx, :from_now])
"10 seconds from now"
iex> Moar.NaiveDateTime.utc_now(minus: {10, :second})
...> |> Moar.Duration.format([:approx, :ago])
"10 seconds ago"
```
"""
@spec utc_now([plus: Moar.Duration.t()] | [minus: Moar.Duration.t()]) :: NaiveDateTime.t()
def utc_now(plus: duration), do: NaiveDateTime.utc_now() |> add(duration)
def utc_now(minus: duration), do: NaiveDateTime.utc_now() |> subtract(duration)
end