tempo/naive_datetime

Functions to use with the NaiveDateTime type in Tempo. Naive datetimes are datetime values without an offset or time zone value.

Example

import tempo/naive_datetime
import tempo/date
import tempo/time

pub fn get_date_and_time() {
  naive_datetime.now_local()
  |> naive_datetime.to_string
  // -> "2024-06-21T13:42:11"
}

## Calendar and range of valid dates

The date part of a naive datetime is a
[proleptic Gregorian calendar](https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar)
date, with Gregorian month lengths and the Gregorian leap year rule
(divisible by 4, except century years, which must be divisible by 400).
Those rules are applied to dates before the calendar's 1582 adoption too,
so early dates do not match what was historically recorded on the Julian
calendar. No other calendar system is supported.

Constructing a naive datetime from calendar parts is limited to **years 1000
through 9999**, so that a year is always four digits. Arithmetic is not
range checked and can carry a value outside that range, where it still
compares correctly but no longer formats as valid ISO 8601. See the
`tempo/date` module docs for the details.

Values

pub fn add(
  datetime: tempo.NaiveDateTime,
  duration duration_to_add: duration.Duration,
) -> tempo.NaiveDateTime

Adds a duration to a naive datetime.

Examples

naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.add(duration.minutes(3))
// -> naive_datetime.literal("2024-06-21T23:20:00")
pub fn as_local(datetime: tempo.NaiveDateTime) -> tempo.DateTime

Sets a naive datetime’s offset to the host’s local offset, leaving the date and time unchanged while returning a datetime value. Alias for set_offset(naive_datetime, offset.local()).

Examples

naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.as_local
// -> datetime.literal("2024-06-21T23:17:00+01:00")
pub fn as_period(
  start start: tempo.NaiveDateTime,
  end end: tempo.NaiveDateTime,
) -> tempo.Period

Creates a period between two naive datetimes. The specified start and end datetimes will be swapped if the start datetime is later than the end datetime.

Examples

naive_datetime.to_period(
  start: naive_datetime.literal("2024-06-12T23:17:00")
  end: naive_datetime.literal("2024-06-16T01:16:12"),
)
|> period.as_days
// -> 3
naive_datetime.to_period(
  start: naive_datetime.literal("2024-06-12T23:17:00"),
  end: naive_datetime.literal("2024-06-16T01:18:12"),
)
|> period.format
// -> "3 days, 2 hours, and 1 minute"
pub fn as_utc(datetime: tempo.NaiveDateTime) -> tempo.DateTime

Sets a naive datetime’s offset to UTC, leaving the date and time unchanged while returning a datetime value. Alias for set_offset(naive_datetime, offset.utc).

Examples

naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.as_utc
// -> datetime.literal("2024-06-21T23:17:00Z")
pub fn compare(
  a: tempo.NaiveDateTime,
  to b: tempo.NaiveDateTime,
) -> order.Order

Compares two naive datetimes.

Examples

naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.compare(to: naive_datetime.literal("2024-06-21T23:17:00"))
// -> order.Eq
naive_datetime.literal("2023-05-11T13:15:00")
|> naive_datetime.compare(to: naive_datetime.literal("2024-06-21T23:17:00"))
// -> order.Lt
pub fn describe_parse_error(
  error: error.NaiveDateTimeParseError,
) -> String

Converts a naive datetime parse error to a human readable error message.

Example

naive_datetime.parse("2024 06 21 23:17:00")
|> snag.map_error(with: naive_datetime.describe_parse_error)
// -> snag.error("Invalid date format in naive datetime: 2024 06 21 23:17:00")
pub fn difference(
  from a: tempo.NaiveDateTime,
  to b: tempo.NaiveDateTime,
) -> duration.Duration

Returns the difference between two naive datetimes as a duration.

Examples

naive_datetime.literal("2024-06-12T23:17:00")
|> naive_datetime.difference(
  to: naive_datetime.literal("2024-06-16T01:16:12"),
)
|> duration.as_days
// -> 3
naive_datetime.literal("2024-06-12T23:17:00")
|> naive_datetime.difference(
  to: naive_datetime.literal("2024-06-16T01:18:12"),
)
|> duration.format
// -> "3 days, 2 hours, and 1 minutes"
pub fn drop_time(
  datetime: tempo.NaiveDateTime,
) -> tempo.NaiveDateTime

Drops the time of a naive datetime, setting it to zero.

Examples

naive_datetime.literal("2024-06-13T23:17:00")
|> naive_datetime.drop_time
// -> datetime.literal("2024-06-13T00:00:00")
pub fn format(
  naive_datetime: tempo.NaiveDateTime,
  in format: tempo.NaiveDateTimeFormat,
) -> String

Formats a naive datetime 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.

All calendar directives render proleptic Gregorian calendar values, and the month and day names are the English Gregorian ones.

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), d (day of the week), dd (min day of the week), ddd (short day of week), dddd (full day of the week), 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), A (AM/PM), a (am/pm).

Example

naive_datetime.literal("2024-06-21T13:42:11.314")
|> naive_datetime.format("ddd @ h:mm A")
// -> "Fri @ 1:42 PM"
naive_datetime.literal("2024-06-03T09:02:01")
|> naive_datetime.format("YY YYYY M MM MMM MMMM D DD d dd ddd")
// --------------------> "24 2024 6 06 Jun June 3 03 1 Mo Mon"
naive_datetime.literal("2024-06-03T09:02:01.014920202")
|> naive_datetime.format("dddd SSS SSSS SSSSS")
// -> "Monday 014 014920 014920202"
naive_datetime.literal("2024-06-03T13: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_string(
  datetime: String,
) -> Result(tempo.NaiveDateTime, error.NaiveDateTimeParseError)

Parses a naive datetime string in the format YYYY-MM-DDThh:mm:ss.s, YYYY-MM-DD hh:mm:ss.s, 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.

The date part is read as a proleptic Gregorian calendar date and must have a year between 1000 and 9999, with a day that exists in that Gregorian month.

Examples

naive_datetime.from_string("20240612")
// -> Ok(naive_datetime.literal("2024-06-12T00:00:00"))
naive_datetime.from_string("2024-06-21 23:17:00")
// -> Ok(naive_datetime.literal("2024-06-21T23:17:00"))
naive_datetime.from_string("24-06-12|23:17:00")
// -> Error(tempo.NaiveDateTimeInvalidFormat)
pub fn get_date(datetime: tempo.NaiveDateTime) -> tempo.Date

Gets the date of a naive datetime.

Examples

naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.get_date
// -> date.literal("2024-06-21")
pub fn get_time(datetime: tempo.NaiveDateTime) -> tempo.Time

Gets the time of a naive datetime.

Examples

naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.get_time
// -> time.literal("23:17:00")
pub fn is_earlier(
  a: tempo.NaiveDateTime,
  than b: tempo.NaiveDateTime,
) -> Bool

Checks if the first naive datetime is earlier than the second naive datetime.

Examples

naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.is_earlier(
  than: naive_datetime.literal("2024-06-21T23:17:00"),
)
// -> False
naive_datetime.literal("2013-06-12T23:17:00")
|> naive_datetime.is_earlier(
  than: naive_datetime.literal("2024-06-12T23:17:00"),
)
// -> True
pub fn is_earlier_or_equal(
  a: tempo.NaiveDateTime,
  to b: tempo.NaiveDateTime,
) -> Bool

Checks if the first naive datetime is earlier or equal to the second naive datetime.

Examples

naive_datetime.literal("2024-08-12T23:17:00")
|> naive_datetime.is_earlier_or_equal(
  to: naive_datetime.literal("2024-06-12T00:00:00"),
)
// -> False
naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.is_earlier_or_equal(
  to: naive_datetime.literal("2024-06-21T23:17:00"),
)
// -> True
pub fn is_equal(
  a: tempo.NaiveDateTime,
  to b: tempo.NaiveDateTime,
) -> Bool

Checks if the first naive datetime is equal to the second naive datetime.

Examples

naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.is_equal(
  to: naive_datetime.literal("2024-06-21T23:17:00"),
)
// -> True
naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.is_equal(
  to: naive_datetime.literal("2024-06-21T23:17:01"),
)
// -> False
pub fn is_later(
  a: tempo.NaiveDateTime,
  than b: tempo.NaiveDateTime,
) -> Bool

Checks if the first naive datetime is later than the second naive datetime.

Examples

naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.is_later(
  than: naive_datetime.literal("2024-06-21T23:17:00"),
)
// -> False
naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.is_later(
  than: naive_datetime.literal("2022-04-12T00:00:00"),
)
// -> True
pub fn is_later_or_equal(
  a: tempo.NaiveDateTime,
  to b: tempo.NaiveDateTime,
) -> Bool

Checks if the first naive datetime is later or equal to the second naive datetime.

Examples

naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.is_later_or_equal(
  to: naive_datetime.literal("2024-06-21T23:17:00"),
)
// -> True
naive_datetime.literal("2022-04-12T00:00:00")
|> naive_datetime.is_later_or_equal(
  to: naive_datetime.literal("2024-06-21T23:17:00"),
)
// -> False
pub fn literal(naive_datetime: String) -> tempo.NaiveDateTime

Creates a new naive datetime value from a string literal, but will panic if the string is invalid.

The date part is read as a proleptic Gregorian calendar date and must have a year between 1000 and 9999, with a day that exists in that Gregorian month. The time part must be a valid time of day.

Useful for declaring date literals that you know are valid within your program.

Examples

naive_datetime.literal("2024-06-21T23:04:00.009")
|> naive_datetime.to_string
// -> "2024-06-21T23:04:00.009"
naive_datetime.literal("2024-06-21T23:04:00.009-04:00")
// panic
pub fn new(
  date: tempo.Date,
  time: tempo.Time,
) -> tempo.NaiveDateTime

Creates a new naive datetime from a date and time value. The date carries the proleptic Gregorian calendar year, month and day; see the tempo/date module docs for its 1000 to 9999 year range.

Examples

naive_datetime.new(
  date.literal("2024-06-21"),
  time.literal("23:04:00.009"),
)
// -> naive_datetime.literal("2024-06-21T23:04:00.009")
pub fn parse(
  str: String,
  in format: tempo.NaiveDateTimeFormat,
) -> Result(tempo.NaiveDateTime, error.NaiveDateTimeParseError)

Parses a naive datetime string in the provided format. Always prefer using this over parse_any. All parsed formats must have all parts of a naive datetime (date and time). Use the other modules for parsing lesser date time values.

The date part is read as a proleptic Gregorian calendar date, with month names matched against the English Gregorian ones. The parsed year must land between 1000 and 9999, and the day must exist in that Gregorian month. A YY two-digit year is resolved into the hundred years leading up to the current date, so "99" parses as 1999 rather than 2099.

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), A (AM/PM), a (am/pm).

Example

naive_datetime.parse("2024/06/08, 13:42:11", "YYYY/MM/DD, HH:mm:ss")
// -> Ok(naive_datetime.literal("2024-06-08T13:42:11"))
naive_datetime.parse("January 13, 2024. 3:42:11", "MMMM DD, YYYY. H:mm:ss")
// -> Ok(naive_datetime.literal("2024-01-13T03:42:11"))
naive_datetime.parse("Hi! 2024 11 13 12 2 am", "[Hi!] YYYY M D h m a")
// -> Ok(naive_datetime.literal("2024-11-13T00:02:00"))
pub fn parse_any(
  str: String,
) -> Result(tempo.NaiveDateTime, error.NaiveDateTimeParseError)

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

naive_datetime.parse_any("2024.06.21 01:32 PM -04:00")
// -> Ok(naive_datetime.literal("2024-06-21T13:32:00"))
naive_datetime.parse_any("2024.06.21")
// -> Error(tempo.ParseMissingTime)
pub fn set_offset(
  datetime: tempo.NaiveDateTime,
  offset: tempo.Offset,
) -> tempo.DateTime

Sets a naive datetime’s offset to the provided offset, leaving the date and time unchanged while returning a datetime value.

Examples

naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.set_offset(offset.literal("+10:00"))
// -> datetime.literal("2024-06-21T23:17:00+10:00")
pub fn subtract(
  datetime: tempo.NaiveDateTime,
  duration duration_to_subtract: duration.Duration,
) -> tempo.NaiveDateTime

Subtracts a duration from a naive datetime.

Examples

naive_datetime.literal("2024-06-12T23:17:00")
|> naive_datetime.subtract(duration.days(3))
// -> naive_datetime.literal("2024-06-09T23:17:00")
pub fn time_left_in_day(
  naive_datetime: tempo.NaiveDateTime,
) -> tempo.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:03")
|> naive_datetime |> tempo.naive_datetime_get_time_left_in_day
// -> time.literal("00:00:57")
naive_datetime.literal("2024-06-18T08:05:20")
|> naive_datetime |> tempo.naive_datetime_get_time_left_in_day
// -> time.literal("15:54:40")
pub fn to_string(datetime: tempo.NaiveDateTime) -> String

Returns a string representation of a naive datetime value in the ISO 8601 format with millisecond precision. If a different precision is needed, use the format function.

Examples

naive_datetime.literal("2024-06-21T23:17:00")
|> naive_datetime.to_string
// -> "2024-06-21T23:17:00.000"
pub fn to_tuple(
  naive_datetime: tempo.NaiveDateTime,
) -> #(#(Int, Int, Int), #(Int, Int, Int))

Returns a tuple of the date and time values in the format used in Erlang.

Example

naive_datetime.literal("2024-06-21T23:17:07")
|> naive_datetime.to_tuple
// -> #(#(2024, 6, 21), #(23, 17, 7))
Search Document