Skip to content

Latest commit

 

History

History
286 lines (210 loc) · 8.31 KB

File metadata and controls

286 lines (210 loc) · 8.31 KB

fasttime for Python

License

fasttime is a fast, lightweight UTC-focused date/time library for Python, powered by Rust. It provides simple, ergonomic APIs for working with dates, times, and durations with nanosecond precision.

Features

  • Fast: Built with Rust using Ben Joffe's constant-time 64-bit days→date algorithm
  • Simple: Clean, Pythonic API for common date/time operations
  • Precise: Nanosecond precision for all time values
  • UTC-focused: All datetime operations are in UTC by default
  • RFC 3339 support: Parse and format timestamps with fixed offsets
  • Type-safe: Full type hints for better IDE support and type checking

Installation

pip install fasttime

Requires Python 3.10 or later.

Quick Start

import fasttime

# Create dates
date = fasttime.Date(2024, 1, 15)
print(date)  # 2024-01-15
print(date.weekday())  # Weekday.Monday
print(date.ordinal())  # 15

# Work with times
time = fasttime.Time(14, 30, 45, nanosecond=123_456_789)
print(time)  # 14:30:45.123456789

# Combine into UTC datetimes
dt = fasttime.DateTime(date, time)
print(dt)  # 2024-01-15T14:30:45.123456789Z

# Get current UTC time
now = fasttime.DateTime.now_utc()
print(f"Current UTC time: {now}")

# Work with durations
later = now.add_duration(fasttime.Duration.seconds(3600))
diff = later.difference(now)
print(f"Difference: {diff.total_seconds()} seconds")

# Parse from strings
parsed_date = fasttime.Date.parse("2024-12-25")
parsed_time = fasttime.Time.parse("23:59:59.999")
parsed_dt = fasttime.DateTime.parse("2024-12-25T23:59:59.999Z")

# Work with time zones (fixed offsets)
offset = fasttime.UtcOffset.from_hours_minutes(True, 5, 30)  # +05:30
local_dt = fasttime.OffsetDateTime.from_local(date, time, offset)
print(local_dt)  # 2024-01-15T14:30:45.123456789+05:30

# Unix timestamps
timestamp = dt.unix_timestamp()  # seconds
timestamp_ns = dt.unix_timestamp_nanos()  # nanoseconds
dt_from_ts = fasttime.DateTime.from_unix_timestamp(timestamp, 123_456_789)

API Reference

Date

A Gregorian calendar date (year, month, day).

# Constructor
date = fasttime.Date(year: int, month: int, day: int)

# Properties
date.year: int        # Year (i32 range)
date.month: int       # Month (1-12)
date.day: int         # Day (1-31)

# Methods
date.weekday() -> Weekday              # Get day of week
date.ordinal() -> int                  # Day of year (1-366)
date.add_days(days: int) -> Date       # Add/subtract days
date.days_since_unix_epoch() -> int    # Days since 1970-01-01

# Class methods
Date.from_days_since_unix_epoch(days: int) -> Date
Date.parse(s: str) -> Date             # Parse "YYYY-MM-DD"

Time

A time of day with nanosecond precision.

# Constructor
time = fasttime.Time(hour: int, minute: int, second: int, nanosecond: int = 0)

# Properties
time.hour: int         # Hour (0-23)
time.minute: int       # Minute (0-59)
time.second: int       # Second (0-59)
time.nanosecond: int   # Nanosecond (0-999,999,999)

# Methods
time.seconds_since_midnight() -> int   # Total seconds (ignoring nanos)
time.nanos_since_midnight() -> int     # Total nanoseconds

# Class methods
Time.parse(s: str) -> Time             # Parse "HH:MM:SS[.fffffffff]"

DateTime

A UTC date and time.

# Constructor
dt = fasttime.DateTime(date: Date, time: Time)

# Properties
dt.date: Date
dt.time: Time

# Methods
dt.unix_timestamp() -> int                      # Seconds since Unix epoch
dt.unix_timestamp_nanos() -> int                # Nanoseconds since Unix epoch
dt.add_duration(dur: Duration) -> DateTime      # Add a duration
dt.difference(other: DateTime) -> Duration      # Calculate difference

# Class methods
DateTime.from_unix_timestamp(secs: int, nanos: int = 0) -> DateTime
DateTime.now_utc() -> DateTime                  # Current UTC time
DateTime.parse(s: str) -> DateTime              # Parse "YYYY-MM-DDTHH:MM:SS[.fff]Z"

Duration

A signed duration with nanosecond precision.

# Class methods (constructors)
Duration.seconds(secs: int) -> Duration
Duration.milliseconds(ms: int) -> Duration
Duration.microseconds(us: int) -> Duration
Duration.nanoseconds(ns: int) -> Duration

# Methods
dur.total_seconds() -> float      # Total seconds as float
dur.total_nanos() -> int          # Total nanoseconds as int

# Operators
dur1 + dur2                       # Add durations
dur1 - dur2                       # Subtract durations
-dur                              # Negate duration
dur1 < dur2                       # Compare durations

UtcOffset

A fixed offset from UTC.

# Class methods
UtcOffset.from_seconds(seconds: int) -> UtcOffset
UtcOffset.from_hours_minutes(sign_positive: bool, hours: int, minutes: int) -> UtcOffset

# Methods
offset.as_seconds() -> int        # Total offset in seconds
offset.is_utc() -> bool           # True if offset is zero

OffsetDateTime

A datetime with a fixed UTC offset (RFC 3339 style).

# Class methods
OffsetDateTime.from_utc(utc: DateTime, offset: UtcOffset) -> OffsetDateTime
OffsetDateTime.from_local(date: Date, time: Time, offset: UtcOffset) -> OffsetDateTime
OffsetDateTime.parse(s: str) -> OffsetDateTime  # Parse RFC 3339

# Properties
odt.utc: DateTime                 # UTC datetime
odt.offset: UtcOffset             # Offset from UTC

# Methods
odt.to_local() -> DateTime                          # Convert to local datetime
odt.unix_timestamp() -> int                         # Seconds since Unix epoch
odt.unix_timestamp_nanos() -> int                   # Nanoseconds since Unix epoch
odt.add_duration(dur: Duration) -> OffsetDateTime   # Add a duration
odt.difference(other: OffsetDateTime) -> Duration   # Calculate difference

Weekday

An enumeration of weekdays (ISO order, Monday = 1).

# Constants
Weekday.MONDAY
Weekday.TUESDAY
Weekday.WEDNESDAY
Weekday.THURSDAY
Weekday.FRIDAY
Weekday.SATURDAY
Weekday.SUNDAY

# Methods
weekday.number_from_monday() -> int  # 1-7

Examples

See the python/examples/ directory for more examples:

Comparison with Other Libraries

Feature fasttime datetime (stdlib) pendulum arrow
Speed ⚡ Very Fast (Rust) Fast (C) Moderate Moderate
Nanosecond precision ❌ (microsecond) ❌ (microsecond) ❌ (microsecond)
UTC-focused Partial
RFC 3339 parsing
Timezone database ❌ (fixed offset only)
Dependencies None (after build) None Many Many
Memory footprint Small Small Large Large

When to use fasttime:

  • You need UTC timestamps and simple date/time operations
  • You want nanosecond precision
  • You prefer a minimal, fast library without heavy dependencies
  • You're working with logs, metrics, or APIs using ISO 8601/RFC 3339

When to use other libraries:

  • You need full timezone database support (use pendulum or zoneinfo)
  • You need complex calendar/business day calculations
  • You're already using the standard library and don't need extra precision

Performance

fasttime is built with Rust and uses highly optimized algorithms for date/time conversions:

  • Days ↔ Date conversion: Uses Ben Joffe's constant-time algorithm (no division/modulo)
  • Unix timestamp conversion: O(1) operations
  • Parsing: Minimal allocations, direct byte processing

Typical operations complete in microseconds, making it suitable for high-throughput applications.

Development

Building from Source

# Install maturin
pip install maturin

# Build the package
maturin develop

# Run tests
pytest python/tests/

Running Examples

python python/examples/basic_usage.py

License

Licensed under the Apache License, Version 2.0. See LICENSE for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.