A pure Rust reimplementation of libc functions localtime, gmtime and mktime.

Related tags

Date and time tz-rs
Overview

tz-rs

version Minimum supported Rust version Documentation

A pure Rust reimplementation of libc functions localtime, gmtime and mktime.

This crate allows to convert between a Unix timestamp and a calendar time exprimed in the proleptic gregorian calendar with a provided time zone.

Time zones are provided to the library with a POSIX TZ string which can be read from the environment.

Two formats are currently accepted for the TZ string:

  • std offset[dst[offset][,start[/time],end[/time]]] providing a time zone description,
  • file or :file providing the path to a TZif file, which is absolute or relative to the system timezone directory.

See also the Linux manual page of tzset(3) and the glibc documentation of the TZ environment variable.

Context

Calls to libc localtime_r and other related functions from Rust are not safe in a multithreaded application, because they may internally set the TZ environment variable with the setenv function, which is not thread-safe.

See RUSTSEC-2020-0071 and RUSTSEC-2020-0159 for more information.

Documentation

Documentation is hosted on docs.rs.

Platform support

This crate is mainly intended for UNIX platforms.

Since the time zone database files are not included in this crate, non-UNIX users can download a copy of the database on the IANA site and compile the time zone database files to a local directory.

The database files can then be read by specifying an absolute path in the TZ string:

TimeZone::from_posix_tz(format!("{local_database_dir}/usr/share/zoneinfo/Pacific/Auckland"))?;

Note that the determination of the local time zone with this crate is not supported on non-UNIX platforms.

Alternatively, a crate like tzdb can be used, which statically provides existing time zone definitions for this crate, and supports finding the local time zone for all Tier 1 platforms.

Compiler support

Requires rustc 1.45+ when building with no default features, or rustc 1.57+ otherwise.

License

This project is licensed under either of

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in time by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Comments
  • IANA Data Base

    IANA Data Base

    I made a small crate that provides the time zone data base statically: https://crates.io/crates/tzdb

    Right now the time zone's data gets parsed once when first used. Maybe it would be possible to make tz::TimeZones const constructible, so the data gets parsed ahead of time? I'll look into the implementation if you too think that this would be useful.

    opened by Kijewski 6
  • Allow const creation of `TimeZoneRef<'a>`

    Allow const creation of `TimeZoneRef<'a>`

    This allows creating an ephemeral TimeZoneRef, that is in UtcDateTime.project(). This function clones the relevant time zone designation, so a 'static lifetime of the whole TimeZoneRef is not needed.

    opened by Kijewski 5
  • `mktime` in a non-UTC zone?

    `mktime` in a non-UTC zone?

    First, thank you for writing this crate. I hate libc's time API for reasons beyond the soundness problem, so it's great to have pure Rust implementations of time zones.

    The crate's blurb says this:

    A pure Rust reimplementation of libc functions localtime, gmtime and mktime.

    but I can't figure out how to replace mktime when operating in a non-UTC time zone. I want to go from a calendar representation (YYYYmmddHTT:MM:SS) in a political time zone like America/Los_Angeles to seconds since epoch.

    [editing to add: also in particular, my code here relies on mktime accepting a "non-normalized" time struct, as described in the man page:

    The mktime() function modifies the fields of the tm structure as follows: ... if structure members are outside their valid interval, they will be normalized (so that, for example, 40 October is changed into 9 November)

    to find the boundary of the next day in both seconds since epoch and in proper calendar terms. I'm not sure if you consider that in-scope for tz-rs or day math is better handled by some other more full-featured datetime crate built on top of it.]

    I see how to create a UtcDateTime from this kind of spec (UtcDateTime::new is mentioned in the crate-level doc even) but not a DateTime.

    Is this possible today? If not, could it be? Ideally with a way of resolving ambiguity like the Javascript TC39 Temporal API offers.

    For context, I'm trying to replace Moonfire NVR's time 0.1-based code here, here, and here.

    opened by scottlamb 4
  • Example datetime + tz where `FoundDateTimeList` is empty

    Example datetime + tz where `FoundDateTimeList` is empty

    I currently have an integration with tz-rs that looks like this:

    pub fn new(
        year: i32,
        month: u8,
        day: u8,
        hour: u8,
        minute: u8,
        second: u8,
        nanoseconds: u32,
        offset: Offset,
    ) -> Result<Self> {
        let tz = offset.time_zone_ref();
        let found_date_times = DateTime::find(year, month, day, hour, minute, second, nanoseconds, tz)?;
    
        // .latest() will always return `Some(DateTime)`
        // FIXME: this assertion is not consistent with the docs in `tz-rs`.
        let dt = found_date_times.latest().expect("No datetime found with this offset");
        Ok(Self { inner: dt, offset })
    }
    

    https://github.com/artichoke/artichoke/blob/ae40b16294d699ea9e9df459785bd9578372b33a/spinoso-time/src/time/tzrs/mod.rs#L149-L166

    I took a peek at the source and it looks like FoundDateTimeList is implemented with an inner Vec and the calls to earliest() and latest() essentially boil down to Vec::first and Vec::last, but I'm wondering: can this expect ever panic?

    I'd love an example timespec + TZ where in practice that this found date time list is empty so I can add a test that makes this expect panic and enforce that this case is handled. Do you happen to know of one?

    opened by lopopolo 3
  • Does tz-rs crate support custom format Datetime ?

    Does tz-rs crate support custom format Datetime ?

    Now, I just find format DateTime to_string(). Does support custom format?

    About code :

    impl fmt::Display for DateTime {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            let ut_offset = self.local_time_type().ut_offset();
            format_date_time(f, self.year, self.month, self.month_day, self.hour, self.minute, self.second, self.nanoseconds, ut_offset)
        }
    }
    
    
    opened by baoyachi 2
  •  build docker error, not find localtime in unix

    build docker error, not find localtime in unix

    ~ docker run -it ghcr.io/cross-rs/x86_64-unknown-linux-gnu:main /bin/sh
    # cd /etc
    # ls
    X11                     binfmt.d              debian_version  fstab      hosts           issue         legal          magic           opt         profile.d  rc5.d        selinux  sysctl.conf  update-motd.d
    adduser.conf            ca-certificates       default         gai.conf   init            issue.net     libaudit.conf  magic.mime      os-release  rc.local   rc6.d        shadow   sysctl.d     xdg
    alternatives            ca-certificates.conf  deluser.conf    group      init.d          kernel        localtime      mke2fs.conf     pam.conf    rc0.d      rcS.d        shells   systemd
    apt                     cron.daily            dhcp            gshadow    inputrc         ld.so.cache   login.defs     modules-load.d  pam.d       rc1.d      resolv.conf  skel     terminfo
    bash.bashrc             cron.weekly           dpkg            gss        insserv         ld.so.conf    logrotate.d    mtab            passwd      rc2.d      rmt          ssl      timezone
    bash_completion.d       dbus-1                emacs           host.conf  insserv.conf    ld.so.conf.d  lsb-release    networks        perl        rc3.d      securetty    subgid   tmpfiles.d
    bindresvport.blacklist  debconf.conf          environment     hostname   insserv.conf.d  ldap          machine-id     nsswitch.conf   profile     rc4.d      security     subuid   udev 
    
    

    not find /etc/localtime file.

    about code:

        pub fn local() -> Result<Self, TzError> {
            #[cfg(not(unix))]
            let local_time_zone = Self::utc();
    
            #[cfg(unix)]
            let local_time_zone = Self::from_posix_tz("localtime")?;
    
            Ok(local_time_zone)
        }
    
        /// Construct a time zone from the contents of a time zone file
        pub fn from_tz_data(bytes: &[u8]) -> Result<Self, TzError> {
            parse_tz_file(bytes)
        }
    
        /// Construct a time zone from a POSIX TZ string, as described in [the POSIX documentation of the `TZ` environment variable](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html).
        pub fn from_posix_tz(tz_string: &str) -> Result<Self, TzError> {
            if tz_string.is_empty() {
                return Err(TzError::TzStringError(TzStringError::InvalidTzString("empty TZ string")));
            }
    
            if tz_string == "localtime" {
                return parse_tz_file(&fs::read("/etc/localtime")?);
            }
    
            let read = |mut file: File| -> io::Result<_> {
                let mut bytes = Vec::new();
                file.read_to_end(&mut bytes)?;
                Ok(bytes)
            };
    
    

    ref: https://github.com/x-hgg-x/tz-rs/blob/master/src/timezone/mod.rs#L500-L518

    opened by baoyachi 1
  • Does tz-rs support bridge(integrate) the time crate.

    Does tz-rs support bridge(integrate) the time crate.

    Now, I want use time now_local method in time crate. but On POSIX systems, the method would be unsound if it returned a success value.

    Does tz-rs support any method bridge(integrate) the time crate?

    opened by baoyachi 1
  • cannot find Datetime when importing

    cannot find Datetime when importing

    hello.

    im trying to run an example from tz-db crate that was made for this crate.

    use tz::{DateTime, TimeZone};
    use tzdb::{time_zone, tz_by_name};
    
    // access by identifier
    DateTime::now(time_zone::europe::KIEV);
    // access by name
    DateTime::now(tz_by_name("Europe/Berlin").unwrap());
    // names are case insensitive
    DateTime::now(tz_by_name("ArCtIc/LongYeArByEn").unwrap())
    

    but when im trying to run this example (with main function ofc)

    error[E0432]: unresolved imports `tz::DateTime`, `tz::TimeZone`
     --> timezones/src/main.rs:4:10
      |
    4 | use tz::{DateTime, TimeZone};
      |          ^^^^^^^^  ^^^^^^^^ no `TimeZone` in the root
      |          |
      |          no `DateTime` in the root
    
    For more information about this error, try `rustc --explain E0432`.
    error: could not compile `timezones` due to previous error
    

    my cargo toml has

    [package]
    name = "timezones"
    version = "0.1.0"
    edition = "2021"
    
    [dependencies]
    tz = "0.2.1"
    tzdb = "0.2.0"
    

    rustc and cargo versions are

    ❱  rustc -V
    rustc 1.60.0-nightly (c5c610aad 2022-02-14)
    
    ❱  cargo -V
    cargo 1.60.0-nightly (c082648 2022-02-08)
    

    maybe am i missing some feature from this crate ?

    what am i missing, because i dont feel that this is wrong.

    thanks in advance.

    opened by alexzanderr 1
  • Store TzAsciiStr as a Pascal string in 8 bytes

    Store TzAsciiStr as a Pascal string in 8 bytes

    This way the struct fits neatly in one 64bit register. Also processors love sequential access, so TzAsciiStr::as_bytes() will be one attosecond faster.

    opened by Kijewski 1
  • Replace `Arc<str>`|`&'static str` by TinyStr8

    Replace `Arc`|`&'static str` by TinyStr8

    There is no need to use a dynamically allocated Arc<str> (yes, I realize that using this type was my idea) when all time zone designations are 5 or fewer ASCII characters. You could remove the Arc<str>|&'static str schism by using e.g. tinystr::TinyAsciiStr<8>.

    opened by Kijewski 1
  • Consider reverting

    Consider reverting "Simplify DateTime api"

    In many cases I (and I guess many other users, too), operate on UNIX timestamps, only converting the ts some local time zone to present the date to a user. It's useful to have a tinier UTC-only type for this use case. So at least in my opinion the API was better before 7e38724f66fed3b370e8a5763a3fca15ef56f000.

    opened by Kijewski 1
Owner
Rust, Go, C/C++, Python, Javascript, Dart
null
Date and time library for Rust

Chrono: Date and Time for Rust It aims to be a feature-complete superset of the time library. In particular, Chrono strictly adheres to ISO 8601. Chro

Chronotope 2.5k Jan 8, 2023
eos is a datetime library for Rust, aimed at being robust, simple, and easy to use

eos eos is a datetime library for Rust, aimed at being robust, simple, and easy to use. eos is made with the assumption of operating under a proleptic

Danny 51 Dec 19, 2022
rsdate connects to an ntp server, printing the returned time and/or sets the system clock.

?? ?? rsdate rsdate connects to an ntp server, printing the returned time and/or sets the system clock.

Wesley Moore 3 Dec 31, 2022
This crate provides high-performance formatting and parsing routines for ISO8061 timestamps

ISO8061 Timestamp This crate provides high-performance formatting and parsing routines for ISO8061 timestamps, primarily focused on UTC values but wit

Lantern 4 Sep 21, 2022
A simple and fun way to view the time!

Concentric Time A simple and fun way to view the time! Screenshots Dark mode Light mode Dev This project uses Dioxus (a Rust-Wasm framework) and does

Parker McMullin 9 Oct 23, 2022
The implementation of the Persian (Solar Hijri) Calendar in Rust

Rust Persian Calendar Rust Persian Calendar v0.1.1 provides functionality for conversion among Persian (Solar Hijri) and Gregorian calendars. A Julian

Navid 27 Mar 5, 2022
Cocom - NTP client written in Rust

Cocom is an implementation of the NTP-protocol, to receive the time from NTP-server. The client does not necessarily need arguments.

Maximilian Sonnenburg 7 Dec 2, 2022
Time series anomaly detection for Rust

AnomalyDetection.rs Time series AnomalyDetection for Rust Learn how it works Installation Add this line to your application’s Cargo.toml under [depend

Andrew Kane 6 Nov 21, 2022
A fuzzer setup to fuzz libc functions.

libc-fuzzer This does what it sounds like! It attempts to, as automatically as possible, generate and run fuzzers for up to the entire set of libc (in

null 9 Nov 30, 2022
A patch to fix tracing LocalTime problem.

tracing-local-time A patch to fix tracing LocalTime problem. Tracing-subscriber now has a bug in LocalTime, so build ourselves' to fix it. In this pat

Cris Liao 2 Dec 27, 2021
Docker images for compiling static Rust binaries using musl-libc and musl-gcc, with static versions of useful C libraries. Supports openssl and diesel crates.

rust-musl-builder: Docker container for easily building static Rust binaries Source on GitHub Changelog UPDATED: Major updates in this release which m

Eric Kidd 1.3k Jan 1, 2023
libc - Raw FFI bindings to platforms' system libraries

libc provides all of the definitions necessary to easily interoperate with C code (or "C-like" code) on each of the platforms that Rust supports. This includes type definitions (e.g. c_int), constants (e.g. EINVAL) as well as function headers (e.g. malloc).

The Rust Programming Language 1.5k Jan 1, 2023
Const equivalents of many [`bytemuck`] functions, and a few additional const functions.

Const equivalents of many bytemuck functions, and a few additional const functions. constmuck uses bytemuck's traits, so any type that implements thos

null 6 Nov 4, 2021
First Git on Rust is reimplementation with rust in order to learn about rust, c and git.

First Git on Rust First Git on Rust is reimplementation with rust in order to learn about rust, c and git. Reference project This project refer to the

Nobkz 1 Jan 28, 2022
Free and open-source reimplementation of Native Mouse Lock (display_mouse_lock) in rust.

dml-rs display_mouse_lock in rust. Free, open-source reimplementation of display_mouse_lock (Native Mouse Lock) in Rust. Written because I felt like i

Tomat 4 Feb 12, 2023
⚡ An extremely fast reimplementation of gmad.exe and gmpublish.exe

⚡ fastgmad Download An extremely fast reimplementation of gmad.exe and gmpublish.exe. Prefer to use a GUI? Check out gmpublisher! Features Up to x100

William 16 Sep 18, 2023
4fun open-source Cave Story reimplementation written in Rust

doukutsu-rs Download latest Nightly builds (Requires being logged in to GitHub) A re-implementation of Cave Story (Doukutsu Monogatari) engine written

null 564 Jan 1, 2023
A reimplementation of the Zopfli compression tool in Rust.

Zopfli in Rust This is a reimplementation of the Zopfli compression tool in Rust. Carol Nichols started the Rust implementation as an experiment in in

null 11 Dec 26, 2022
Reimplementation of Matthias Müller's "Ten Minute Physics" demos in Rust with WASM + WebGL

ten-minute-physics-rs reimplements Matthias Müller's "Ten Minute Physics" demos in Rust with WASM + WebGL. Compared with the source pure Javascript im

Lucas V. Schuermann 56 Jan 26, 2023
A reimplementation of the minecraft server framework in rust.

FerrumC About FerrumC is a Rust-based reimplementation of the Minecraft server, designed to be fast and efficient, optimized for low memory usage and

Sweattypalms 3 Sep 4, 2023