Live data from Hacker News

Jiff: Datetime library for Rust

github.com

181–190 of 249 posts

Re: Jiff: Datetime library for Rust

#181

Overall this looks nice, but I found myself stumbling over the ToSpan syntax: let span = 5.days().hours(8).minutes(1); It feels sort of weird how the first number appears in front, and then all the other ones are function arguments. I suppose if you don't like that you can just write: let span = Span::new().days(5).hours(8).minutes(1); at the expense of a couple characters, which is not too bad.

I stumbled over use jiff::{Timestamp, ToSpan}; fn main() -> Result { let time: Timestamp = "2024-07-11T01:14:00Z".parse()?; I seem to remember Rust does that thing with interfaces instead of classes, is it that? How come I import a library and all of a sudden strings have a `parse()` method that despite its generic name results in a `Timestamp` object? or is it the left-hand side that determines which meaning `str.pa…

> I have so many questions.

Not being snarky, but I suggest starting by reading at least a little about traits? None of your questions are really about this library - it's just FromStr and an orphan rule.

Re: Jiff: Datetime library for Rust

#182
post #29

Earlier quoted context omitted.

In Rust, you can't implicitly omit fields when instantiating a struct, so it would have to be a bit more verbose, explicitly using Rust's analog to the spread syntax. It would have to look something like: f({ hours: 2, seconds: 53, ..Default::default() }) The defaults could come from some value / function with a name shorter than Default::default(), but it would be less clear.

Adding support for struct default field values would allow for - leaving some mandatory fields - reduce the need for the builder pattern - enable the above to be written as f(S { hours: 2, seconds: 53, .. }) If that feature ever lands, coupled with structural/anonymous structs or struct literal inference, you're getting everything you'd want from named arguments without any of the foot guns.

Has anyone ever proposed it? It's such a straightforward feature with such obvious semantics ("default field values are const contexts") and impossible-to-bikeshed syntax (`a: i32 = 42`) that I've been meaning to write up an RFC myself for around, oh, ten years now...

Re: Jiff: Datetime library for Rust

#183

Earlier quoted context omitted.

It's not really in Rust (at least, not unless I choose to rewrite it in WASM), but there is one case where a lack of leap-second support has really been a thorn in my side. I've been working on and off on a JS web application that performs certain high-precision astronomical calculations, and leap seconds are a big challenge w.r.t. future correctness. Ephemerides don't change very much, but leap seconds can. I can em…

Yeah the way Jiff's leap second support worked (before I ripped it out) is that it would just read from `/usr/share/zoneinfo/leap-seconds.list` (or `/usr/share/zoneinfo/leapseconds`, whichever was available) and use that with some rudimentary caching. That way, Jiff isn't responsible for keeping the list up-to-date. The sysadmin is. Just like what we do for tzdb.

Indeed. The problem is, in the absence of one good solution like that, there are no good solutions, as is the case with web JS. Currently (on the desktop or laptop), the best bet is hifitime's leap-seconds parser, but then the programmer is still responsible for coming up with a sane fallback path for all their target systems. (Which can be tricky for individuals to do, e.g., I have no way to tell whether the tz database is in an expected location on macOS or iOS.)

Re: Jiff: Datetime library for Rust

#184
post #104

Earlier quoted context omitted.

> How could be erased those panic! methods that are used in most of Rust's libraries is something that may be is beyond the possible? It's arguably quite possible, though not as straightforwards as one may hope. For example, there's no_panic, which results in a linker error if the compiler cannot prove a function cannot panic [0], albeit with some caveats. > So much correctness in the Rust language just for to promot…

> Is there that much "promoting" of unchecked unwrap()/expect()/etc. going on? How do you distinguish that from "genuine" cases of violations of the programmer's assumptions? More like promoted indirectly, I think by being used widely on reference code and tutorials the programmers absorbs as a familiar and quick to write method without planning much. And at same time by not being actively promoted that such methods…

> More like promoted indirectly, I think by being used widely on reference code and tutorials the programmers absorbs as a familiar and quick to write method without planning much.

For references/documentation/tutorials I think the use of unwrap() and friends is a tradeoff. It (arguably) allows for more focused/self-contained examples that better showcase a particular aspect, though with the risk that a reader uses those examples as-is without taking other factors into consideration. There's also the fact that documentation examples can be used as tests, in which case use of unwrap() in docs/examples/etc. is arguably a good thing.

> And at same time by not being actively promoted that such methods should not be used within a library runtime or similar at least, because many people do not see it as wrong, what convert it in philosophy I guess.

I think it might depend on where you're looking. For example, the Rust book has a section titled "To panic! or Not to panic!" [0] which outlines some things to consider when deciding whether to panic/call unwrap()/etc. Not sure if that counts as active promotion, but the fact it's in official docs should count for something at least.

> IMHO they can't be genuine if a lib can panic the program

I feel this is a rather strong position to take. Given how panics are intended to be used (handling unexpected state/precondition violations/etc.), it seems it seems akin to saying "just don't write bugs", which would certainly be nice but isn't really realistic for the vast majority of development. I suppose one could hypothetically bubble up every possible error but that comes with its own maintainability/readability/etc. costs.

In addition, that stance seems similar to stating that there's no "genuine" assertion failures or similar in libraries, which seems... bold? What would the alternative be?

> or if it was just a unfinished prototyping part or etc

At least in Rust there's todo!() and unimplemented!() which more directly convey meaning.

[0]: https://doc.rust-lang.org/book/ch09-03-to-panic-or-not-to-pa...

Re: Jiff: Datetime library for Rust

#185

Overall this looks nice, but I found myself stumbling over the ToSpan syntax: let span = 5.days().hours(8).minutes(1); It feels sort of weird how the first number appears in front, and then all the other ones are function arguments. I suppose if you don't like that you can just write: let span = Span::new().days(5).hours(8).minutes(1); at the expense of a couple characters, which is not too bad.

Or 0.days(5).hours(8).minutes(1)?

Re: Jiff: Datetime library for Rust

#186
post #56

Earlier quoted context omitted.

I haven't tried it (so I'm sorry if it's wrong or not what you're talking about) but can't you get a freestanding days function by use jiff::ToSpan::days;

You cannot import trait methods as free standing functions. I'm not sure if there was a discussion about making this a possibility but it's definitely not something you can do today.

multiple discussions happened for this and I don't quite remember the outcome.

But it's much less simple then it seems.

Because `use Trait::method` would not be one (potential generic) method but a group of them so it would be it's own kind of thing working differently to free functions etc. Furthermore as generics might be on the trait you might not be able to fill them in with `::` and even if you fill them in you also wouldn't be able to get a function pointer without having a way to also specify the type the trait is implemented on.

All of this (and probably more issues) are solvable AFIK but in context of this being a minor UX benefit its IMHO not worth it, 1. due to additional compiler complexity but also due to 2. additional language complexity. Through maybe it will happen if someone really cares about it.

Anyway until then you can always define a free function which just calls the method, e.g. `fn default() -> T { T::default() }`. (Which is probably roughly how `use` on a trait method would work if it where a thing.)

Re: Jiff: Datetime library for Rust

#187
post #104

Earlier quoted context omitted.

> Is there that much "promoting" of unchecked unwrap()/expect()/etc. going on? How do you distinguish that from "genuine" cases of violations of the programmer's assumptions? More like promoted indirectly, I think by being used widely on reference code and tutorials the programmers absorbs as a familiar and quick to write method without planning much. And at same time by not being actively promoted that such methods…

> More like promoted indirectly, I think by being used widely on reference code and tutorials the programmers absorbs as a familiar and quick to write method without planning much. For references/documentation/tutorials I think the use of unwrap() and friends is a tradeoff. It (arguably) allows for more focused/self-contained examples that better showcase a particular aspect, though with the risk that a reader uses t…

> it seems it seems akin to saying "just don't write bugs"

That is indeed exactly what is being said as far as I can tell. And yes, it's exactly as ridiculous as you think it is.

I'll link my blog on the topic again because I think it might help here as well: https://blog.burntsushi.net/unwrap/

`unwrap()` contains an assertion. Just like `slice[i]` or even `Box::new(whatever)`. The way to avoid these in C is to commit UB instead of panicking. I've seen arguments that seem understandable for why this is maybe appropriate in the Linux kernel ("I'd rather continue executing with garbage than shut down the user's system"), but I don't think it applies much beyond that. And to be clear, I'm not saying I agree with that either.

Re: Jiff: Datetime library for Rust

#188

Overall this looks nice, but I found myself stumbling over the ToSpan syntax: let span = 5.days().hours(8).minutes(1); It feels sort of weird how the first number appears in front, and then all the other ones are function arguments. I suppose if you don't like that you can just write: let span = Span::new().days(5).hours(8).minutes(1); at the expense of a couple characters, which is not too bad.

Or 0.days(5).hours(8).minutes(1)?

Great, that gives us 0-days.

Re: Jiff: Datetime library for Rust

#189

Earlier quoted context omitted.

You cannot import trait methods as free standing functions. I'm not sure if there was a discussion about making this a possibility but it's definitely not something you can do today.

multiple discussions happened for this and I don't quite remember the outcome. But it's much less simple then it seems. Because `use Trait::method` would not be one (potential generic) method but a group of them so it would be it's own kind of thing working differently to free functions etc. Furthermore as generics might be on the trait you might not be able to fill them in with `:: ` and even if you fill them in you…

Ignoring the technical and UX complexities the desire is somewhat obvious. Particularly for things like ::default().

Re: Jiff: Datetime library for Rust

#190

Earlier quoted context omitted.

This is about the "pit of success", being correct and predictable by default. A difference of timestamps not returning the corresponding elapsed wall-time is _very_ surprising. I want to be able to compute durations between timestamps stored in the DB, received from API calls or retrieved from the system and get the right duration "out of the box". Computing these durations lets me apply business logic relying on it.…

What I'm not clear on though is what the failure mode is in your scenario. What happens when it's wrong? Does something bad happen? If something is one second longer or shorter than what it ought to be on very rare occasions, then what does wrong? I would, for example, imagine that the business use case of "editable for x amount of time" would be perfectly fine with that being plus-or-minus 1 second. It's not just ab…

I think that you have made the right decision.

One of the most common and high-impact failure mode is crashing when parsing a leap second that is represented as "23:59:60".

Jiff is able to parse leap seconds, and beyond that, I doubt that there are many scenarios where you care about leap seconds but not enough to use a library that supports them.

Post reply on HN