x-hgg-x / tz-rs Goto Github PK
View Code? Open in Web Editor NEWA pure Rust reimplementation of libc functions localtime, gmtime and mktime.
License: Apache License 2.0
A pure Rust reimplementation of libc functions localtime, gmtime and mktime.
License: Apache License 2.0
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 7e38724.
For people who are not familiar with the POSIX localtime, gmtime and mktime functions.
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.
~ 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
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 })
}
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?
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>.
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)
}
}
I am looking to implement a C-compatible tzset
function in terms of tz-rs, and am curious if you know of a way to wire this up. It seems tzset
needs to determine the following information:
daylight
: does the local timezone ever have daylight savings time rules applied?timezone
: UTC offset of local standard timetzname[0]
: the name of the local standard designationtzname[1]
: the name of the local daylight savings designationI can get the local time time from tz-rs like this:
let time_zone_local = TimeZone::local()?;
let local_time_type = time_zone_local.find_current_local_time_type();
That leaves me with a few questions:
local_time_type.is_dst()
the same as daylight
, or is it an indication of whether dst is presently active?local_time_type.time_zone_desgination()
the currently active designation, or is it always for the standard designation?local_time_type.ut_offset()
for the currently active designation, or is it always for the standard designation?Any help you might be able to provide would be greatly appreciated!
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.
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?
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.