| Crates.io | chrono-intervals |
| lib.rs | chrono-intervals |
| version | 0.3.0 |
| created_at | 2022-10-31 10:16:08.164335+00 |
| updated_at | 2022-11-05 12:33:04.367032+00 |
| description | Create chrono time intervals as per-day, per-week etc. |
| homepage | https://github.com/sgasse/chrono-intervals |
| repository | https://github.com/sgasse/chrono-intervals |
| max_upload_size | |
| id | 702058 |
| size | 64,735 |
Create chrono time intervals as "per-day", "per-week" etc.
The most convenient way to get intervals is by creating an
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),
),
]
);
The IntervalGenerator can be configured in many ways. Let's look at an
example of retrieving monthly intervals but in the Pacific Daylight Time
(PDT) timezone:
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),
),
]
);
Here is an overview of configurable options and their defaults:
Grouping, the default is Grouping::PerDay.chrono::Duration. We do not check that the precision is
reasonable. You probably want to set it to the smallest duration that you
still consider, e.g. milliseconds or microseconds.begin or not: By default,
the first interval will start on the boundary before begin. You can
switch this off if you want only full intervals that are strickly after
begin.end or not: By default, the
last interval will end at the boundary after end. You can switch this
off if you want only full intervals that are strickly before end.Let's look at an example with all configuration options used:
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),
),
]
);
The generator is the most convenient way. However you can also use two different functions to obtain intervals:
get_extended_utc_intervals returns grouped intervals which enclose the
begin and end and have a precision of 1ms. This is pretty close to
the default IntervalGenerator behavior, just that you have to
specify a Grouping.get_utc_intervals_opts returns grouped intervals and allows to specify
all options that the generator also accepts.Get daily intervals between two times with default options:
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),
),
]
);
Get monthly intervals with default options in the Pacific Daylight Time (PDT) timezone:
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),
),
]
);
Specify options for 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),
),
]
);