PcapFileEx.Timestamp (pcap_file_ex v0.5.5)

View Source

High-precision timestamp supporting nanosecond resolution.

Unlike Elixir's DateTime (limited to microsecond precision), this struct preserves full nanosecond precision from PCAP files. This is essential for accurate chronological sorting and merging of packets from multiple capture files.

Structure

A timestamp consists of two components:

  • secs: Unix timestamp in seconds since the epoch (January 1, 1970)
  • nanos: Nanoseconds component (0-999,999,999)

Examples

# Create a timestamp
iex> PcapFileEx.Timestamp.new(1731065049, 735188123)
%PcapFileEx.Timestamp{secs: 1731065049, nanos: 735188123}

# Convert to total nanoseconds
iex> ts = PcapFileEx.Timestamp.new(1731065049, 735188123)
iex> PcapFileEx.Timestamp.to_unix_nanos(ts)
1731065049735188123

# Convert to DateTime (loses nanosecond precision)
iex> ts = PcapFileEx.Timestamp.new(1731065049, 735188123)
iex> PcapFileEx.Timestamp.to_datetime(ts)
~U[2024-11-08 11:24:09.735188Z]

# Compare timestamps
iex> ts1 = PcapFileEx.Timestamp.new(100, 500)
iex> ts2 = PcapFileEx.Timestamp.new(100, 600)
iex> PcapFileEx.Timestamp.compare(ts1, ts2)
:lt

# Sort packets by precise timestamp
# packets
# |> Enum.sort_by(& &1.timestamp_precise, PcapFileEx.Timestamp)

Precision Note

When converting to DateTime using to_datetime/1, the nanosecond precision is truncated to microseconds due to DateTime's limitations. The original nanosecond precision is preserved in the Timestamp struct itself.

Summary

Functions

Compares two timestamps.

Calculates the difference between two timestamps in nanoseconds.

Creates a timestamp from an Elixir DateTime.

Creates a new timestamp from seconds and nanoseconds.

Converts a timestamp to an Elixir DateTime.

Converts a timestamp to total nanoseconds since Unix epoch.

Types

t()

@type t() :: %PcapFileEx.Timestamp{nanos: 0..999_999_999, secs: non_neg_integer()}

Functions

compare(timestamp1, timestamp2)

@spec compare(t(), t()) :: :lt | :eq | :gt

Compares two timestamps.

Returns:

  • :lt if the first timestamp is earlier than the second
  • :eq if the timestamps are equal
  • :gt if the first timestamp is later than the second

Examples

iex> ts1 = PcapFileEx.Timestamp.new(100, 500)
iex> ts2 = PcapFileEx.Timestamp.new(100, 600)
iex> PcapFileEx.Timestamp.compare(ts1, ts2)
:lt

iex> ts1 = PcapFileEx.Timestamp.new(200, 500)
iex> ts2 = PcapFileEx.Timestamp.new(100, 600)
iex> PcapFileEx.Timestamp.compare(ts1, ts2)
:gt

iex> ts1 = PcapFileEx.Timestamp.new(100, 500)
iex> ts2 = PcapFileEx.Timestamp.new(100, 500)
iex> PcapFileEx.Timestamp.compare(ts1, ts2)
:eq

diff(ts1, ts2)

@spec diff(t(), t()) :: integer()

Calculates the difference between two timestamps in nanoseconds.

Returns a positive number if ts1 is later than ts2, negative if earlier.

Examples

iex> ts1 = PcapFileEx.Timestamp.new(100, 500)
iex> ts2 = PcapFileEx.Timestamp.new(100, 600)
iex> PcapFileEx.Timestamp.diff(ts1, ts2)
-100

iex> ts1 = PcapFileEx.Timestamp.new(101, 0)
iex> ts2 = PcapFileEx.Timestamp.new(100, 0)
iex> PcapFileEx.Timestamp.diff(ts1, ts2)
1000000000

from_datetime(dt, resolution \\ :microsecond)

@spec from_datetime(DateTime.t(), :microsecond | :nanosecond) :: t()

Creates a timestamp from an Elixir DateTime.

The resulting timestamp will have microsecond precision, with the nanosecond component being the microsecond value multiplied by 1000.

Parameters

  • datetime - The DateTime to convert
  • resolution - Optional resolution (:microsecond or :nanosecond). Defaults to :microsecond.

Examples

iex> dt = ~U[2024-11-08 11:24:09.735188Z]
iex> PcapFileEx.Timestamp.from_datetime(dt)
%PcapFileEx.Timestamp{secs: 1731065049, nanos: 735188000}

iex> dt = ~U[2024-11-08 11:24:09.735188Z]
iex> PcapFileEx.Timestamp.from_datetime(dt, :nanosecond)
%PcapFileEx.Timestamp{secs: 1731065049, nanos: 735188000}

new(secs, nanos)

@spec new(non_neg_integer(), 0..999_999_999) :: t()

Creates a new timestamp from seconds and nanoseconds.

Parameters

  • secs - Unix timestamp in seconds since epoch
  • nanos - Nanoseconds component (0-999,999,999)

Examples

iex> PcapFileEx.Timestamp.new(1731065049, 735188123)
%PcapFileEx.Timestamp{secs: 1731065049, nanos: 735188123}

iex> PcapFileEx.Timestamp.new(0, 0)
%PcapFileEx.Timestamp{secs: 0, nanos: 0}

to_datetime(timestamp)

@spec to_datetime(t()) :: DateTime.t()

Converts a timestamp to an Elixir DateTime.

Warning: This conversion loses nanosecond precision! DateTime only supports microsecond precision (6 decimal places), so the last 3 digits of nanosecond precision are truncated.

Examples

iex> ts = PcapFileEx.Timestamp.new(1731065049, 735188123)
iex> PcapFileEx.Timestamp.to_datetime(ts)
~U[2024-11-08 11:24:09.735188Z]
# Note: 735188123 nanos becomes 735188 micros (lost 123 nanos)

to_unix_nanos(timestamp)

@spec to_unix_nanos(t()) :: non_neg_integer()

Converts a timestamp to total nanoseconds since Unix epoch.

This is useful for precise time calculations and comparisons.

Examples

iex> ts = PcapFileEx.Timestamp.new(1731065049, 735188123)
iex> PcapFileEx.Timestamp.to_unix_nanos(ts)
1731065049735188123

iex> ts = PcapFileEx.Timestamp.new(0, 999999999)
iex> PcapFileEx.Timestamp.to_unix_nanos(ts)
999999999