polars_plan/dsl/
dt.rs

1use super::*;
2
3/// Specialized expressions for [`Series`] with dates/datetimes.
4pub struct DateLikeNameSpace(pub(crate) Expr);
5
6impl DateLikeNameSpace {
7    /// Add a given number of business days.
8    #[cfg(feature = "business")]
9    pub fn add_business_days(
10        self,
11        n: Expr,
12        week_mask: [bool; 7],
13        holidays: Vec<i32>,
14        roll: Roll,
15    ) -> Expr {
16        self.0.map_binary(
17            FunctionExpr::Business(BusinessFunction::AddBusinessDay {
18                week_mask,
19                holidays,
20                roll,
21            }),
22            n,
23        )
24    }
25
26    /// Convert from Date/Time/Datetime into String with the given format.
27    /// See [chrono strftime/strptime](https://docs.rs/chrono/0.4.19/chrono/format/strftime/index.html).
28    pub fn to_string(self, format: &str) -> Expr {
29        let format = format.to_string();
30        self.0
31            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::ToString(
32                format,
33            )))
34    }
35
36    /// Convert from Date/Time/Datetime into String with the given format.
37    /// See [chrono strftime/strptime](https://docs.rs/chrono/0.4.19/chrono/format/strftime/index.html).
38    ///
39    /// Alias for `to_string`.
40    pub fn strftime(self, format: &str) -> Expr {
41        self.to_string(format)
42    }
43
44    /// Change the underlying [`TimeUnit`]. And update the data accordingly.
45    pub fn cast_time_unit(self, tu: TimeUnit) -> Expr {
46        self.0
47            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::CastTimeUnit(
48                tu,
49            )))
50    }
51
52    /// Change the underlying [`TimeUnit`] of the [`Series`]. This does not modify the data.
53    pub fn with_time_unit(self, tu: TimeUnit) -> Expr {
54        self.0
55            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::WithTimeUnit(
56                tu,
57            )))
58    }
59
60    /// Change the underlying [`TimeZone`] of the [`Series`]. This does not modify the data.
61    #[cfg(feature = "timezones")]
62    pub fn convert_time_zone(self, time_zone: TimeZone) -> Expr {
63        self.0.map_unary(FunctionExpr::TemporalExpr(
64            TemporalFunction::ConvertTimeZone(time_zone),
65        ))
66    }
67
68    /// Get the millennium of a Date/Datetime
69    pub fn millennium(self) -> Expr {
70        self.0
71            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Millennium))
72    }
73
74    /// Get the century of a Date/Datetime
75    pub fn century(self) -> Expr {
76        self.0
77            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Century))
78    }
79
80    /// Get the year of a Date/Datetime
81    pub fn year(self) -> Expr {
82        self.0
83            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Year))
84    }
85
86    /// Determine whether days are business days.
87    #[cfg(feature = "business")]
88    pub fn is_business_day(self, week_mask: [bool; 7], holidays: Vec<i32>) -> Expr {
89        self.0
90            .map_unary(FunctionExpr::Business(BusinessFunction::IsBusinessDay {
91                week_mask,
92                holidays,
93            }))
94    }
95
96    // Compute whether the year of a Date/Datetime is a leap year.
97    pub fn is_leap_year(self) -> Expr {
98        self.0
99            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::IsLeapYear))
100    }
101
102    /// Get the iso-year of a Date/Datetime.
103    /// This may not correspond with a calendar year.
104    pub fn iso_year(self) -> Expr {
105        self.0
106            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::IsoYear))
107    }
108
109    /// Get the month of a Date/Datetime.
110    pub fn month(self) -> Expr {
111        self.0
112            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Month))
113    }
114
115    /// Extract quarter from underlying NaiveDateTime representation.
116    /// Quarters range from 1 to 4.
117    pub fn quarter(self) -> Expr {
118        self.0
119            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Quarter))
120    }
121
122    /// Extract the week from the underlying Date representation.
123    /// Can be performed on Date and Datetime
124    ///
125    /// Returns the ISO week number starting from 1.
126    /// The return value ranges from 1 to 53. (The last week of year differs by years.)
127    pub fn week(self) -> Expr {
128        self.0
129            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Week))
130    }
131
132    /// Extract the ISO week day from the underlying Date representation.
133    /// Can be performed on Date and Datetime.
134    ///
135    /// Returns the weekday number where monday = 1 and sunday = 7
136    pub fn weekday(self) -> Expr {
137        self.0
138            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::WeekDay))
139    }
140
141    /// Get the month of a Date/Datetime.
142    pub fn day(self) -> Expr {
143        self.0
144            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Day))
145    }
146
147    /// Get the ordinal_day of a Date/Datetime.
148    pub fn ordinal_day(self) -> Expr {
149        self.0
150            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::OrdinalDay))
151    }
152
153    /// Get the (local) time of a Date/Datetime/Time.
154    pub fn time(self) -> Expr {
155        self.0
156            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Time))
157    }
158
159    /// Get the (local) date of a Date/Datetime.
160    pub fn date(self) -> Expr {
161        self.0
162            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Date))
163    }
164
165    /// Get the (local) datetime of a Datetime.
166    pub fn datetime(self) -> Expr {
167        self.0
168            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Datetime))
169    }
170
171    /// Get the hour of a Datetime/Time64.
172    pub fn hour(self) -> Expr {
173        self.0
174            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Hour))
175    }
176
177    /// Get the minute of a Datetime/Time64.
178    pub fn minute(self) -> Expr {
179        self.0
180            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Minute))
181    }
182
183    /// Get the second of a Datetime/Time64.
184    pub fn second(self) -> Expr {
185        self.0
186            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Second))
187    }
188
189    /// Get the millisecond of a Time64 (scaled from nanosecs).
190    pub fn millisecond(self) -> Expr {
191        self.0
192            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Millisecond))
193    }
194
195    /// Get the microsecond of a Time64 (scaled from nanosecs).
196    pub fn microsecond(self) -> Expr {
197        self.0
198            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Microsecond))
199    }
200
201    /// Get the nanosecond part of a Time64.
202    pub fn nanosecond(self) -> Expr {
203        self.0
204            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::Nanosecond))
205    }
206
207    /// Return the timestamp (UNIX epoch) of a Datetime/Date.
208    pub fn timestamp(self, tu: TimeUnit) -> Expr {
209        self.0
210            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::TimeStamp(tu)))
211    }
212
213    /// Truncate the Datetime/Date range into buckets.
214    pub fn truncate(self, every: Expr) -> Expr {
215        self.0.map_binary(
216            FunctionExpr::TemporalExpr(TemporalFunction::Truncate),
217            every,
218        )
219    }
220
221    /// Roll backward to the first day of the month.
222    #[cfg(feature = "month_start")]
223    pub fn month_start(self) -> Expr {
224        self.0
225            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::MonthStart))
226    }
227
228    /// Roll forward to the last day of the month.
229    #[cfg(feature = "month_end")]
230    pub fn month_end(self) -> Expr {
231        self.0
232            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::MonthEnd))
233    }
234
235    /// Get the base offset from UTC.
236    #[cfg(feature = "timezones")]
237    pub fn base_utc_offset(self) -> Expr {
238        self.0
239            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::BaseUtcOffset))
240    }
241
242    /// Get the additional offset from UTC currently in effect (usually due to daylight saving time).
243    #[cfg(feature = "timezones")]
244    pub fn dst_offset(self) -> Expr {
245        self.0
246            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::DSTOffset))
247    }
248
249    /// Round the Datetime/Date range into buckets.
250    pub fn round(self, every: Expr) -> Expr {
251        self.0
252            .map_binary(FunctionExpr::TemporalExpr(TemporalFunction::Round), every)
253    }
254
255    /// Offset this `Date/Datetime` by a given offset [`Duration`].
256    /// This will take leap years/ months into account.
257    #[cfg(feature = "offset_by")]
258    pub fn offset_by(self, by: Expr) -> Expr {
259        self.0
260            .map_binary(FunctionExpr::TemporalExpr(TemporalFunction::OffsetBy), by)
261    }
262
263    #[cfg(feature = "timezones")]
264    pub fn replace_time_zone(
265        self,
266        time_zone: Option<TimeZone>,
267        ambiguous: Expr,
268        non_existent: NonExistent,
269    ) -> Expr {
270        self.0.map_binary(
271            FunctionExpr::TemporalExpr(TemporalFunction::ReplaceTimeZone(time_zone, non_existent)),
272            ambiguous,
273        )
274    }
275
276    /// Combine an existing Date/Datetime with a Time, creating a new Datetime value.
277    pub fn combine(self, time: Expr, tu: TimeUnit) -> Expr {
278        self.0.map_binary(
279            FunctionExpr::TemporalExpr(TemporalFunction::Combine(tu)),
280            time,
281        )
282    }
283
284    /// Express a Duration in terms of its total number of integer days.
285    #[cfg(feature = "dtype-duration")]
286    pub fn total_days(self) -> Expr {
287        self.0
288            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::TotalDays))
289    }
290
291    /// Express a Duration in terms of its total number of integer hours.
292    #[cfg(feature = "dtype-duration")]
293    pub fn total_hours(self) -> Expr {
294        self.0
295            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::TotalHours))
296    }
297
298    /// Express a Duration in terms of its total number of integer minutes.
299    #[cfg(feature = "dtype-duration")]
300    pub fn total_minutes(self) -> Expr {
301        self.0
302            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::TotalMinutes))
303    }
304
305    /// Express a Duration in terms of its total number of integer seconds.
306    #[cfg(feature = "dtype-duration")]
307    pub fn total_seconds(self) -> Expr {
308        self.0
309            .map_unary(FunctionExpr::TemporalExpr(TemporalFunction::TotalSeconds))
310    }
311
312    /// Express a Duration in terms of its total number of milliseconds.
313    #[cfg(feature = "dtype-duration")]
314    pub fn total_milliseconds(self) -> Expr {
315        self.0.map_unary(FunctionExpr::TemporalExpr(
316            TemporalFunction::TotalMilliseconds,
317        ))
318    }
319
320    /// Express a Duration in terms of its total number of microseconds.
321    #[cfg(feature = "dtype-duration")]
322    pub fn total_microseconds(self) -> Expr {
323        self.0.map_unary(FunctionExpr::TemporalExpr(
324            TemporalFunction::TotalMicroseconds,
325        ))
326    }
327
328    /// Express a Duration in terms of its total number of nanoseconds.
329    #[cfg(feature = "dtype-duration")]
330    pub fn total_nanoseconds(self) -> Expr {
331        self.0.map_unary(FunctionExpr::TemporalExpr(
332            TemporalFunction::TotalNanoseconds,
333        ))
334    }
335
336    /// Replace the time units of a value
337    #[allow(clippy::too_many_arguments)]
338    pub fn replace(
339        self,
340        year: Expr,
341        month: Expr,
342        day: Expr,
343        hour: Expr,
344        minute: Expr,
345        second: Expr,
346        microsecond: Expr,
347        ambiguous: Expr,
348    ) -> Expr {
349        self.0.map_n_ary(
350            FunctionExpr::TemporalExpr(TemporalFunction::Replace),
351            [
352                year,
353                month,
354                day,
355                hour,
356                minute,
357                second,
358                microsecond,
359                ambiguous,
360            ],
361        )
362    }
363}