#date-time #time #interval #date

chrono-intervals

创建按每日、每周等间隔的chrono时间间隔

3个版本 (破坏性)

0.3.0 2022年11月5日
0.2.0 2022年11月1日
0.1.0 2022年10月31日

#261 in 日期和时间

Download history 148/week @ 2024-03-13 138/week @ 2024-03-20 113/week @ 2024-03-27 120/week @ 2024-04-03 81/week @ 2024-04-10 102/week @ 2024-04-17 173/week @ 2024-04-24 156/week @ 2024-05-01 110/week @ 2024-05-08 135/week @ 2024-05-15 67/week @ 2024-05-22 105/week @ 2024-05-29 103/week @ 2024-06-05 86/week @ 2024-06-12 50/week @ 2024-06-19 65/week @ 2024-06-26

每月316次下载

MIT/Apache

30KB
286

chrono-intervals:Rust的时间间隔分组

创建按“每日”、“每周”等间隔的chrono时间间隔。

用法

获取间隔的最方便方式是创建一个 IntervalGenerator

use chrono::{DateTime, TimeZone, Utc};
use chrono_intervals::{IntervalGenerator};

let begin = DateTime::parse_from_rfc3339("2022-06-25T08:23:45.000000Z").unwrap();
let end = DateTime::parse_from_rfc3339("2022-06-27T09:31:12.000000Z").unwrap();

let daily_intervals = IntervalGenerator::new().get_intervals(begin, end);

assert_eq!(
    daily_intervals,
    vec![
        (
            Utc.ymd(2022, 6, 25).and_hms(0, 0, 0),
            Utc.ymd(2022, 6, 25).and_hms_milli(23, 59, 59, 999),
        ),
        (
            Utc.ymd(2022, 6, 26).and_hms(0, 0, 0),
            Utc.ymd(2022, 6, 26).and_hms_milli(23, 59, 59, 999),
        ),
        (
            Utc.ymd(2022, 6, 27).and_hms(0, 0, 0),
            Utc.ymd(2022, 6, 27).and_hms_milli(23, 59, 59, 999),
        ),
    ]
);

IntervalGenerator 可以以多种方式配置。让我们看看获取每月间隔但位于太平洋夏令时(PDT)时区的示例

use chrono::{DateTime, TimeZone, Utc};
use chrono_intervals::{Grouping, IntervalGenerator};

// We want to obtain monthly intervals for month in PDT instead of in UTC.
let begin = DateTime::parse_from_rfc3339("2022-06-10T12:23:45.000000-07:00").unwrap();
let end = DateTime::parse_from_rfc3339("2022-08-26T12:23:45.000000-07:00").unwrap();

// PDT is 7h behind of UTC (towards the **west**), thus the
// `offset_west_seconds` are 7*3600
let pdt_offset_west_seconds = 7 * 3600;

let monthly_intervals = IntervalGenerator::new()
    .with_grouping(Grouping::PerMonth)
    .with_offset_west_secs(pdt_offset_west_seconds)
    .get_intervals(begin, end);

// In UTC, we expect the intervals to start 7h after the month boundary.
assert_eq!(
    monthly_intervals,
    vec![
        (
            Utc.ymd(2022, 6, 1).and_hms(7, 0, 0),
            Utc.ymd(2022, 7, 1).and_hms_milli(6, 59, 59, 999),
        ),
        (
            Utc.ymd(2022, 7, 1).and_hms(7, 0, 0),
            Utc.ymd(2022, 8, 1).and_hms_milli(6, 59, 59, 999),
        ),
        (
            Utc.ymd(2022, 8, 1).and_hms(7, 0, 0),
            Utc.ymd(2022, 9, 1).and_hms_milli(6, 59, 59, 999),
        ),
    ]
);

配置选项和默认值

以下是可配置选项及其默认值的概述

  • 间隔分组:您可以选择 Grouping 中表示的任何分组,默认为 PerDay
  • 一个间隔的结束和下一个间隔的开始之间的时间跨度(精度):默认为1毫秒,但可以通过传递任意值来覆盖。您可能希望将其设置为仍认为合理的最短时间跨度,例如毫秒或微秒。
  • 相对于您本地时区的西偏秒数:如果您想获取太平洋夏令时(PDT)的间隔,例如在GMT-7,您需要传递 7*3600 秒的时间差,西偏值以正数表示。例如,中欧时间(CET)在GMT+1,需要 -3600 秒的西偏值。
  • 第一个间隔是否扩展到 begin 之前:默认情况下,第一个间隔将在 begin 的边界之前开始。如果您想只有完全在 begin 之后的完整间隔,可以关闭此选项。
  • 最后一个间隔是否扩展到 end 之后:默认情况下,最后一个间隔将在 end 的边界之后结束。如果您想只有完全在 end 之前的完整间隔,可以关闭此选项。

让我们看看使用所有配置选项的示例

use chrono::{DateTime, Duration, TimeZone, Utc};
use chrono_intervals::{Grouping, IntervalGenerator};

let begin = DateTime::parse_from_rfc3339("2022-10-02T08:23:45.000000Z").unwrap();
let end = DateTime::parse_from_rfc3339("2022-10-18T08:23:45.000000Z").unwrap();

let inter_gen = IntervalGenerator::new()
    .with_grouping(Grouping::PerWeek)
    .with_precision(Duration::microseconds(1))
    .with_offset_west_secs(-3600)
    .without_extended_begin()
    .without_extended_end();

let weekly_intervals = inter_gen.get_intervals(begin, end);

assert_eq!(
    weekly_intervals,
    vec![
        (
            Utc.ymd(2022, 10, 2).and_hms(23, 0, 0),
            Utc.ymd(2022, 10, 9).and_hms_micro(22, 59, 59, 999999),
        ),
        (
            Utc.ymd(2022, 10, 9).and_hms(23, 0, 0),
            Utc.ymd(2022, 10, 16).and_hms_micro(22, 59, 59, 999999),
        ),
    ]
);

使用函数而不是生成器

生成器是最方便的方法。但是,您也可以使用两种不同的函数来获取间隔。

  • get_extended_utc_intervals 返回包含 beginend 的分组区间,精度为 1 毫秒。这与默认的 IntervalGenerator 行为非常相似,只是您需要指定一个 Grouping
  • get_utc_intervals_opts 返回分组区间,并允许指定生成器接受的全部选项。

示例

使用默认选项获取两个时间之间的每日区间

use chrono::{DateTime, TimeZone, Utc};
use chrono_intervals::{Grouping, get_extended_utc_intervals};

let begin = DateTime::parse_from_rfc3339("2022-06-25T08:23:45.000000Z").unwrap();
let end = DateTime::parse_from_rfc3339("2022-06-27T09:31:12.000000Z").unwrap();

let daily_intervals =
    get_extended_utc_intervals(begin, end, &Grouping::PerDay, 0);

assert_eq!(
    daily_intervals,
    vec![
        (
            Utc.ymd(2022, 6, 25).and_hms(0, 0, 0),
            Utc.ymd(2022, 6, 25).and_hms_milli(23, 59, 59, 999),
        ),
        (
            Utc.ymd(2022, 6, 26).and_hms(0, 0, 0),
            Utc.ymd(2022, 6, 26).and_hms_milli(23, 59, 59, 999),
        ),
        (
            Utc.ymd(2022, 6, 27).and_hms(0, 0, 0),
            Utc.ymd(2022, 6, 27).and_hms_milli(23, 59, 59, 999),
        ),
    ]
);

使用默认选项在太平洋夏令时 (PDT) 时区获取月度区间

use chrono::{DateTime, TimeZone, Utc};
use chrono_intervals::{Grouping, get_extended_utc_intervals};

// We want to obtain monthly intervals for months in PDT instead of in UTC.
let begin = DateTime::parse_from_rfc3339("2022-06-10T12:23:45.000000-07:00").unwrap();
let end = DateTime::parse_from_rfc3339("2022-08-26T12:23:45.000000-07:00").unwrap();

// PDT is 7h behind of UTC (towards the **west**), thus the
// `offset_west_seconds` are 7*3600
let pdt_offset_west_seconds = 7 * 3600;

let monthly_intervals =
    get_extended_utc_intervals(begin, end, &Grouping::PerMonth, pdt_offset_west_seconds);

// In UTC, we expect the intervals to start 7h after the day boundary.
assert_eq!(
    monthly_intervals,
    vec![
        (
            Utc.ymd(2022, 6, 1).and_hms(7, 0, 0),
            Utc.ymd(2022, 7, 1).and_hms_milli(6, 59, 59, 999),
        ),
        (
            Utc.ymd(2022, 7, 1).and_hms(7, 0, 0),
            Utc.ymd(2022, 8, 1).and_hms_milli(6, 59, 59, 999),
        ),
        (
            Utc.ymd(2022, 8, 1).and_hms(7, 0, 0),
            Utc.ymd(2022, 9, 1).and_hms_milli(6, 59, 59, 999),
        ),
    ]
);

get_utc_intervals_opts 指定选项

use chrono::{DateTime, Duration, TimeZone, Utc};
use chrono_intervals::{Grouping, get_utc_intervals_opts};

let begin = DateTime::parse_from_rfc3339("2022-06-15T08:23:45.000000Z").unwrap();
let end = DateTime::parse_from_rfc3339("2022-06-30T09:31:12.000000Z").unwrap();

let weekly_intervals =
    get_utc_intervals_opts(
        begin,
        end,
        &Grouping::PerWeek,
        0,
        Duration::microseconds(1),  // interval end is 1µs before the next
        false,                      // start on the boundary after `start`
        true,                       // end at the boundary after `end`
    );

assert_eq!(
    weekly_intervals,
    vec![
        (
            // First interval begins **after** `begin`
            Utc.ymd(2022, 6, 20).and_hms(0, 0, 0),
            Utc.ymd(2022, 6, 26).and_hms_micro(23, 59, 59, 999999),
        ),
        (
            Utc.ymd(2022, 6, 27).and_hms(0, 0, 0),
            // Last interval ends **after** `end`
            Utc.ymd(2022, 7, 3).and_hms_micro(23, 59, 59, 999999),
        ),
    ]
);

依赖项

~1MB
~18K SLoC