获取从现在到下一个午夜之间的持续时间的惯用方法是什么?
我有一个这样的函数:
extern crate chrono;
use chrono::prelude::*;
use time;
fn duration_until_next_midnight() -> time::Duration {
let now = Local::now(); // Fri Dec 08 2017 23:00:00 GMT-0300 (-03)
// ... how to continue??
}
它应该在 1 小时内Duration
,因为下一个午夜是星期六 Dec 09 2017 00:00:00 GMT-0300 (-03)
在搜索文档后,我终于找到了缺失的链接:Date::and_hms
。
所以,实际上,它就像
:fn main() {
let now = Local::now();
let tomorrow_midnight = (now + Duration::days(1)).date().and_hms(0, 0, 0);
let duration = tomorrow_midnight.signed_duration_since(now).to_std().unwrap();
println!("Duration between {:?} and {:?}: {:?}", now, tomorrow_midnight, duration);
}
这个想法很简单:
- 增加明天的
DateTime
, - 提取保留时区的
Date
部分, - 通过使用
and_hms
指定"00:00:00"Time
来重建新DateTime
。
and_hms
中有一个panic!
,所以必须小心指定正确的时间。
只需减去两个日期:午夜和现在:
extern crate chrono;
use chrono::prelude::*;
use std::time;
fn duration_until_next_midnight() -> time::Duration {
let now = Local::now();
// change to next day and reset hour to 00:00
let midnight = (now + chrono::Duration::days(1))
.with_hour(0).unwrap()
.with_minute(0).unwrap()
.with_second(0).unwrap()
.with_nanosecond(0).unwrap();
println!("Duration between {:?} and {:?}:", now, midnight);
midnight.signed_duration_since(now).to_std().unwrap()
}
fn main() {
println!("{:?}", duration_until_next_midnight())
}
根据Matthieu的要求,你可以写这样的东西:
fn duration_until_next_midnight() -> Duration {
let now = Local::now();
// get the NaiveDate of tomorrow
let midnight_naivedate = (now + chrono::Duration::days(1)).naive_utc().date();
// create a NaiveDateTime from it
let midnight_naivedatetime = NaiveDateTime::new(midnight_naivedate, NaiveTime::from_hms(0, 0, 0));
// get the local DateTime of midnight
let midnight: DateTime<Local> = DateTime::from_utc(midnight_naivedatetime, *now.offset());
println!("Duration between {:?} and {:?}:", now, midnight);
midnight.signed_duration_since(now).to_std().unwrap()
}
但我不确定它是否更好。
一种方法是计算到下一个午夜的秒数,请记住,time::Tm
同时考虑夏令时和时区:
tm_utcoff: i32
标识用于计算此细分时间值的时区,包括夏令时的任何调整。这是 UTC 以东的秒数。例如,对于美国太平洋夏令时,值为 -7*60*60 = -25200。
extern crate time;
use std::time::Duration;
fn duration_until_next_midnight() -> Duration {
let tnow = time::now();
Duration::new(
(86400 - tnow.to_timespec().sec % 86400 -
i64::from(tnow.tm_utcoff)) as u64,
0,
)
}
如果你想要纳秒级的精度,你必须做更多的数学......