Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a duration of 1 day with Rust chrono?

I am dealing with some Rust code that works with durations of days but the implementation of Duration::days(n) is, per the documentation n * 24 * 60 * 60 seconds, which isn't n days because not all days are 24 * 60 * 60 seconds.

This behaviour is well documented:

pub fn days(days: i64) -> Duration

Makes a new Duration with given number of days. Equivalent to Duration::seconds(days * 24 * 60 * 60) with overflow checks. Panics when the duration is out of bounds.

Is there a way with Rust Chrono to get a duration that is, strictly, 1 day rather than a number of seconds and is compatible with the DateTime types? Not all days are the same number of seconds. seconds and days are quite different units. If there were such a function then the following would always give a result that is the same time of day on the following day?

let start = Local.now();
let one_day_later = start + function_that_returns_a_duration_of_days(1);

Again, Duration:days(1) is not such a function because it returns 1 * 24 * 60 * 60 seconds, rather than 1 day.

For example, with TZ set to America/Denver the following:

let start = Local.ymd(2019, 3, 10).and_hms(0, 0, 0);
println!("start: {}", start);
let end = Local.ymd(2019, 3, 11).and_hms(0, 0, 0);
println!("end: {}", end);
let elapsed_seconds = end.timestamp() - start.timestamp();
println!("elapsed_seconds: {}", elapsed_seconds);
let end2 = start + Duration::days(1);
println!("end2: {}", end2);
let elapsed_seconds2 = end2.timestamp() - start.timestamp();
println!("elapsed_seconds2: {}", elapsed_seconds2);

Returns:

start: 2019-03-10 00:00:00 -07:00
end: 2019-03-11 00:00:00 -06:00
elapsed_seconds: 82800
end2: 2019-03-11 01:00:00 -06:00
elapsed_seconds2: 86400

It adds 86400 seconds, rather than 1 day.

I can get the correct result with:

let one_day_later =
    (start.date() + Duration::days(1)).and_hms(start.hour(), start.minute(), start.second());

But I would prefer a function that returns a duration of days and in general would like to know more about Rust Chrono capabilities for handling durations. Does it have durations with units other than seconds? What about weeks, months and years, which also have variable numbers of seconds.

I should probably say that I don't know Rust, only having worked with it for a few days now and I haven't much read the source code. I did look at it, but find it difficult to understand due to my limited familiarity with the language.

like image 978
Ian Avatar asked Jan 09 '20 11:01

Ian


1 Answers

A Duration is an amount of time. There is no amount of time that when added to an instant, always yields the same time on the next day, because as you have noticed, calendar days may have different amounts of time in them.

Not only years, weeks and days, but even hours and minutes do not always comprise the same amount of time (Leap second). A Duration is an amount of time, not a "calendar unit". So no, a Duration is not capable of expressing an idea like "same time next week".

The easiest way to express "same time next day" is with the succ and and_time methods on Date:

let one_day_later = start.date().succ().and_time(start.time());

and_time will panic if the time does not exist on the new date.

like image 63
trent Avatar answered Sep 29 '22 06:09

trent