chrono
chrono copied to clipboard
Ergonomics for naive::Days and Months
naive::Days and Months are extremely unergonomic at the moment; it's impossible to recover the number of days/months once one has been constructed, and the constructors Days::new and Months::new are rather verbose.
Would it be possible for chrono to provide From and Into impls for u64/u32 (respectively) and/or make each integer pub so users can construct and destructure them?
What's your use case for this? It seems unergonomic because you're using them in a way that we didn't foresee when designing them.
Also how is Days::new() more verbose than Days::from()? I suppose you want to use .into() instead?
I suppose you want to use .into() instead?
Indeed, or the constructor Days().
What's your use case for this?
E.g., if I want an iterator that yields the same day/time on consecutive months, I currently write:
struct It {
base: DateTime<Utc>,
here: u32,
}
impl It {
fn new(base: DateTime<Utc>) -> Self {
Self { base, here: 0 }
}
}
impl Iterator for It {
type Item = DateTime<Utc>;
fn next(&mut self) -> Option<Self::Item> {
let m = self.here;
self.here += 1;
self.base.checked_add_months(Months::new(m))
}
}
fn main() {
let dt = Utc.with_ymd_and_hms(2023, 07, 31, 12, 34, 56).single().unwrap();
dbg!(It::new(dt).take(5).collect::<Vec<_>>());
}
Whereas the following would be easier and clearer (less unit confusion):
// ...
here: Months,
// ...
Self { base, here: Months(0) }
// ...
let m = self.here;
self.here += Months(1); // or self.here.0 += 1, vel sim.
self.base.checked_add_months(m)
I also can't write a helper that accepts Months and does anything but pass it on unmodified:
fn consecutive(dt: DateTime<Utc>, months: Months) -> Vec<DateTime<Utc>> {
It::new(dt).take(months/* uh oh... */).collect()
}
When I initially encountered Days and Months I assumed they were newtypes meant to help manage units, but you can't actually use them like that. If the only purpose of these types is to force you to write Months::new() in every call to very-explicitly-named methods like checked_add_months, I don't see why they exist at all (the Add/Sub impls, I suppose?).
Yes, they mostly exist for the Add/Sub impls. I don't want to expose the inner field publicly so you won't be able to write Days(1) directly.
I don't want to
Ok…
@nathan I don't really follow about the constructors, but regarding From, this PR adds Months::as_u32(), which should allow you to determine the value of months. Using that method you can then easily implement any From conversions you need 🙂
Also I think all of this will be superseded by the CalendarDuration type as proposed in #1290.