Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-time/src/month_end.rs
6939 views
1
use arrow::legacy::time_zone::Tz;
2
use chrono::NaiveDateTime;
3
use polars_core::prelude::*;
4
use polars_core::utils::arrow::temporal_conversions::{
5
MILLISECONDS, SECONDS_IN_DAY, timestamp_ms_to_datetime, timestamp_ns_to_datetime,
6
timestamp_us_to_datetime,
7
};
8
9
use crate::month_start::roll_backward;
10
use crate::windows::duration::Duration;
11
12
// roll forward to the last day of the month
13
fn roll_forward(
14
t: i64,
15
time_zone: Option<&Tz>,
16
timestamp_to_datetime: fn(i64) -> NaiveDateTime,
17
datetime_to_timestamp: fn(NaiveDateTime) -> i64,
18
offset_fn: fn(&Duration, i64, Option<&Tz>) -> PolarsResult<i64>,
19
) -> PolarsResult<i64> {
20
let t = roll_backward(t, time_zone, timestamp_to_datetime, datetime_to_timestamp)?;
21
let t = offset_fn(&Duration::parse("1mo"), t, time_zone)?;
22
offset_fn(&Duration::parse("-1d"), t, time_zone)
23
}
24
25
pub trait PolarsMonthEnd {
26
fn month_end(&self, time_zone: Option<&Tz>) -> PolarsResult<Self>
27
where
28
Self: Sized;
29
}
30
31
impl PolarsMonthEnd for DatetimeChunked {
32
fn month_end(&self, time_zone: Option<&Tz>) -> PolarsResult<Self> {
33
let timestamp_to_datetime: fn(i64) -> NaiveDateTime;
34
let datetime_to_timestamp: fn(NaiveDateTime) -> i64;
35
let offset_fn: fn(&Duration, i64, Option<&Tz>) -> PolarsResult<i64>;
36
match self.time_unit() {
37
TimeUnit::Nanoseconds => {
38
timestamp_to_datetime = timestamp_ns_to_datetime;
39
datetime_to_timestamp = datetime_to_timestamp_ns;
40
offset_fn = Duration::add_ns;
41
},
42
TimeUnit::Microseconds => {
43
timestamp_to_datetime = timestamp_us_to_datetime;
44
datetime_to_timestamp = datetime_to_timestamp_us;
45
offset_fn = Duration::add_us;
46
},
47
TimeUnit::Milliseconds => {
48
timestamp_to_datetime = timestamp_ms_to_datetime;
49
datetime_to_timestamp = datetime_to_timestamp_ms;
50
offset_fn = Duration::add_ms;
51
},
52
};
53
Ok(self
54
.phys
55
.try_apply_nonnull_values_generic(|t| {
56
roll_forward(
57
t,
58
time_zone,
59
timestamp_to_datetime,
60
datetime_to_timestamp,
61
offset_fn,
62
)
63
})?
64
.into_datetime(self.time_unit(), self.time_zone().clone()))
65
}
66
}
67
68
impl PolarsMonthEnd for DateChunked {
69
fn month_end(&self, _time_zone: Option<&Tz>) -> PolarsResult<Self> {
70
const MSECS_IN_DAY: i64 = MILLISECONDS * SECONDS_IN_DAY;
71
let ret = self.phys.try_apply_nonnull_values_generic(|t| {
72
let fwd = roll_forward(
73
MSECS_IN_DAY * t as i64,
74
None,
75
timestamp_ms_to_datetime,
76
datetime_to_timestamp_ms,
77
Duration::add_ms,
78
)?;
79
PolarsResult::Ok((fwd / MSECS_IN_DAY) as i32)
80
})?;
81
Ok(ret.into_date())
82
}
83
}
84
85