rust chrono Duration 如何获得年数或月数?

问题描述 投票:0回答:4

我对 Rust 和 chrono 库还很陌生。

我检查了 https://docs.rs/chrono/0.4.19/chrono/struct.Duration.html#method.num_weeks,但是 chrono::Duration 中没有

num_years()
num_months()
API。

有没有解决这个问题的方法?

date datetime rust duration rust-chrono
4个回答
1
投票

板条箱

chronoutil
提供
RelativeDuration
,即“延长Chrono的持续时间以增加月份和年份”

来自 docs.rs 的示例:

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));

请注意,无法仅从持续时间中提取以月或年为单位的持续时间。这些属性可能会有所不同,具体取决于您使用的日历上的时间点。

例如,在公历中,并非所有月份都一样长(28 至 31 天),这取决于开始日期/时间,持续时间内有多少个月。

date_component 箱考虑到了这一点。给定两个日期,它会为您计算月份和年份。

示例(来自文档):

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 }

1
投票

我也必须解决这个问题。正如其他人指出的那样,年份和月份的问题在于您需要提供开始日期,否则您会根据月份中的日期和年份中的闰日得到不同的答案。

chrono::Duration
不记得您使用的原始基准日期,因此无法提供这些答案。

但是,如果您可以访问计算持续时间的 2 个日期,则可以通过

<end_datetime>.years_since(<start_datetime)
获得年份。

Chrono 没有有任何计算月份的函数。这是因为它(吞咽)简单吗?太琐碎以至于无法包含在一个全面的日历包中?不知道。他们确实提供其他月份的计算,例如

<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)
    }
}

0
投票

chrono::Duration 以“纳秒精度的 ISO 8601 持续时间”提供日期和时间持续时间,这意味着它在内部将持续时间表示为纳秒数,然后提供方便的方法来转换为其他持续时间单位,例如天、周、毫秒等

这与实际的 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 天。

如果您要编写自己的算法来以年、月、日、小时、分钟、秒等形式格式化持续时间。您必须知道开始日期。此外,时区也很重要,因为需要考虑夏令时。您还必须决定如何表示月份或年份的部分内容。例如,1 月有 31 天,2 月有 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()!


0
投票

我同意如果没有开始日期,您无法计算以月为单位的持续时间。但考虑到开始日期,计算月份和年份似乎相对简单:

let months = (end.year() * 12) as u32 + end.month() 
    - ((start.year() * 12) as u32 + start.month());
let years = months/12;

© www.soinside.com 2019 - 2024. All rights reserved.