TypeDB.DateTimeTZ (TypeDB v0.2.0)

Copy Markdown View Source

A TypeDB datetime-tz value.

TypeDB stores a wall-clock timestamp together with either an IANA time zone name or a fixed UTC offset, and renders them differently on the wire:

"2024-03-01T10:30:00.000000000 Europe/London"   # IANA zone
"2024-03-01T10:30:00.000000000+01:00"           # fixed offset

Both parse into this struct. The distinction matters — an IANA zone survives daylight-saving transitions, a fixed offset does not — so the driver keeps it rather than flattening both into a DateTime.

iex> tz = TypeDB.DateTimeTZ.parse("2024-03-01T10:30:00.000000000 Europe/London")
iex> tz.time_zone
"Europe/London"

raw holds the original string; TypeDB renders nanoseconds, while NaiveDateTime only keeps microseconds.

Summary

Functions

Parses a TypeDB datetime-tz string, returning {:ok, value} or :error.

Builds a value for writing, from a wall-clock time and a zone or offset.

Parses a TypeDB datetime-tz string.

Renders back to the TypeDB wire format.

Types

t()

@type t() :: %TypeDB.DateTimeTZ{
  naive: NaiveDateTime.t(),
  raw: String.t(),
  time_zone: String.t() | nil,
  utc_offset: integer() | nil
}

Functions

from_iso8601(string)

@spec from_iso8601(String.t()) :: {:ok, t()} | :error

Parses a TypeDB datetime-tz string, returning {:ok, value} or :error.

new(naive, time_zone)

@spec new(NaiveDateTime.t(), String.t() | integer()) :: t()

Builds a value for writing, from a wall-clock time and a zone or offset.

parse/1 is how you get one out of TypeDB; this is how you make one to send back in, which otherwise meant formatting TypeDB's wire string yourself and putting it in :raw.

The second argument is either an IANA zone name or a fixed UTC offset in seconds — the distinction TypeDB itself keeps, and the reason this module exists rather than a plain DateTime:

iex> ~N[2024-03-01 10:30:00] |> TypeDB.DateTimeTZ.new("Europe/London") |> to_string()
"2024-03-01T10:30:00.000000000 Europe/London"

iex> ~N[2024-03-01 10:30:00] |> TypeDB.DateTimeTZ.new(3600) |> to_string()
"2024-03-01T10:30:00.000000000+01:00"

Rendered at nanosecond precision because that is what TypeDB stores and echoes back, so a value written this way and read again compares equal to itself. Pass the result straight to given_rows; see TypeDB.Given.

parse(string)

@spec parse(String.t()) :: t() | String.t()

Parses a TypeDB datetime-tz string.

Returns the original string unchanged when it cannot be parsed.

to_datetime(value, opts \\ [])

@spec to_datetime(
  t(),
  keyword()
) ::
  {:ok, DateTime.t()}
  | {:ambiguous, DateTime.t(), DateTime.t()}
  | {:gap, DateTime.t(), DateTime.t()}
  | {:error, term()}

Converts to a DateTime.

Fixed-offset values convert without help. IANA-zoned values need a time zone database — pass one with :time_zone_database, or configure a global default via Calendar.put_time_zone_database/1 (for example tz or tzdata).

Ambiguous local times (the repeated hour when clocks go back) return {:ambiguous, first, second}; skipped times return {:gap, before, after}.

to_iso8601(date_time_tz)

@spec to_iso8601(t()) :: String.t()

Renders back to the TypeDB wire format.

Returns :raw verbatim — the exact string TypeDB sent, or the one new/2 built. This struct is a decoded value, not a builder: editing :naive, :time_zone or :utc_offset on one you already have does not change what this renders. Build a new one with new/2 instead.