ariebovenberg
Joined 4 years ago
Joined 4 years ago
edit: wording
It shows just how inheritance is such a blursed way in general of extending code. Designing a base class is such an art, and even if you get it right, there's little to stop subclasses from extending beyond the carefully designed parts it is allowed to modify.
Django views are probably the place where I've seen this work the best--but certainly not foolproof
Javascript's big datetime redesign (Temporal) has an interesting overview of the decisions they made [1]. Whenever is currently undergoing an expansion of ISO support as well, if you'd like to chime in [2].
[1] https://tc39.es/proposal-temporal/#sec-temporal-iso8601gramm... [2] https://github.com/ariebovenberg/whenever/issues/204#issueco...
> In casual benchmarks, the pure-Python version is about 10x slower than the Rust version, making it 5x slower than the standard library but still (in general) faster than Pendulum and Arrow.
"(in general)" here since the speed compares differently per operation, while the Rust version is faster across the board. That said, there's no operation that is _significantly_ (or unnecessarily) slower than Arrow or Pendulum.
edit: I'm considering adding comparison to the pure Python version once I get the time for a more expanded "benchmarks" page in the docs
1. I _love_ pure Python packages. Not everybody should be forced to use Rust. I want installing pure-Python to be as easy as possible
2. Having separate names on PyPi (with or without extras) creates confusion for libraries depending on whenever: should they depend on whenever-py or whenever-rust? If one “overwrites” the other, this adds confusion.
3. Most users expect to “pip install whenever” and start using the “fast” version
For me, points (3) and (2) weigh heavy enough to make (1) slightly more cumbersome.
But: Maybe I’ve missed something. Have a read in the above issue or add your 2 cents.
edit: formatting
Probably the approach of Chrono is best: allow leap seconds to be represented (i.e. 23:59:60), but not to account for them historically.
Basically:
- Store the offset and the tz ID
- When deserializing, allow explicit choice what to do: keep the offset (i.e. same moment in time) or keep the local time (i.e. same time on the 'wall clock')
I actually did start out basically porting Chrono to Python, but decided against it for two reasons:
1. While I really liked handling local/UTC conversions with the "LocalResult" enum in Rust, it translated poorly to Python. Somewhere along the line you'd need to transition from Rust's "errors as values" to Python's exception-oriented world. I actually wish Python would go Rust's way, but I'm not going to swim against the current here...
2. Most modern libraries in other languages choose to disambiguate local datetimes. I felt it was safer to go the road more traveled here.
This is a conscious decision, I'll explicitly address this in the FAQ soon.
As I commented elsewhere, this is completely in line with industry standards (iCal, Unix time) and other modern libraries. I don't (yet) see any reason to deviate.
Unix time ignores leap seconds, so does RFC 5545 (iCal), and most modern libraries (Chrono, Temporal, NodaTime).
> There'd be a way to do something equivalent without peeking at the call stack, by requiring the caller to explicitly pass a descriptive & unique name
Agree with your tradeoff here. "No instrospection, ever" can also be harmful. Reminds me how 'no global mutable state' also needs to be broken in some cases.