tempo/time
Functions to use with the Time
type in Tempo. The time values are wall
time values unless explicitly stated otherwise.
Example
import tempo/time
pub fn is_past_5pm() {
time.now_utc()
|> time.is_later(than: time.literal("17:00"))
}
import tempo/time
pub fn get_enthusiastic_time() {
time.now_local()
|> time.format(
"[The hour is:] HH, [wow! And even better the minute is:] mm!"
)
// -> "The hour is: 13, wow! And even better the minute is: 42!"
}
import tempo/time
pub fn run_task() {
let resuult = do_long_task()
let end_time = time.now_unique()
#(end_time, resuult)
}
// -> These tasks are now sortable by end time
Types
Functions
pub fn add(a: Time, duration b: Duration) -> Time
Adds a duration to a time.
Example
time.literal("08:42:53")
|> time.add(duration.mintues(36))
// -> time.literal("09:18:53")
pub fn compare(a: Time, to b: Time) -> Order
Compares two time values.
Example
time.literal("13:42:11")
|> time.compare(to: time.literal("13:42:11"))
// -> order.Eq
time.literal("15:32:01")
|> time.compare(to: time.literal("13:42:11"))
// -> order.Gt
time.literal("13:10:11")
|> time.compare(to: time.literal("13:42:11"))
// -> order.Lt
pub fn difference(from a: Time, to b: Time) -> Duration
Gets the difference between two times as a duration. Always prefer using
duration.start_monotonic
and duration.stop_monotonic
to record live
time passing, as it is more precise.
Example
time.literal("23:42:11.435")
|> time.difference(from: time.literal("23:42:09.743"))
|> duration.as_milliseconds
// -> 1692
time.literal("13:30:11")
|> time.difference(from: time.literal("13:55:13"))
|> duration.as_minutes
// -> -25
pub fn difference_abs(a: Time, from b: Time) -> Duration
Gets the absolute difference between two times as a duration.
Example
time.literal("23:42:11.435")
|> time.difference(from: time.literal("23:42:09.743"))
|> duration.as_milliseconds
// -> 1692
time.literal("13:30:11")
|> time.difference(from: time.literal("13:55:13"))
|> duration.as_minutes
// -> 25
pub fn format(time: Time, in fmt: String) -> String
Formats a time value using the provided format string. Implements the same formatting directives as the great Day.js library: https://day.js.org/docs/en/display/format.
Values can be escaped by putting brackets around them, like “[Hello!] HH”.
Available directives: H (hour), HH (two-digit hour), h (12-hour clock hour), hh (two-digit 12-hour clock hour), m (minute), mm (two-digit minute), s (second), ss (two-digit second), SSS (millisecond), SSSS (microsecond), SSSSS (nanosecond), A (AM/PM), a (am/pm).
Example
time.literal("13:42:11.314")
|> time.format("h:mm A")
// -> "1:42 PM"
time.literal("09:02:01.014920202")
|> time.format("HH:mm:ss SSS SSSS SSSSS")
// -> "09:02:01 014 014920 014920202"
naive_datetime.literal("13:02:01")
|> naive_datetime.format("H HH h hh m mm s ss a A [An ant]")
// -------------------> "13 13 1 01 2 02 1 01 pm PM An ant"
pub fn from_duration(duration: Duration) -> Time
Converts a duration to the equivalent time of day, assuming the duration epoch is “00:00:00”. Durations longer than 24 hours will be wrapped to fit within a 24 hour representation.
Example
duration.seconds(58)
|> time.from_duration
|> time.to_second_precision
|> time.to_string
// -> "00:00:58"
duration.minutes(17)
|> time.from_duration
|> time.to_string
// -> "00:17:00.000000000"
duration.hours(25)
|> time.from_duration
|> time.to_string
// -> "01:00:00.000000000"
duration.nanoseconds(-3_000_000_000)
|> time.from_duration
|> time.to_string
// -> "23:59:57.000000000"
pub fn from_string(time: String) -> Result(Time, TimeParseError)
Converts a string to a time value. Accepted formats are hh:mm:ss.s
,
hhmmss.s
, hh:mm:ss
, hhmmss
, hh:mm
, or hhmm
.
Example
time.from_string("00:00:00.000000300")
// -> Ok(time.literal("00:00:00.000000300"))
time.from_string("34:54:16")
// -> Error(tempo.TimeOutOfBounds)
pub fn from_tuple(
time: #(Int, Int, Int),
) -> Result(Time, TimeOutOfBoundsError)
Converts a tuple of hours, minutes, and seconds to a time value. Useful for using with another time library.
Example
#(13, 42, 11)
|> time.from_tuple
// -> time.literal("13:42:11")
pub fn from_tuple_nanosecond(
time: #(Int, Int, Int, Int),
) -> Result(Time, TimeOutOfBoundsError)
Converts a tuple of hours, minutes, seconds, and nanoseconds to a time value. Useful for using with another time library.
Example
#(13, 42, 11, 872000000)
|> time.from_tuple_nanosecond
|> time.to_milli_precision
// -> time.literal("13:42:11.872")
pub fn get_hour(time: Time) -> Int
Gets the hour value of a time.
Example
time.literal("13:42:11")
|> time.get_hour
// -> 13
pub fn get_minute(time: Time) -> Int
Gets the minute value of a time.
Example
time.literal("13:42:11")
|> time.get_minute
// -> 42
pub fn get_nanosecond(time: Time) -> Int
Gets the nanosecond value of a time.
Example
time.literal("13:42:11.123")
|> time.get_nanosecond
// -> 123000000
pub fn get_second(time: Time) -> Int
Gets the second value of a time.
Example
time.literal("13:42:11")
|> time.get_second
// -> 11
pub fn is_between(
time: Time,
start: Boundary,
and end: Boundary,
) -> Bool
Checks if a time is between two boundaries.
Example
time.literal("13:42:11")
|> time.is_between(
Boundary(time.literal("05:00:00"), inclusive: True),
and: Boundary(time.literal("15:00:00"), inclusive: False),
)
// -> True
pub fn is_earlier(a: Time, than b: Time) -> Bool
Checks if the first time is earlier than the second time.
Example
time.literal("13:42:11")
|> time.is_earlier(than: time.literal("13:42:12"))
// -> True
time.literal("13:42:11")
|> time.is_earlier(than: time.literal("13:42:11"))
// -> False
time.literal("13:22:15")
|> time.is_earlier(than: time.literal("07:42:11"))
// -> False
pub fn is_earlier_or_equal(a: Time, to b: Time) -> Bool
Checks if the first time is earlier or equal to the second time.
Example
time.literal("13:42:11")
|> time.is_earlier_or_equal(to: time.literal("13:42:12"))
// -> True
time.literal("13:42:11")
|> time.is_earlier_or_equal(to: time.literal("13:42:11.000"))
// -> True
time.literal("13:22:15")
|> time.is_earlier_or_equal(to: time.literal("07:42:12"))
// -> False
pub fn is_equal(a: Time, to b: Time) -> Bool
Checks if the first time is equal to the second time.
Example
time.literal("13:42:11.000")
|> time.is_equal(to: time.literal("13:42:11"))
// -> True
time.literal("13:42:11.002")
|> time.is_equal(to: time.literal("13:42:11"))
// -> False
pub fn is_later(a: Time, than b: Time) -> Bool
Checks if the first time is later than the second time.
Example
time.literal("13:22:15")
|> time.is_later(than: time.literal("07:42:11"))
// -> True
time.literal("13:42:11")
|> time.is_later(than: time.literal("13:42:12"))
// -> False
time.literal("13:42:11")
|> time.is_later(than: time.literal("13:42:11"))
// -> False
pub fn is_later_or_equal(a: Time, to b: Time) -> Bool
Checks if the first time is earlier or equal to the second time.
Example
time.literal("13:22:15")
|> time.is_later_or_equal(to: time.literal("07:42:12"))
// -> True
```gleam
time.literal("13:42")
|> time.is_later_or_equal(to: time.literal("13:42:00.000"))
// -> True
time.literal("13:42:11")
|> time.is_later_or_equal(to: time.literal("13:42:12"))
// -> False
pub fn is_outside(
time: Time,
start: Boundary,
and end: Boundary,
) -> Bool
Checks if a time is outside of two boundaries.
Example
time.literal("13:42:11")
|> time.is_outside(
time.Boundary(time.literal("05:00:00"), inclusive: True),
and: time.Boundary(time.literal("15:00:00"), inclusive: False),
)
// -> False
pub fn left_in_day(time: Time) -> Time
Converts a time to the equivalent time left in the day.
Example
time.literal("23:59:03") |> time.left_in_day
// -> time.literal("00:00:57")
time.literal("08:05:20") |> time.left_in_day
// -> time.literal("15:54:40")
pub fn literal(time: String) -> Time
Creates a new time value from a string literal, but will panic if
the string is invalid. Accepted formats are
hh:mm:ss.s
, hhmmss.s
, hh:mm:ss
, hhmmss
, hh:mm
, or hhmm
.
Useful for declaring time literals that you know are valid within your program.
Example
case
time.now_local()
|> time.is_later(than: time.literal("11:50:00"))
{
True -> "We are late!"
False -> "No rush :)"
}
pub fn new(
hour: Int,
minute: Int,
second: Int,
) -> Result(Time, TimeOutOfBoundsError)
Creates a new time value with second precision.
Example
time.new(13, 42, 11)
// -> Ok(time.literal("13:42:11"))
time.new(53, 42, 61)
// -> Error(tempo.TimeOutOfBounds)
pub fn new_micro(
hour: Int,
minute: Int,
second: Int,
microsecond: Int,
) -> Result(Time, TimeOutOfBoundsError)
Creates a new time value with microsecond precision.
Example
time.new_micro(13, 42, 11, 20)
// -> Ok(time.literal("13:42:11.000020"))
time.new_micro(13, 42, 11, 200_000)
// -> Ok(time.literal("13:42:11.200000"))
time.new_micro(13, 42, 11, 7_500_000)
// -> Error(tempo.TimeOutOfBounds)
pub fn new_milli(
hour: Int,
minute: Int,
second: Int,
millisecond: Int,
) -> Result(Time, TimeOutOfBoundsError)
Creates a new time value with millisecond precision.
Example
time.new_milli(13, 42, 11, 20)
// -> Ok(time.literal("13:42:11.020"))
time.new_milli(13, 42, 11, 200)
// -> Ok(time.literal("13:42:11.200"))
time.new_milli(13, 42, 11, 7_500)
// -> Error(tempo.TimeOutOfBounds)
pub fn new_nano(
hour: Int,
minute: Int,
second: Int,
nanosecond: Int,
) -> Result(Time, TimeOutOfBoundsError)
Creates a new time value with nanosecond precision.
Example
time.new_nano(13, 42, 11, 20)
// -> Ok(time.literal("13:42:11.000000020"))
time.new_nano(13, 42, 11, 200_000_000)
// -> Ok(time.literal("13:42:11.200000000"))
time.new_nano(13, 42, 11, 7_500_000_000)
// -> Error(tempo.TimeOutOfBounds)
pub fn now_local() -> Time
Gets the local wall time of the host. Always prefer using
duration.start_monotonic
to record time passing and time.now_unique
to sort events by time.
Example
case
time.now_local()
|> time.is_later(than: time.literal("11:50:00"))
{
True -> "We are late!"
False -> "No rush :)"
}
pub fn now_monotonic() -> Int
Gets the monotonic time of the host. Monotonic time
is useful for timing events; now_utc
and now_local
should not be
used for timing events. The duration
module has nicer functions to use
for timing events and should be preferred over this function.
Example
time.now_monotonic()
// -> -576_460_750_802_442_634
pub fn now_unique() -> Int
Gets a positive unique integer based on the monotonic time of the Erlang VM on the Erlang target. Returns the a value that starts at 1 and increments by 1 with each call on the JavaScript target. This is useful for tagging and then ordering events by time, but should not be assumed to represent wall time.
Example
time.now_unique()
// -> 1
time.now_unique()
// -> 2
pub fn now_utc() -> Time
Gets the UTC wall time of the host. Always prefer using
duration.start_monotonic
to record time passing and time.now_unique
to sort events by time.
Example
case
time.now_utc()
|> time.is_later(than: time.literal("11:50:00"))
{
True -> "We are all late!"
False -> "No rush :)"
}
pub fn parse(
str: String,
in fmt: String,
) -> Result(Time, TimeParseError)
Parses a time string in the provided format. Always prefer using
this over parse_any
. All parsed formats must have an hour and a second.
Values can be escaped by putting brackets around them, like “[Hello!] HH”.
Available directives: H (hour), HH (two-digit hour), h (12-hour clock hour), hh (two-digit 12-hour clock hour), m (minute), mm (two-digit minute), s (second), ss (two-digit second), SSS (millisecond), SSSS (microsecond), SSSSS (nanosecond), A (AM/PM), a (am/pm),
Example
time.parse("2024/06/08, 13:42:11", "YYYY/MM/DD")
// -> Ok(time.literal("13:42:11"))
time.parse("January 13, 2024", "MMMM DD, YYYY")
// -> Error(tempo.ParseMissingTime)
time.parse("Hi! 12 2 am", "[Hi!] h m a")
// -> Ok(time.literal("00:02:00"))
pub fn parse_any(str: String) -> Result(Time, Nil)
Tries to parse a given date string without a known format. It will not parse two digit years and will assume the month always comes before the day in a date. Will leave off any time offset values present.
Example
time.parse_any("2024.06.21 01:32 PM -04:00")
// -> Ok(time.literal("13:32:00"))
time.parse_any("2024.06.21")
// -> Error(tempo.ParseMissingTime)
pub fn since(time: Time, since: Time) -> Duration
Returns a duration representing the time since a given time.
Example
time.literal("23:54:00")
|> time.since(time.literal("13:30:04"))
|> duration.as_hours
// -> 10
time.literal("12:30:54")
|> time.since(time.literal("22:00:00"))
|> duration.as_milliseconds
// -> 0
pub fn subtract(a: Time, duration b: Duration) -> Time
Subtracts a duration from a time.
Example
time.literal("13:42:02")
|> time.subtract(duration.hours(2))
// -> time.literal("11:42:02")
pub fn to_duration(time: Time) -> Duration
Converts a time to duration, assuming the duration epoch is “00:00:00”.
Example
time.literal("00:00:00.000000300")
|> time.to_duration
|> duration.as_nanoseconds
// -> 300
time.literal("00:03:06")
|> time.to_duration
|> duration.as_milliseconds
// -> 186_000
pub fn to_string(time: Time) -> String
Converts a time value to a string in the format hh:mm:ss.s
Example
time.to_string(my_time)
// -> "21:53:03.534"
pub fn to_tuple(time: Time) -> #(Int, Int, Int)
Returns a time value as a tuple of hours, minutes, and seconds. Useful for using with another time library.
Example
time.literal("13:42:11")
|> time.to_tuple
// -> #(13, 42, 11)
pub fn to_tuple_nanosecond(time: Time) -> #(Int, Int, Int, Int)
Returns a time value as a tuple of hours, minutes, seconds, and nanoseconds. Useful for using with another time library.
Example
time.literal("13:42:11.872")
|> time.to_tuple_nanosecond
// -> #(13, 42, 11, 872000000)
pub fn until(time: Time, until: Time) -> Duration
Returns a duration representing the time left until a given time.
Example
time.literal("23:54:00")
|> time.until(time.literal("23:59:04"))
|> duration.as_seconds
// -> 304
time.literal("23:59:03")
|> time.until(time.literal("22:00:00"))
|> duration.as_milliseconds
// -> 0