我对Rust和chrono库还比较新。
我查看了https://docs.rs/chrono/0.4.19/chrono/struct.Duration.html#method.num_weeks,但是在chrono::Duration中没有num_years()
或num_months()
的API。
有什么解决方法吗?
我对Rust和chrono库还比较新。
我查看了https://docs.rs/chrono/0.4.19/chrono/struct.Duration.html#method.num_weeks,但是在chrono::Duration中没有num_years()
或num_months()
的API。
有什么解决方法吗?
chrono::Duration
不记得你使用的原始基准日期,因此它无法提供这些答案。<end_datetime>.years_since(<start_datetime)
来获取年份。<datetime>.checked_add_months(..)
。但是(至少我认为)这是我自己的做法:type BaseDT = DateTime<FixedOffset>;
type UnitSize = i64;
pub fn signed_month_difference(start: BaseDT, end: BaseDT) -> UnitSize {
let end_naive = end.date_naive();
let start_naive = start.date_naive();
let month_diff = end_naive.month() as UnitSize - start_naive.month() as UnitSize;
let years_diff = (end_naive.year() - start_naive.year()) as UnitSize;
if month_diff >= 0 {
(years_diff * 12) + month_diff
} else {
(years_diff - 1) * 12 + (month_diff + 12)
}
}
chronoutil
提供RelativeDuration
,它"扩展了Chrono的Duration,以添加月份和年份"。let one_day = RelativeDuration::days(1);
let one_month = RelativeDuration::months(1);
let delta = one_month + one_day;
let start = NaiveDate::from_ymd(2020, 1, 30);
assert_eq!(start + delta, NaiveDate::from_ymd(2020, 3, 1));
use chrono::prelude::*;
use date_component::date_component;
fn main() {
let date1 = Utc.ymd(2015, 4, 20).and_hms(0, 0, 0);
let date2 = Utc.ymd(2015, 12, 19).and_hms(0, 0, 0);
let date_interval = date_component::calculate(&date1, &date2);
println!("{:?}", date_interval);
}
// DateComponent { year: 0, month: 7, week: 4, modulo_days: 1, day: 29, hour: 0, minute: 0, second: 0, interval_seconds: 20995200, interval_minutes: 349920, interval_hours: 5832, interval_days: 243, invert: false }
chrono::Duration提供了“ISO 8601时间持续时间与纳秒精度”的日期和时间持续时间,这意味着它在内部表示持续时间为纳秒数,然后提供方便的方法将其转换为其他持续时间单位,如天、周、毫秒等。
这与实际的ISO 8601持续时间标准有些不符,该标准是一种表示和格式的标准。该标准通过格式P [n] Y [n] M [n] DT [n] H [n] M [n] S表示持续时间-这可能会给您想要的结果。但这不是chronos :: Duration的设计目的。
问题在于,为了表示几个月或几年的持续时间,需要比纳秒数更多的信息。持续时间定义了时间间隔中的介入时间:两个点之间的时间。起始或结束时间很重要,因为月份或年份不是标准的持续时间。有28、29、30、31天的月份,以及365和366天的年份。
如果您要编写自己的算法以年、月、日、小时、分钟、秒等格式格式化持续时间,则必须知道开始日期。此外,时区很重要,因为需要考虑夏令时。您还必须做出关于如何表示月份或年份的决策。例如,一月有31天,二月有28天。从1月1日开始计算持续时间1.75个月意味着什么?这是否意味着1月有31天,然后在2月份中有0.75 * 28天?
或者,您可以以级联单位格式表示从起始日期开始的持续时间:例如,在1970年1月1日12:00Z之后的5年、4个月、3天、2小时、12分钟和3秒钟。就像ISO 8601标准一样。
因此,这不是一个简单的解决方案,这一切都取决于您的要求。我可以理解为什么chronos:Duration的开发人员没有提供num_months()和num_years()!
struct
持有天数、月份、年份等等独立于偏移量的持续时间。只有在使用 Duration 进行计算时才会关注偏移量。现在我们需要调用ICU组件来完成这项工作,因为我没有看到其他的解决方法。 - Code4R7
num_weeks() / 4
或num_days() / 30
来获取一个近似值。 - Jmb2020y/December + months{1} == 2021y/January
。months{1}
表示一个月的时间跨度。 - Howard Hinnant2020年2月1日 + months{1} == 2020年3月1日
。在C++中,months{1}
是2629746秒的持续时间或30.437天,这可能会导致意外的结果。 - Jmb2020y/March/1
不是你预期的结果吗?这就是我得到的结果。更多信息请参见:https://dev59.com/46Dia4cB1Zd3GeqPB1Er#43018120 - Howard Hinnant