tempo/datetime
Functions to use with the DateTime
type in Tempo.
Examples
import tempo/datetime
import snag
pub fn main() {
datetime.literal("2024-12-25T06:00:00+05:00")
|> datetime.format("ddd @ h:mm A, Z")
// -> "Fri @ 6:00 AM, +05:00"
datetime.parse("06:21:2024 23:17:07.123Z", "MM:DD:YYYY HH:mm:ss.SSSZ")
|> snag.map_error(datetime.describe_parse_error)
|> result.map(datetime.to_string)
// -> Ok("2024-06-21T23:17:07.123Z")
}
import gleam/list
import tempo/datetime
import tempo/period
pub fn get_every_friday_between(datetime1, datetime2) {
period.new(datetime1, datetime2)
|> period.comprising_dates
|> list.filter(fn(date) {
date |> date.to_day_of_week == date.Fri
})
// -> ["2024-06-21", "2024-06-28", "2024-07-05"]
}
Functions
pub fn add(
datetime: DateTime,
duration duration_to_add: Duration,
) -> DateTime
Adds a duration to a datetime.
Examples
datetime.literal("2024-06-12T23:17:00Z")
|> datetime.add(duration |> tempo.offset_get_minutes(3))
// -> datetime.literal("2024-06-12T23:20:00Z")
pub fn apply_offset(datetime: DateTime) -> NaiveDateTime
Applies the offset of a datetime to the date and time values, resulting in a new naive datetime value that represents the original datetime in UTC time.
Examples
datetime.literal("2024-06-21T05:36:11.195-04:00")
|> datetime.apply_offset
// -> naive_datetime.literal("2024-06-21T09:36:11.195")
pub fn as_period(
start start: DateTime,
end end: DateTime,
) -> Period
Creates a period between two datetimes, where the start and end times are the equivalent UTC times of the provided datetimes. The specified start and end datetimes will be swapped if the start datetime is later than the end datetime.
Examples
datetime.to_period(
start: datetime.literal("2024-06-12T23:17:00Z")
end: datetime.literal("2024-06-16T01:16:12Z"),
)
|> period.as_days
// -> 3
datetime.to_period(
start: datetime.literal("2024-06-12T23:17:00Z")
end: datetime.literal("2024-06-16T01:18:12Z"),
)
|> period.format
// -> "3 days, 2 hours, and 1 minute"
pub fn compare(a: DateTime, to b: DateTime) -> Order
Compares two datetimes.
Examples
datetime.literal("2024-06-21T23:47:00+09:05")
|> datetime.compare(to: datetime.literal("2024-06-21T23:47:00+09:05"))
// -> order.Eq
datetime.literal("2023-05-11T13:30:00-04:00")
|> datetime.compare(to: datetime.literal("2023-05-11T13:15:00Z"))
// -> order.Lt
datetime.literal("2024-06-12T23:47:00+09:05")
|> datetime.compare(to: datetime.literal("2022-04-12T00:00:00"))
// -> order.Gt
pub fn describe_parse_error(error: DateTimeParseError) -> String
Converts a datetime parse error to a human readable error message.
Example
datetime.parse("13:42:11.314-04:00", "YYYY-MM-DDTHH:mm:ss.SSSZ")
|> snag.map_error(with: datetime.describe_parse_error)
// -> snag.error("Invalid date format in datetime: 13:42:11.314-04:00")
pub fn difference(from a: DateTime, to b: DateTime) -> Duration
Returns the difference between two datetimes as a duration between their equivalent UTC times.
Examples
datetime.literal("2024-06-12T23:17:00Z")
|> datetime.difference(
from: datetime.literal("2024-06-16T01:16:12Z"),
)
|> duration.as_days
// -> 3
datetime.literal("2024-06-12T23:17:00Z")
|> datetime.difference(
from: datetime.literal("2024-06-16T01:18:12Z"),
)
|> duration.format
// -> "3 days, 2 hours, and 1 minute"
pub fn drop_offset(datetime: DateTime) -> NaiveDateTime
Drops the time of a datetime, leaving the date and time values unchanged.
Examples
datetime.literal("2024-06-13T13:42:11.195Z")
|> datetime.drop_offset
// -> naive_datetime.literal("2024-06-13T13:42:11")
pub fn drop_time(datetime: DateTime) -> DateTime
Drops the time of a datetime, leaving the date value unchanged.
Examples
datetime.literal("2024-06-18T13:42:11.195Z")
|> datetime.drop_time
// -> naive_datetime.literal("2024-06-18T00:00:00Z")
pub fn format(
datetime: DateTime,
in format: DateTimeFormat,
) -> String
Formats a datetime value into a string using the provided format.
Examples
datetime.literal(tempo.Custom("2024-06-21T13:42:11.314-04:00"))
|> datetime.format("ddd @ h:mm A (z)")
// -> "Fri @ 1:42 PM (-04)"
datetime.literal("2024-06-03T09:02:01-04:00")
|> datetime.format(tempo.Custom("YY YYYY M MM MMM MMMM D DD d dd ddd"))
// -----------:---------------> "24 2024 6 06 Jun June 3 03 1 Mo Mon"
datetime.literal("2024-06-03T09:02:01.014920202-00:00")
|> datetime.format(tempo.Custom("dddd SSS SSSS SSSSS Z ZZ z"))
// -> "Monday 014 014920 014920202 -00:00 -0000 Z"
datetime.literal("2024-06-03T13:02:01-04:00")
|> datetime.format(tempo.Custom("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_dynamic_string(
dynamic_string: Dynamic,
) -> Result(DateTime, List(DecodeError))
Checks if a dynamic value is a valid datetime string, and returns the datetime if it is.
Examples
dynamic.from("2024-06-13T13:42:11.195Z")
|> datetime.from_dynamic_string
// -> Ok(datetime.literal("2024-06-13T13:42:11.195Z"))
dynamic.from("24-06-13,13:42:11.195")
|> datetime.from_dynamic_string
// -> Error([
// dynamic.DecodeError(
// expected: "tempo.DateTime",
// found: "Invalid format: 24-06-13,13:42:11.195",
// path: [],
// ),
// ])
pub fn from_dynamic_unix_micro_utc(
dynamic_ts: Dynamic,
) -> Result(DateTime, List(DecodeError))
Checks if a dynamic value is a valid unix timestamp in microseconds, and returns the datetime if it is.
Examples
dynamic.from(1_718_629_314_334_734)
|> datetime.from_dynamic_unix_micro_utc
// -> Ok(datetime.literal("2024-06-17T13:01:54.334734Z"))
dynamic.from("hello")
|> datetime.from_dynamic_unix_micro_utc
// -> Error([
// dynamic.DecodeError(
// expected: "Int",
// found: "String",
// path: [],
// ),
// ])
pub fn from_dynamic_unix_milli_utc(
dynamic_ts: Dynamic,
) -> Result(DateTime, List(DecodeError))
Checks if a dynamic value is a valid unix timestamp in milliseconds, and returns the datetime if it is.
Examples
dynamic.from(1_718_629_314_334)
|> datetime.from_dynamic_unix_milli_utc
// -> Ok(datetime.literal("2024-06-17T13:01:54.334Z"))
dynamic.from("hello")
|> datetime.from_dynamic_unix_milli_utc
// -> Error([
// dynamic.DecodeError(
// expected: "Int",
// found: "String",
// path: [],
// ),
// ])
pub fn from_dynamic_unix_utc(
dynamic_ts: Dynamic,
) -> Result(DateTime, List(DecodeError))
Checks if a dynamic value is a valid unix timestamp in seconds, and returns the datetime representation if it is.
Examples
dynamic.from(1_718_629_314)
|> datetime.from_dynamic_unix_utc
// -> Ok(datetime.literal("2024-06-17T13:01:54Z"))
dynamic.from("hello")
|> datetime.from_dynamic_unix_utc
// -> Error([
// dynamic.DecodeError(
// expected: "Int",
// found: "String",
// path: [],
// ),
// ])
pub fn from_string(
datetime: String,
) -> Result(DateTime, DateTimeParseError)
Parses a datetime string in the format YYYY-MM-DDThh:mm:ss.sTZD
,
YYYYMMDDThhmmss.sTZD
, YYYY-MM-DD hh:mm:ss.sTZD
,
YYYYMMDD hhmmss.sTZD
, YYYY-MM-DD
, YYYY-M-D
, YYYY/MM/DD
,
YYYY/M/D
, YYYY.MM.DD
, YYYY.M.D
, YYYY_MM_DD
, YYYY_M_D
,
YYYY MM DD
, YYYY M D
, or YYYYMMDD
.
Examples
datetime.from_string("20240613T230400.009+00:00")
// -> datetime.literal("2024-06-13T23:04:00.009Z")
pub fn from_timestamp(timestamp: Timestamp) -> DateTime
Converts a core gleam time timestamp type to a datetime.
pub fn from_unix_micro(unix_ts: Int) -> DateTime
Returns the UTC datetime of a unix timestamp in microseconds.
Examples
datetime.from_unix_micro(1_718_629_314_334_734)
// -> datetime.literal("2024-06-17T13:01:54.334734Z")
pub fn from_unix_milli(unix_ts: Int) -> DateTime
Returns the UTC datetime of a unix timestamp in milliseconds.
Examples
datetime.from_unix_milli(1_718_629_314_334)
// -> datetime.literal("2024-06-17T13:01:54.334Z")
pub fn from_unix_seconds(unix_ts: Int) -> DateTime
Returns the UTC datetime of a unix timestamp.
Examples
datetime.from_unix_seconds(1_718_829_191)
// -> datetime.literal("2024-06-17T12:59:51Z")
pub fn get_calendar_date(datetime: DateTime) -> Date
Gets the core gleam time package calendar date of a datetime.
Examples
datetime.literal("2024-06-21T13:42:11.195Z")
|> datetime.get_calendar_date
// -> calendar.Date(2024, calendar.June, 21)
pub fn get_calendar_time_of_day(datetime: DateTime) -> TimeOfDay
Gets the core gleam time package calendar time of day of a datetime.
Examples
datetime.literal("2024-06-21T13:42:11.195Z")
|> datetime.get_calendar_time_of_day
// -> calendar.TimeOfDay(13, 42, 11, 195_000_000)
pub fn get_date(datetime: DateTime) -> Date
Gets the date of a datetime.
Examples
datetime.literal("2024-06-21T13:42:11.195Z")
|> datetime.get_date
// -> date.literal("2024-06-21")
pub fn get_offset(datetime: DateTime) -> Offset
Gets the offset of a datetime.
Examples
datetime.literal("2024-06-12T13:42:11.195-04:00")
|> datetime.get_offset
// -> offset.literal("+04:00")
pub fn get_time(datetime: DateTime) -> Time
Gets the time of a datetime.
Examples
datetime.literal("2024-06-21T13:42:11.195Z")
|> datetime.get_time
// -> time.literal("13:42:11.195")
pub fn get_timezone_name(datetime: DateTime) -> Option(String)
Gets the name of the timezone the datetime is in.
Example
datetime.literal("2024-06-21T06:30:02.334Z")
|> datetime.get_timezone_name
// -> None
import gtz
let assert Ok(tz) = gtz.timezone("Europe/London")
datetime.to_timezone(my_datetime, tz)
|> datetime.get_timezone_name
// -> Some("Europe/London")
pub fn is_earlier(a: DateTime, than b: DateTime) -> Bool
Checks if the first datetime is earlier than the second datetime.
Examples
datetime.literal("2024-06-21T23:47:00+09:05")
|> datetime.is_earlier(
than: datetime.literal("2024-06-21T23:47:00+09:05"),
)
// -> False
datetime.literal("2023-05-11T13:30:00-04:00")
|> datetime.is_earlier(
than: datetime.literal("2023-05-11T13:15:00Z"),
)
// -> True
pub fn is_earlier_or_equal(a: DateTime, to b: DateTime) -> Bool
Checks if the first datetime is earlier or equal to the second datetime.
Examples
datetime.literal("2024-06-21T23:47:00+09:05")
|> datetime.is_earlier_or_equal(
to: datetime.literal("2024-06-21T23:47:00+09:05"),
)
// -> True
datetime.literal("2024-07-15T23:40:00-04:00")
|> datetime.is_earlier_or_equal(
to: datetime.literal("2023-05-11T13:15:00Z"),
)
// -> False
pub fn is_equal(a: DateTime, to b: DateTime) -> Bool
Checks if the first datetime is equal to the second datetime.
Examples
datetime.literal("2024-06-21T09:44:00Z")
|> datetime.is_equal(
to: datetime.literal("2024-06-21T05:44:00-04:00"),
)
// -> True
datetime.literal("2024-06-21T09:44:00Z")
|> datetime.is_equal(
to: datetime.literal("2024-06-21T09:44:00.045Z"),
)
// -> False
pub fn is_later(a: DateTime, than b: DateTime) -> Bool
Checks if the first datetime is later than the second datetime.
Examples
datetime.literal("2024-06-21T23:47:00+09:05")
|> datetime.is_later(
than: datetime.literal("2024-06-21T23:47:00+09:05"),
)
// -> False
datetime.literal("2023-05-11T13:00:00+04:00")
|> datetime.is_later(
than: datetime.literal("2023-05-11T13:15:00.534Z"),
)
// -> True
pub fn is_later_or_equal(a: DateTime, to b: DateTime) -> Bool
Checks if the first datetime is later or equal to the second datetime.
Examples
datetime.literal("2016-01-11T03:47:00+09:05")
|> datetime.is_later_or_equal(
to: datetime.literal("2024-06-21T23:47:00+09:05"),
)
// -> False
datetime.literal("2024-07-15T23:40:00-04:00")
|> datetime.is_later_or_equal(
to: datetime.literal("2023-05-11T13:15:00Z"),
)
// -> True
pub fn literal(datetime: String) -> DateTime
Create a new datetime value from a string literal, but will panic if
the string is invalid. Accepted formats are YYYY-MM-DDThh:mm:ss.sTZD
or
YYYYMMDDThhmmss.sTZD
Useful for declaring datetime literals that you know are valid within your
program.
Examples
datetime.literal("2024-06-13T23:04:00.009+10:00")
|> datetime.to_string
// -> "2024-06-13T23:04:00.009+10:00"
pub fn new(
date date: Date,
time time: Time,
offset offset: Offset,
) -> DateTime
Create a new datetime from a date, time, and offset.
Examples
datetime.new(
date.literal("2024-06-13"),
time.literal("23:04:00.009"),
offset.literal("+10:00"),
)
// -> datetime.literal("2024-06-13T23:04:00.009+10:00")
pub fn parse(
str: String,
in format: DateTimeFormat,
) -> Result(DateTime, DateTimeParseError)
Parses a datetime string in the provided format. Always prefer using
this over parse_any
. All parsed formats must have all parts of a
datetime (date, time, offset). Use the other modules for parsing lesser
date time values.
Values can be escaped by putting brackets around them, like “[Hello!] YYYY”.
Available directives: YY (two-digit year), YYYY (four-digit year), M (month), MM (two-digit month), MMM (short month name), MMMM (full month name), D (day of the month), DD (two-digit day of the month), 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), Z (offset from UTC), ZZ (offset from UTC with no “:”), z (short offset from UTC “-04”, “Z”), A (AM/PM), a (am/pm).
Example
datetime.parse("2024/06/08, 13:42:11, -04:00", "YYYY/MM/DD, HH:mm:ss, Z")
// -> Ok(datetime.literal("2024-06-08T13:42:11-04"))
datetime.parse("January 13, 2024. 3:42:11Z", "MMMM DD, YYYY. H:mm:ssz")
// -> Ok(datetime.literal("2024-01-13T03:42:11Z"))
datetime.parse("Hi! 2024 11 13 12 2 am Z", "[Hi!] YYYY M D h m a z")
// -> Ok(datetime.literal("2024-11-13T00:02:00Z"))
pub fn parse_any(
str: String,
) -> Result(DateTime, DateTimeParseError)
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.
Example
parse_any.parse_any("2024.06.21 01:32 PM -0400")
// -> Ok(datetime.literal("2024-06-21T13:32:00-04:00"))
parse_any.parse_any("2024.06.21 01:32 PM")
// -> Error(tempo.ParseMissingOffset)
pub fn subtract(
datetime: DateTime,
duration duration_to_subtract: Duration,
) -> DateTime
Subtracts a duration from a datetime.
Examples
datetime.literal("2024-06-21T23:17:00Z")
|> datetime.subtract(duration.days(3))
// -> datetime.literal("2024-06-18T23:17:00Z")
pub fn time_left_in_day(datetime: DateTime) -> Time
Gets the time left in the day.
Does not account for leap seconds like the rest of the package.
Examples
naive_datetime.literal("2015-06-30T23:59:03Z")
|> naive_datetime.time_left_in_day
// -> time.literal("00:00:57")
naive_datetime.literal("2024-06-18T08:05:20-04:00")
|> naive_datetime.time_left_in_day
// -> time.literal("15:54:40")
pub fn to_local_imprecise(datetime: DateTime) -> DateTime
Converts a datetime to the equivalent local datetime. Prefer to either
design your application to not need this, or add an external timezone
provider to use with the to_timezone
function.
Conversion is based on the host’s current offset. We can not be sure the current host offset is applicable to the given datetime, and so an imprecise conversion will be performed. The imprecise conversion can be inaccurate to the degree the local offset changes throughout the year. For example, in North America where Daylight Savings Time is observed with a one-hour time shift, the imprecise conversion can be off by up to an hour, depending on the time of year.
If the date of the given datetime matches the date of the host, then the conversion will actually be precise all but during the hour(s) when the time zone offset is shifting.
Examples
datetime.literal("2024-06-21T09:57:11.195Z")
|> datetime.to_local_imprecise
// -> tempo.Precise(datetime.literal("2024-06-21T05:57:11.195-04:00"))
datetime.literal("1998-08-23T09:57:11.195Z")
|> datetime.to_local_imprecise
// -> tempo.Imprecise(datetime.literal("1998-08-23T05:57:11.195-04:00"))
pub fn to_offset(datetime: DateTime, offset: Offset) -> DateTime
Converts a datetime to the equivalent time in an offset.
Examples
datetime.literal("2024-06-21T05:36:11.195-04:00")
|> datetime.to_offset(offset.literal("+10:00"))
// -> datetime.literal("2024-06-21T19:36:11.195+10:00")
pub fn to_string(datetime: DateTime) -> String
Returns a string representation of a datetime value in the ISO 8601
format with millisecond precision. If a different precision is needed,
use the format
function. If serializing to send outside of Gleam and then
parse back into a datetime value, use the serialize
function.
Examples
datetime.to_string(my_datetime)
// -> "2024-06-21T05:22:22.009534Z"
pub fn to_timestamp(datetime: DateTime) -> Timestamp
Converts a datetime to a core gleam time timestamp type.
pub fn to_timezone(
datetime: DateTime,
tz: TimeZoneProvider,
) -> DateTime
Converts a datetime to the specified timezone. Relies on an external
package like gtz
to provide timezone information.
Example
import gtz
let assert Ok(tz) = gtz.timezone("America/New_York")
datetime.literal("2024-06-21T06:30:02.334Z")
|> datetime.to_timezone(tz)
|> datetime.to_string
// -> "2024-01-03T02:30:02.334-04:00"
import gtz
let assert Ok(local_tz) = gtz.local_name() |> gtz.timezone
datetime.from_unix_seconds(1_729_257_776)
|> datetime.to_timezone(local_tz)
|> datetime.to_string
// -> "2024-10-18T14:22:56.000+01:00"
pub fn to_unix_micro(datetime: DateTime) -> Int
Returns the UTC unix timestamp in microseconds of a datetime.
Examples
datetime.literal("2024-06-17T13:01:54.334734Z")
|> datetime.to_unix_micro
// -> 1_718_629_314_334_734
pub fn to_unix_milli(datetime: DateTime) -> Int
Returns the UTC unix timestamp in milliseconds of a datetime.
Examples
datetime.literal("2024-06-17T13:01:54.334Z")
|> datetime.to_unix_milli
// -> 1_718_629_314_334
pub fn to_unix_seconds(datetime: DateTime) -> Int
Returns the UTC unix timestamp of a datetime.
Examples
datetime.literal("2024-06-17T12:59:51Z")
|> datetime.to_unix_seconds
// -> 1_718_829_191