Packages
livebook
0.17.1
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.6
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.3
0.17.2
0.17.1
0.17.0
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.14.0-rc.1
0.14.0-rc.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.2
0.1.1
0.1.0
Automate code & data workflows with interactive notebooks
Current section
Files
Jump to
Current section
Files
lib/livebook/utils/time.ex
defmodule Livebook.Utils.Time do
# A simplified version of https://gist.github.com/tlemens/88e9b08f62150ba6082f478a4a03ac52
@doc """
Formats the given point in time relatively to present.
## Examples
To deal with clock-drifts when receiving timestamps from the server, we accept future times:
iex> Livebook.Utils.Time.time_ago_in_words(~N[2100-06-20 18:15:00])
"less than 5 seconds"
"""
@spec time_ago_in_words(NaiveDateTime.t()) :: String.t()
def time_ago_in_words(naive_date_time) when is_struct(naive_date_time, NaiveDateTime) do
distance_of_time_in_words(naive_date_time, NaiveDateTime.utc_now())
end
@doc """
Formats time distance between `from_ndt` and `to_ndt` as a
human-readable string.
## Examples
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-20 18:15:04])
"less than 5 seconds"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-20 18:15:09])
"less than 10 seconds"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-20 18:15:19])
"less than 20 seconds"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-20 18:15:20])
"half a minute"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-20 18:15:39])
"half a minute"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-20 18:15:40])
"less than a minute"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-20 18:15:59])
"less than a minute"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-20 18:16:00])
"1 minute"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-20 18:16:29])
"1 minute"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-20 18:16:30])
"2 minutes"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-20 18:58:30])
"44 minutes"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-20 18:59:30])
"about 1 hour"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-20 19:59:30])
"about 2 hours"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-21 18:14:00])
"about 24 hours"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-21 18:15:00])
"1 day"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-06-22 18:15:00])
"2 days"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2020-07-22 18:15:00])
"about 1 month"
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:00], ~N[2021-08-22 18:15:00])
"about 14 months"
To deal with clock-drifts when receiving timestamps from another machine, we accept future times:
iex> Livebook.Utils.Time.distance_of_time_in_words(~N[2020-06-20 18:15:06], ~N[2020-06-20 18:15:04])
"less than 5 seconds"
"""
@spec distance_of_time_in_words(NaiveDateTime.t(), NaiveDateTime.t()) :: String.t()
def distance_of_time_in_words(from_ndt, to_ndt)
when is_struct(from_ndt, NaiveDateTime) and is_struct(to_ndt, NaiveDateTime) do
duration_seconds = NaiveDateTime.diff(to_ndt, from_ndt)
{:seconds, duration_seconds}
|> maybe_convert_to_minutes()
|> duration_in_words()
end
defp maybe_convert_to_minutes({:seconds, seconds}) when seconds > 59 do
{:minutes, round(seconds / 60)}
end
defp maybe_convert_to_minutes(duration), do: duration
defp duration_in_words({:seconds, seconds}) when seconds <= 4 do
"less than 5 seconds"
end
defp duration_in_words({:seconds, seconds}) when seconds in 5..9 do
"less than 10 seconds"
end
defp duration_in_words({:seconds, seconds}) when seconds in 10..19 do
"less than 20 seconds"
end
defp duration_in_words({:seconds, seconds}) when seconds in 20..39 do
"half a minute"
end
defp duration_in_words({:seconds, seconds}) when seconds in 40..59 do
"less than a minute"
end
defp duration_in_words({:minutes, minutes}) when minutes == 1 do
"1 minute"
end
defp duration_in_words({:minutes, minutes}) when minutes in 2..44 do
"#{minutes} minutes"
end
defp duration_in_words({:minutes, minutes}) when minutes in 45..89 do
"about 1 hour"
end
# 90 mins up to 24 hours
defp duration_in_words({:minutes, minutes}) when minutes in 90..1439 do
"about #{round(minutes / 60)} hours"
end
# 24 hours up to 42 hours
defp duration_in_words({:minutes, minutes}) when minutes in 1440..2519 do
"1 day"
end
# 42 hours up to 30 days
defp duration_in_words({:minutes, minutes}) when minutes in 2520..43_199 do
"#{round(minutes / 1440)} days"
end
# 30 days up to 45 days
defp duration_in_words({:minutes, minutes}) when minutes in 43_200..64_799 do
"about 1 month"
end
# 45 days up to 60 days
defp duration_in_words({:minutes, minutes}) when minutes in 64_800..86_399 do
"about 2 months"
end
defp duration_in_words({:minutes, minutes}) do
"about #{round(minutes / 43_200)} months"
end
end