Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-expr/src/dispatch/range/datetime_range.rs
7884 views
1
#[cfg(feature = "timezones")]
2
use polars_core::prelude::time_zone::parse_time_zone;
3
use polars_core::prelude::*;
4
#[cfg(feature = "dtype-date")]
5
use polars_plan::dsl::DateRangeArgs;
6
use polars_time::{ClosedWindow, Duration, datetime_range_impl};
7
8
use super::utils::{
9
ensure_items_contain_exactly_one_value, temporal_ranges_impl_broadcast,
10
temporal_series_to_i64_scalar,
11
};
12
13
const CAPACITY_FACTOR: usize = 5;
14
15
#[cfg(feature = "dtype-date")]
16
pub(super) fn date_range(
17
s: &[Column],
18
interval: Option<Duration>,
19
closed: ClosedWindow,
20
arg_type: DateRangeArgs,
21
) -> PolarsResult<Column> {
22
let dt_type = DataType::Datetime(TimeUnit::Microseconds, None);
23
match arg_type {
24
DateRangeArgs::StartEndInterval => dt_range_start_end_interval(
25
&s[0].cast(&dt_type)?,
26
&s[1].cast(&dt_type)?,
27
interval.unwrap(),
28
closed,
29
),
30
DateRangeArgs::StartEndSamples => todo!(),
31
DateRangeArgs::StartIntervalSamples => todo!(),
32
DateRangeArgs::EndIntervalSamples => todo!(),
33
}
34
.map(|c| c.cast(&DataType::Date))?
35
}
36
37
#[cfg(feature = "dtype-date")]
38
pub(super) fn date_ranges(
39
s: &[Column],
40
interval: Option<Duration>,
41
closed: ClosedWindow,
42
arg_type: DateRangeArgs,
43
) -> PolarsResult<Column> {
44
let dt_type = DataType::Datetime(TimeUnit::Microseconds, None);
45
match arg_type {
46
DateRangeArgs::StartEndInterval => dt_ranges_start_end_interval(
47
&s[0].cast(&dt_type)?,
48
&s[1].cast(&dt_type)?,
49
interval.unwrap(),
50
closed,
51
),
52
DateRangeArgs::StartEndSamples => todo!(),
53
DateRangeArgs::StartIntervalSamples => todo!(),
54
DateRangeArgs::EndIntervalSamples => todo!(),
55
}
56
.map(|c| c.cast(&DataType::List(Box::new(DataType::Date))))?
57
}
58
59
#[cfg(feature = "dtype-datetime")]
60
pub(super) fn datetime_range(
61
s: &[Column],
62
interval: Option<Duration>,
63
closed: ClosedWindow,
64
arg_type: DateRangeArgs,
65
) -> PolarsResult<Column> {
66
match arg_type {
67
DateRangeArgs::StartEndInterval => {
68
dt_range_start_end_interval(&s[0], &s[1], interval.unwrap(), closed)
69
},
70
DateRangeArgs::StartEndSamples => todo!(),
71
DateRangeArgs::StartIntervalSamples => todo!(),
72
DateRangeArgs::EndIntervalSamples => todo!(),
73
}
74
}
75
76
#[cfg(feature = "dtype-datetime")]
77
pub(super) fn datetime_ranges(
78
s: &[Column],
79
interval: Option<Duration>,
80
closed: ClosedWindow,
81
arg_type: DateRangeArgs,
82
) -> PolarsResult<Column> {
83
match arg_type {
84
DateRangeArgs::StartEndInterval => {
85
dt_ranges_start_end_interval(&s[0], &s[1], interval.unwrap(), closed)
86
},
87
DateRangeArgs::StartEndSamples => todo!(),
88
DateRangeArgs::StartIntervalSamples => todo!(),
89
DateRangeArgs::EndIntervalSamples => todo!(),
90
}
91
}
92
93
/// Datetime range given start, end, and interval.
94
fn dt_range_start_end_interval(
95
start: &Column,
96
end: &Column,
97
interval: Duration,
98
closed: ClosedWindow,
99
) -> PolarsResult<Column> {
100
ensure_items_contain_exactly_one_value(&[start, end], &["start", "end"])?;
101
let dtype = start.dtype();
102
103
if let DataType::Datetime(tu, time_zone) = dtype {
104
let tz = match time_zone {
105
#[cfg(feature = "timezones")]
106
Some(tz) => Some(parse_time_zone(tz)?),
107
_ => None,
108
};
109
let name = start.name();
110
let start = temporal_series_to_i64_scalar(start)
111
.ok_or_else(|| polars_err!(ComputeError: "start is an out-of-range time."))?;
112
let end = temporal_series_to_i64_scalar(end)
113
.ok_or_else(|| polars_err!(ComputeError: "end is an out-of-range time."))?;
114
let result =
115
datetime_range_impl(name.clone(), start, end, interval, closed, *tu, tz.as_ref())?;
116
Ok(result.into_column())
117
} else {
118
polars_bail!(ComputeError: "expected Datetime input, got {:?}", dtype);
119
}
120
}
121
122
fn dt_ranges_start_end_interval(
123
start: &Column,
124
end: &Column,
125
interval: Duration,
126
closed: ClosedWindow,
127
) -> PolarsResult<Column> {
128
let dtype = start.dtype();
129
130
let start = start.to_physical_repr();
131
let start = start.i64()?;
132
let end = end.to_physical_repr();
133
let end = end.i64()?;
134
135
let out = if let DataType::Datetime(tu, time_zone) = dtype {
136
let mut builder = ListPrimitiveChunkedBuilder::<Int64Type>::new(
137
start.name().clone(),
138
start.len(),
139
start.len() * CAPACITY_FACTOR,
140
DataType::Int64,
141
);
142
143
let tz = match time_zone {
144
#[cfg(feature = "timezones")]
145
Some(tz) => Some(parse_time_zone(tz)?),
146
_ => None,
147
};
148
let range_impl = |start, end, builder: &mut ListPrimitiveChunkedBuilder<Int64Type>| {
149
let rng = datetime_range_impl(
150
PlSmallStr::EMPTY,
151
start,
152
end,
153
interval,
154
closed,
155
*tu,
156
tz.as_ref(),
157
)?;
158
builder.append_slice(rng.physical().cont_slice().unwrap());
159
Ok(())
160
};
161
162
temporal_ranges_impl_broadcast(start, end, range_impl, &mut builder)?
163
} else {
164
polars_bail!(ComputeError: "expected Datetime input, got {:?}", dtype);
165
};
166
167
let to_type = DataType::List(Box::new(dtype.clone()));
168
out.cast(&to_type)
169
}
170
171