Skip to main content

Crate dtt

Crate dtt 

Source
Expand description

DateTime (DTT) is a comprehensive library for date and time manipulation.

§Overview

This crate provides robust tools for handling dates, times, and timezones in Rust, with a focus on correctness, ergonomics, and performance.

§Features

  • Create and parse dates in multiple formats
  • Timezone conversions and handling
  • Date and time arithmetic
  • Formatting and serialization

§Error Handling

This crate uses the thiserror crate for error handling. All errors are properly typed and implement standard error traits. Operations that may fail return Result<T, AppError>.

§Examples

use dtt::DateTime;

let now = DateTime::new();
println!("Current time: {}", now);

DateTime (DTT) logo

DateTime (DTT)

An ergonomic Rust library for parsing, validating, manipulating, and formatting dates, times, and timezones — with guaranteed round-trip safety and unambiguous timezone codes.

Build Crates.io Docs.rs Coverage lib.rs


§Table of Contents


§Install

cargo add dtt

Or add to Cargo.toml:

[dependencies]
dtt = "0.0.10"

§Prerequisites

DTT requires Rust 1.88.0 or later (pinned by time = 0.3.47, which carries the upstream fix for RUSTSEC stack-exhaustion DoS in time < 0.3.47).

PlatformSetup
macOSbrew install rustup-init && rustup-init -y
Linuxcurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
WSLSame as Linux, run inside your WSL distribution
WindowsDownload rustup-init.exe from rustup.rs

After install, verify with rustc --version (must be ≥ 1.88.0). Upgrade an existing toolchain with rustup update stable.


§Quick Start

use dtt::prelude::*;

fn main() -> Result<(), AppError> {
    // Current UTC time
    let now = DateTime::new();
    println!("Current time: {}", now);

    // Parse — strict, offset-required for time-bearing inputs
    let parsed = DateTime::parse("2024-01-15T10:30:00Z")?;
    println!("Parsed: {}", parsed);

    // Round-trip is guaranteed: parse(format(x)) == x
    let s = parsed.format_rfc3339()?;
    assert_eq!(parsed, DateTime::parse(&s)?);

    // Arithmetic
    let next_week = parsed.add_days(7)?;
    let next_year = parsed.add_years(1)?;
    println!("Next week: {next_week}, next year: {next_year}");

    // Timezone conversion (note the explicit USA suffix)
    let est = parsed.convert_to_tz("EST_USA")?;
    println!("In US Eastern: {est}");

    // Validation
    assert!(DateTime::is_valid_iso_8601("2024-01-15T10:30:00Z"));
    assert!(!DateTime::is_valid_year("10000")); // outside time crate range

    Ok(())
}

Run the full demo:

cargo run --example dtt

§Why DTT?

Most datetime libraries silently produce wrong answers in surprising places. DTT is designed to fail loudly rather than guess:

  • Round-trip safety: DateTime::parse(&dt.format_rfc3339()?)? == dt always holds. No silent date-only truncation.
  • Unambiguous timezones: IST could mean Indian (+05:30), Irish (+01:00), or Israel (+02:00). DTT requires explicit suffixes (IST_INDIA, IST_IRELAND, IST_ISRAEL) so you cannot accidentally use the wrong one.
  • Mixed-sign offsets rejected: new_with_custom_offset(5, -30) returns an error instead of silently producing +05:30.
  • Deterministic Default: DateTime::default() returns the Unix epoch, not wall-clock time, so tests are reproducible.
  • UTC-normalised equality: Two DateTime values that represent the same instant compare equal regardless of which offset they were stored in.
  • Strict validation: is_valid_year is bounded to the actual time::Date range (-9999..=9999), so the validator and the builder always agree.

§Features

ParsingRFC 3339 with offset, ISO 8601 date-only, custom format strings
FormattingRFC 3339, custom format descriptors
ValidationComponents, ranges, leap years, ISO 8601, time strings
Arithmeticadd_days, add_months, add_years (overflow-checked)
ComparisonsEq, Ord, Hash — all UTC-normalised
Calendar helpersstart_of_week, end_of_month, iso_week, iso_year
Timezone support22 disambiguated abbreviations + custom offsets
Serializationserde round-trip via canonical RFC 3339 strings
Cross-platformmacOS, Linux, WSL, Windows

§Supported Timezone Abbreviations

Common abbreviations are intentionally disambiguated. Bare codes like EST, CST, IST, and WADT are not accepted because they refer to multiple zones in the real world.

CodeOffsetRegion
UTC, GMT+00:00Coordinated Universal Time
EST_USA−05:00US Eastern Standard Time
EDT−04:00US Eastern Daylight Time
CST_USA−06:00US Central Standard Time
CDT−05:00US Central Daylight Time
MST / MDT−07/−06US Mountain
PST / PDT−08/−07US Pacific
CET / CEST+01/+02Central Europe
EET / EEST+02/+03Eastern Europe
IST_IRELAND+01:00Irish Standard Time
IST_ISRAEL+02:00Israel Standard Time
IST_INDIA+05:30Indian Standard Time
JST+09:00Japan
HKT+08:00Hong Kong
CST_CHINA+08:00China Standard Time
EST_AUS / AEST+10:00Australian Eastern
AEDT+11:00Australian Eastern Daylight
ACWST+08:45Australian Central Western

For any other zone, use DateTime::new_with_custom_offset(hours, minutes).

Note: DST is not handled automatically. Pick the appropriate code (e.g. EDT vs EST_USA) for the date range you care about.


§API Highlights

§Construction

use dtt::prelude::*;
use time::UtcOffset;

let now    = DateTime::new();                              // current UTC
let utc    = DateTime::new_with_tz("UTC")?;                // explicit
let mumbai = DateTime::new_with_tz("IST_INDIA")?;          // disambiguated
let custom = DateTime::new_with_custom_offset(5, 30)?;     // +05:30
let exact  = DateTime::from_components(2024, 1, 15, 10, 30, 0, UtcOffset::UTC)?;
let epoch  = DateTime::default();                          // 1970-01-01T00:00:00Z

// Builder pattern
let dt = DateTimeBuilder::new()
    .year(2024).month(1).day(15)
    .hour(10).minute(30).second(0)
    .offset(UtcOffset::UTC)
    .build()?;

§Parsing & Formatting

let dt1 = DateTime::parse("2024-01-15T10:30:00Z")?;
let dt2 = DateTime::parse("2024-01-15T10:30:00+05:30")?;
let dt3 = DateTime::parse("2024-01-15")?;                  // date-only OK

let custom = DateTime::parse_custom_format(
    "15/01/2024 10:30",
    "[day]/[month]/[year] [hour]:[minute]",
)?;

let s: String = dt1.format_rfc3339()?;
let pretty   = dt1.format("[year]-[month]-[day]")?;

§Arithmetic & Calendar Math

let dt = DateTime::parse("2024-01-31T00:00:00Z")?;

let next_day  = dt.next_day()?;
let prev_day  = dt.previous_day()?;
let next_week = dt.add_days(7)?;
let next_feb  = dt.add_months(1)?;     // → 2024-02-29 (leap year aware)
let next_year = dt.add_years(1)?;

let monday    = dt.start_of_week()?;
let sunday    = dt.end_of_week()?;
let last_day  = dt.end_of_month()?;

§Macros

use dtt::prelude::*;
use dtt::{dtt_now, dtt_parse, dtt_add_days, dtt_diff, dtt_diff_seconds};

let now = dtt_now!();
let dt  = dtt_parse!("2024-01-15T10:30:00Z")?;
let later = dtt_add_days!(dt, 7)?;

let secs: Option<i64> = dtt_diff_seconds!("1609459200", "1609459230");
assert_eq!(secs, Some(30));

§Development

Clone, build, and verify in under a minute on any platform:

git clone https://github.com/sebastienrousseau/dtt.git
cd dtt

make verify     # fmt-check + lint + test in one command
make help       # full task list

The Makefile is a thin wrapper around the underlying Cargo commands, so the equivalent direct invocations also work:

cargo build                                # build the library and binary
cargo test                                 # run all 240+ tests
cargo clippy --all-targets -- -D warnings  # lint with strict warnings
cargo fmt --check                          # verify formatting
cargo doc --no-deps --open                 # open API docs in your browser
cargo run --example dtt                    # run the end-to-end demo
cargo bench                                # run criterion benchmarks

All commands work identically on macOS, Linux, and WSL. CI exercises the same matrix on Linux, macOS, and Windows on every PR via .github/workflows/cross-platform.yml.


§Troubleshooting

SymptomLikely causeFix
feature 'edition2024' is required from time-coreRust < 1.88.0rustup update stable
Err(InvalidTimezone) for "EST", "CST", "IST"Bare ambiguous codes are rejected by designUse a suffixed form (e.g. EST_USA, IST_INDIA)
Err(InvalidFormat) parsing "2024-01-01T12:00:00"RFC 3339 requires an offsetAppend Z or +HH:MM
Err(InvalidTimezone) from new_with_custom_offset(5, -30)Mixed-sign offsets are rejectedPass same-sign components, e.g. (4, 30)
Err(InvalidDate) from from_components(10000, ...)time::Date only supports -9999..=9999Use a year inside that range
Tests fail with environment-variable racecargo test runs tests in parallelAlready mitigated via serial_test; use cargo test -- --test-threads=1 if you have a custom env-var test

§Documentation


§Contributing

Contributions are welcome. Please read CONTRIBUTING.md — in particular, all commits must be cryptographically signed (git commit -S).

Quick checklist before opening a PR:

cargo fmt
cargo clippy --all-targets -- -D warnings
cargo test
git commit -S -m "feat(dtt): your conventional commit message"

THE ARCHITECTSebastien Rousseau THE ENGINEEUXIS ᴬ Enterprise Unified Execution Intelligence System


§License

Dual-licensed under Apache 2.0 or MIT, at your option.

Back to Top

Modules§

constants
Library constants and configuration values
datetime
Core datetime functionality and operations.
error
Error handling types and implementations.
macros
Macro definitions for common operations.
prelude
Commonly used types and traits.

Macros§

dtt_add_days
Adds the specified number of days to the given DateTime instance.
dtt_assert
Asserts that the given expression is true.
dtt_clone
Creates a copy of the provided DateTime object.
dtt_diff
A helper macro to calculate the difference between two DateTime instances.
dtt_diff_days
Calculates the difference in days between two DateTime instances.
dtt_diff_seconds
Calculates the difference in seconds between two DateTime instances.
dtt_format
Formats a DateTime object using the provided format string.
dtt_is_valid_function
Generates a function that validates a given input string based on a specified type.
dtt_join
Joins multiple strings into a single string.
dtt_map
Creates a new map of the given key-value pairs.
dtt_max
Returns the maximum of the given values.
dtt_min
Returns the minimum of the given values.
dtt_new_with_tz
Creates a new DateTime instance with the specified timezone.
dtt_now
Creates a new DateTime instance with the current date and time in UTC.
dtt_parse
Prints the arguments to the console.
dtt_print
Prints the arguments to the console.
dtt_print_vec
Prints a vector of elements to the console.
dtt_sub_days
Subtracts the specified number of days from the given DateTime instance.
dtt_vec
Creates a new vector of the given elements.
is_valid
Generates a function that validates a given input string based on a specified type.

Structs§

DateTime
Represents a date and time with timezone offset support.

Enums§

AppError
Custom error type for the application.

Functions§

run
Runs the main library functionality with proper error handling.