rfc3339-fast 0.2.0

High-performance ISO8601/RFC3339 timestamp parsing and formatting for JSON, with optional SIMD acceleration.
Documentation

rfc3339-fast

crates.io docs.rs license

A high-performance Rust library for parsing and formatting RFC3339 timestamps with support for nanosecond precision.

Features

  • Wide timestamp range: Supports timestamps from year 1 to year 9999
  • Nanosecond precision: Up to 9 decimal places of fractional seconds
  • Zero-copy formatting: Reusable stack-allocated buffer for efficient string generation
  • SystemTime integration: Direct conversion to/from std::time::SystemTime
  • Chrono support: Optional integration with the chrono crate via the chrono feature
  • Serde support: Optional serialization/deserialization support via the serde feature
  • SIMD acceleration: Automatic optimization for platforms supporting SSSE3 (x86/x86_64) or NEON (ARM)
  • Efficient parsing: Fast parsing of RFC3339/ISO8601 timestamps

Installation

Add this to your Cargo.toml:

[dependencies]
rfc3339-fast = "0.2"

Optional Features

The default feature set is ["std", "serde"]. Available features:

  • std (default) — enables std::time-dependent APIs (Timestamp::now, conversions to/from std::time::SystemTime, and the std::error::Error impl for TimestampError). Disabling default features makes the crate #![no_std].
  • serde (default) — enables Serialize/Deserialize for Timestamp.
  • chrono — enables conversions from chrono::DateTime<Tz> to Timestamp (implies std).

For example, to enable chrono alongside the defaults:

[dependencies]
rfc3339-fast = { version = "0.1", features = ["chrono"] }

For a no_std build without serde:

[dependencies]
rfc3339-fast = { version = "0.1", default-features = false }

Usage

Parsing Timestamps

Parse an RFC3339/ISO8601 timestamp string:

use std::str::FromStr;
use rfc3339_fast::Timestamp;

let ts = Timestamp::from_str("2026-02-25T14:30:00Z")?;

Formatting Timestamps

Format a timestamp to an RFC3339 string:

use rfc3339_fast::{Timestamp, Buffer};

let ts = Timestamp::now();
let mut buf = Buffer::new();
let formatted = buf.format(ts);
println!("{}", formatted);  // Prints: 2026-02-25T...Z

Constructing from raw components

Build a Timestamp from Unix seconds and nanoseconds, or read those components back out:

use rfc3339_fast::Timestamp;

let ts = Timestamp::from_unix(1_641_006_000, 250_000_000)?;
assert_eq!(ts.seconds(), 1_641_006_000);
assert_eq!(ts.subsec_nanos(), 250_000_000);

from_unix returns TimestampError::OutOfRange if the seconds are outside year 1..=9999 or nanos >= 1_000_000_000. The same validation is also available via TryFrom<(i64, u32)>.

Working with SystemTime

Convert between SystemTime and Timestamp:

use std::time::SystemTime;
use rfc3339_fast::Timestamp;

let sys_time = SystemTime::now();
let ts = Timestamp::from(sys_time);

With Chrono (requires chrono feature)

use rfc3339_fast::Timestamp;

let now = chrono::Utc::now();
let ts: Timestamp = now.into();

With Serde (requires serde feature)

use serde::{Deserialize, Serialize};
use rfc3339_fast::Timestamp;

#[derive(Serialize, Deserialize)]
struct Event {
    name: String,
    timestamp: Timestamp,
}

let json = r#"{"name": "event", "timestamp": "2026-02-25T14:30:00Z"}"#;
let event: Event = serde_json::from_str(json)?;

Timestamp Format

The library uses the ISO8601/RFC3339 format:

YYYY-MM-DDTHH:mm:ss[.nnn]Z

Where:

  • YYYY - Year (0001-9999)
  • MM - Month (01-12)
  • DD - Day (01-31)
  • HH - Hour (00-23)
  • mm - Minute (00-59)
  • ss - Second (00-59)
  • [.nnn] - Optional fractional seconds (3, 6, or 9 digits for millisecond, microsecond, or nanosecond precision)
  • Z - UTC timezone indicator

Performance

The Buffer type is designed for efficient formatting without heap allocations:

let mut buf = Buffer::new();

// Format many timestamps using the same buffer
for ts in timestamps {
    let formatted = buf.format(ts);
    // Use the formatted string
}

The buffer uses a fixed stack-allocated array, making it suitable for high-throughput scenarios.

SIMD acceleration

This crate uses SIMD-accelerated parsing paths for x86/x86_64 (SSSE3) and AArch64 (NEON). Selection is done at compile time via #[cfg(target_feature = ...)], not runtime detection.

  • AArch64 (Apple Silicon, modern ARM servers): NEON is part of the baseline target features, so the SIMD path is enabled automatically.

  • x86_64: SSSE3 is not part of the default x86_64 baseline, so a stock cargo build --release will use the scalar fallback even on a CPU that supports SSSE3. To opt in, build with one of:

    RUSTFLAGS="-C target-cpu=native"      cargo build --release
    RUSTFLAGS="-C target-feature=+ssse3"  cargo build --release
    

    Or set this in .cargo/config.toml for your workspace:

    [build]
    rustflags = ["-C", "target-cpu=native"]
    

    Note that binaries built this way will not run on CPUs that lack the enabled features. If you need a single binary that works everywhere and still picks the fast path on capable CPUs, you'll need to build with the scalar baseline (the default).

Building

To build the project:

cargo build

With optimizations:

cargo build --release

Testing

Run the test suite:

cargo test

With all features:

cargo test --all-features

Benchmarking

Run the criterion benchmarks:

cargo bench

This will measure parsing and formatting performance.

Error Handling

The library provides a TimestampError enum for error handling:

use rfc3339_fast::{Timestamp, TimestampError};
use std::str::FromStr;

match Timestamp::from_str("invalid-timestamp") {
    Ok(ts) => println!("Parsed: {:?}", ts),
    Err(TimestampError::InvalidFormat) => println!("Invalid format"),
    Err(TimestampError::OutOfRange) => println!("Timestamp out of range"),
}

Limitations

  • Parses UTC (Z) and numeric offsets (+HH:MM / -HH:MM); offsets are normalized to UTC on parse.
  • Formatting always emits UTC (Z); the original offset is not preserved on round-trip.
  • Fractional seconds must be exactly 3, 6, or 9 digits.

Algorithm Notes

  • Date calculations use the Fliegel/Van Flandern algorithm for efficient conversion between calendar dates and day counts
  • SIMD implementations leverage platform-specific CPU instructions for faster digit parsing when available

No-std Support

The crate is #![no_std]-compatible when built with default-features = false. In that mode Timestamp operates entirely on (i64 seconds, u32 nanos); the std-only APIs (Timestamp::now, From<SystemTime> / From<&SystemTime>, From<Timestamp> for SystemTime, and the std::error::Error impl for TimestampError) are gated behind the std feature.

License

Licensed under the BSD 2-Clause License.

Contributing

Contributions are welcome! Please ensure all tests pass and add tests for new features:

cargo test --all-features