#simd #date-time #date #date-parser #rfc-3339 #time-formatting #time

packedtime-rs

Utilities for efficiently storing, parsing, formatting and truncating timestamps

11 releases

0.3.1 Nov 3, 2023
0.3.0 Nov 1, 2023
0.2.6 Jul 3, 2023
0.2.5 Apr 17, 2023
0.1.1 Jul 26, 2022

#50 in Date and time

Download history 369/week @ 2024-07-22 846/week @ 2024-07-29 1441/week @ 2024-08-05 497/week @ 2024-08-12 1290/week @ 2024-08-19 1817/week @ 2024-08-26 1781/week @ 2024-09-02 1435/week @ 2024-09-09 1667/week @ 2024-09-16 1625/week @ 2024-09-23 1193/week @ 2024-09-30 268/week @ 2024-10-07 1449/week @ 2024-10-14 787/week @ 2024-10-21 375/week @ 2024-10-28 724/week @ 2024-11-04

3,476 downloads per month

Apache-2.0 OR BSD-3-Clause

88KB
2K SLoC

PackedTime-RS

Utilities for efficiently storing, parsing, formatting and truncating timestamps

  • A bit-packed timestamp representation using the same layout as i64 (PackedTimestamp). Each timestamp component uses the minimal number of bits, leaving enough bits for arbitrary timezone offsets in minutes and enough range for years from -9999 to 9999. This is a useful storage format if the timestamps are only parsed, formatted or compared.
  • SIMD optimized parsing and formatting functions using rfc 3339 format. In microbenchmarks these functions are ~20x faster than using chrono
  • Optimized functions for truncating timestamps to year, month, quarter, week or day precision. When used in compute kernels with arrays as input and output these functions are 2x-3x faster compared to chrono.

Usage

Parsing Timestamps

Parsing uses SSE instructions when compiled for a target that supports them. There is a special fast-path when the millisecond uses 3 digits and the timezone is UTC. Without SSE a hand-written recursive descent parser is used.

assert_eq!(
    "2022-08-21T17:30:15.250Z".parse(),
    Ok(PackedTimestamp::new_utc(2022, 8, 21, 17, 30, 15, 250))
);
assert_eq!(
    "2022-08-21T17:30:15.25Z".parse(),
    Ok(PackedTimestamp::new_utc(2022, 8, 21, 17, 30, 15, 250))
);
assert_eq!(
    "2022-08-21 17:30:15.1Z".parse(),
    Ok(PackedTimestamp::new_utc(2022, 8, 21, 17, 30, 15, 100))
);
assert_eq!(
    "2022-08-21 17:30:15Z".parse(),
    Ok(PackedTimestamp::new_utc(2022, 8, 21, 17, 30, 15, 0))
);

Formatting Timestamps

Note that formatting currently ignores the timezone offset and always writes a Z as the offset.

Milliseconds are always included and printed using 3 digits.

assert_eq!(
    PackedTimestamp::new_utc(2022, 8, 21, 17, 30, 15, 100).to_string(),
    "2022-08-21T17:30:15.100Z".to_owned()
);
assert_eq!(
    PackedTimestamp::new_utc(2022, 8, 21, 17, 30, 15, 123).to_string(),
    "2022-08-21T17:30:15.123Z".to_owned()
);
assert_eq!(
    PackedTimestamp::new_utc(2022, 8, 21, 17, 30, 15, 250).to_string(),
    "2022-08-21T17:30:15.250Z".to_owned()
);

Timestamp Kernels

The date_trunc and date_add_month kernels are written in a way that the compiler can auto-vectorize when used in a loop.

assert_eq!(date_trunc_year_timestamp_millis(1658765238_000), 1640995200_000);
assert_eq!(date_trunc_month_timestamp_millis(1658765238_000), 1656633600_000);

assert_eq!(date_add_month_timestamp_millis(1661102969_000, 1), 1663718400_000);
assert_eq!(date_add_month_timestamp_millis(1661102969_000, 12), 1692576000_000);

The package net.jhorstmann:packedtime implements the same packed layout for Java.

No runtime deps