Atex.TID (atex v0.3.0)

View Source

Struct and helper functions for dealing with AT Protocol TIDs (Timestamp Identifiers), a 13-character string representation of a 64-bit number comprised of a Unix timestamp (in microsecond precision) and a random "clock identifier" to help avoid collisions.

ATProto spec: https://atproto.com/specs/tid

TID strings are always 13 characters long. All bits in the 64-bit number are encoded, essentially meaning that the string is padded with "2" if necessary, (the 0th character in the base32-sortable alphabet).

Summary

Types

An integer to be used for the lower 10 bits of the TID.

t()

A Unix timestamp representing when the TID was created.

Functions

Decode a TID string into an Atex.TID struct, returning an error if it's invalid.

Encode a TID struct into a string.

Generate a random integer to be used as a clock_id.

Create a new TID from a DateTime or an integer representing a Unix timestamp in microseconds.

Returns a TID for the current moment in time, along with a random clock ID.

Convert a TID struct to an instance of DateTime.

Types

clock_id()

@type clock_id() :: 0..1023

An integer to be used for the lower 10 bits of the TID.

t()

@type t() :: %Atex.TID{clock_id: clock_id(), timestamp: timestamp()}

timestamp()

@type timestamp() :: integer()

A Unix timestamp representing when the TID was created.

Functions

decode(tid)

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

Decode a TID string into an Atex.TID struct, returning an error if it's invalid.

Examples

Syntactically valid TIDs:

iex> Atex.TID.decode("3jzfcijpj2z2a")
{:ok, %Atex.TID{clock_id: 6, timestamp: 1688137381887007}}

iex> Atex.TID.decode("7777777777777")
{:ok, %Atex.TID{clock_id: 165, timestamp: 5811096293381285}}

iex> Atex.TID.decode("3zzzzzzzzzzzz")
{:ok, %Atex.TID{clock_id: 1023, timestamp: 2251799813685247}}

iex> Atex.TID.decode("2222222222222")
{:ok, %Atex.TID{clock_id: 0, timestamp: 0}}

Invalid TIDs:

# not base32
iex> Atex.TID.decode("3jzfcijpj2z21")
:error
iex> Atex.TID.decode("0000000000000")
:error

# case-sensitive
iex> Atex.TID.decode("3JZFCIJPJ2Z2A")
:error

# too long/short
iex> Atex.TID.decode("3jzfcijpj2z2aa")
:error
iex> Atex.TID.decode("3jzfcijpj2z2")
:error
iex> Atex.TID.decode("222")
:error

# legacy dash syntax *not* supported (TTTT-TTT-TTTT-CC)
iex> Atex.TID.decode("3jzf-cij-pj2z-2a")
:error

# high bit can't be set
iex> Atex.TID.decode("zzzzzzzzzzzzz")
:error
iex> Atex.TID.decode("kjzfcijpj2z2a")
:error

encode(tid)

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

Encode a TID struct into a string.

Examples

iex> Atex.TID.encode(%Atex.TID{clock_id: 6, timestamp: 1688137381887007})
"3jzfcijpj2z2a"

iex> Atex.TID.encode(%Atex.TID{clock_id: 165, timestamp: 5811096293381285})
"7777777777777"

iex> Atex.TID.encode(%Atex.TID{clock_id: 1023, timestamp: 2251799813685247})
"3zzzzzzzzzzzz"

iex> Atex.TID.encode(%Atex.TID{clock_id: 0, timestamp: 0})
"2222222222222"

gen_clock_id()

@spec gen_clock_id() :: clock_id()

Generate a random integer to be used as a clock_id.

new(source, clock_id \\ nil)

@spec new(DateTime.t() | integer(), integer() | nil) :: t()

Create a new TID from a DateTime or an integer representing a Unix timestamp in microseconds.

If clock_id isn't provided, a random one will be generated.

now()

@spec now() :: t()

Returns a TID for the current moment in time, along with a random clock ID.

to_datetime(tid)

Convert a TID struct to an instance of DateTime.