1#[cfg(feature = "timezones")]
2use chrono_tz::Tz;
3#[cfg(feature = "timezones")]
4use polars_time::base_utc_offset as base_utc_offset_fn;
5#[cfg(feature = "timezones")]
6use polars_time::dst_offset as dst_offset_fn;
7#[cfg(feature = "offset_by")]
8use polars_time::impl_offset_by;
9#[cfg(any(feature = "dtype-date", feature = "dtype-datetime"))]
10use polars_time::replace::{replace_date, replace_datetime};
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14use super::*;
15
16#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17#[derive(Clone, PartialEq, Debug, Eq, Hash)]
18pub enum TemporalFunction {
19 Millennium,
20 Century,
21 Year,
22 IsLeapYear,
23 IsoYear,
24 Quarter,
25 Month,
26 Week,
27 WeekDay,
28 Day,
29 OrdinalDay,
30 Time,
31 Date,
32 Datetime,
33 Duration(TimeUnit),
34 Hour,
35 Minute,
36 Second,
37 Millisecond,
38 Microsecond,
39 Nanosecond,
40 TotalDays,
41 TotalHours,
42 TotalMinutes,
43 TotalSeconds,
44 TotalMilliseconds,
45 TotalMicroseconds,
46 TotalNanoseconds,
47 ToString(String),
48 CastTimeUnit(TimeUnit),
49 WithTimeUnit(TimeUnit),
50 #[cfg(feature = "timezones")]
51 ConvertTimeZone(TimeZone),
52 TimeStamp(TimeUnit),
53 Truncate,
54 #[cfg(feature = "offset_by")]
55 OffsetBy,
56 #[cfg(feature = "month_start")]
57 MonthStart,
58 #[cfg(feature = "month_end")]
59 MonthEnd,
60 #[cfg(feature = "timezones")]
61 BaseUtcOffset,
62 #[cfg(feature = "timezones")]
63 DSTOffset,
64 Round,
65 Replace,
66 #[cfg(feature = "timezones")]
67 ReplaceTimeZone(Option<TimeZone>, NonExistent),
68 Combine(TimeUnit),
69 DatetimeFunction {
70 time_unit: TimeUnit,
71 time_zone: Option<TimeZone>,
72 },
73}
74
75impl TemporalFunction {
76 pub(super) fn get_field(&self, mapper: FieldsMapper) -> PolarsResult<Field> {
77 use TemporalFunction::*;
78 match self {
79 Millennium | Century => mapper.with_dtype(DataType::Int8),
80 Year | IsoYear => mapper.with_dtype(DataType::Int32),
81 OrdinalDay => mapper.with_dtype(DataType::Int16),
82 Month | Quarter | Week | WeekDay | Day | Hour | Minute | Second => {
83 mapper.with_dtype(DataType::Int8)
84 },
85 Millisecond | Microsecond | Nanosecond => mapper.with_dtype(DataType::Int32),
86 TotalDays | TotalHours | TotalMinutes | TotalSeconds | TotalMilliseconds
87 | TotalMicroseconds | TotalNanoseconds => mapper.with_dtype(DataType::Int64),
88 ToString(_) => mapper.with_dtype(DataType::String),
89 WithTimeUnit(_) => mapper.with_same_dtype(),
90 CastTimeUnit(tu) => mapper.try_map_dtype(|dt| match dt {
91 DataType::Duration(_) => Ok(DataType::Duration(*tu)),
92 DataType::Datetime(_, tz) => Ok(DataType::Datetime(*tu, tz.clone())),
93 dtype => polars_bail!(ComputeError: "expected duration or datetime, got {}", dtype),
94 }),
95 #[cfg(feature = "timezones")]
96 ConvertTimeZone(tz) => mapper.try_map_dtype(|dt| match dt {
97 DataType::Datetime(tu, _) => Ok(DataType::Datetime(*tu, Some(tz.clone()))),
98 dtype => polars_bail!(ComputeError: "expected Datetime, got {}", dtype),
99 }),
100 TimeStamp(_) => mapper.with_dtype(DataType::Int64),
101 IsLeapYear => mapper.with_dtype(DataType::Boolean),
102 Time => mapper.with_dtype(DataType::Time),
103 Duration(tu) => mapper.with_dtype(DataType::Duration(*tu)),
104 Date => mapper.with_dtype(DataType::Date),
105 Datetime => mapper.try_map_dtype(|dt| match dt {
106 DataType::Datetime(tu, _) => Ok(DataType::Datetime(*tu, None)),
107 dtype => polars_bail!(ComputeError: "expected Datetime, got {}", dtype),
108 }),
109 Truncate => mapper.with_same_dtype(),
110 #[cfg(feature = "offset_by")]
111 OffsetBy => mapper.with_same_dtype(),
112 #[cfg(feature = "month_start")]
113 MonthStart => mapper.with_same_dtype(),
114 #[cfg(feature = "month_end")]
115 MonthEnd => mapper.with_same_dtype(),
116 #[cfg(feature = "timezones")]
117 BaseUtcOffset => mapper.with_dtype(DataType::Duration(TimeUnit::Milliseconds)),
118 #[cfg(feature = "timezones")]
119 DSTOffset => mapper.with_dtype(DataType::Duration(TimeUnit::Milliseconds)),
120 Round => mapper.with_same_dtype(),
121 Replace => mapper.with_same_dtype(),
122 #[cfg(feature = "timezones")]
123 ReplaceTimeZone(tz, _non_existent) => mapper.map_datetime_dtype_timezone(tz.as_ref()),
124 DatetimeFunction {
125 time_unit,
126 time_zone,
127 } => Ok(Field::new(
128 PlSmallStr::from_static("datetime"),
129 DataType::Datetime(*time_unit, time_zone.clone()),
130 )),
131 Combine(tu) => mapper.try_map_dtype(|dt| match dt {
132 DataType::Datetime(_, tz) => Ok(DataType::Datetime(*tu, tz.clone())),
133 DataType::Date => Ok(DataType::Datetime(*tu, None)),
134 dtype => {
135 polars_bail!(ComputeError: "expected Date or Datetime, got {}", dtype)
136 },
137 }),
138 }
139 }
140
141 pub fn function_options(&self) -> FunctionOptions {
142 use TemporalFunction as T;
143 match self {
144 T::Millennium
145 | T::Century
146 | T::Year
147 | T::IsLeapYear
148 | T::IsoYear
149 | T::Quarter
150 | T::Month
151 | T::Week
152 | T::WeekDay
153 | T::Day
154 | T::OrdinalDay
155 | T::Time
156 | T::Date
157 | T::Datetime
158 | T::Hour
159 | T::Minute
160 | T::Second
161 | T::Millisecond
162 | T::Microsecond
163 | T::Nanosecond
164 | T::TotalDays
165 | T::TotalHours
166 | T::TotalMinutes
167 | T::TotalSeconds
168 | T::TotalMilliseconds
169 | T::TotalMicroseconds
170 | T::TotalNanoseconds
171 | T::ToString(_)
172 | T::TimeStamp(_)
173 | T::CastTimeUnit(_)
174 | T::WithTimeUnit(_) => FunctionOptions::elementwise(),
175 #[cfg(feature = "timezones")]
176 T::ConvertTimeZone(_) => FunctionOptions::elementwise(),
177 #[cfg(feature = "month_start")]
178 T::MonthStart => FunctionOptions::elementwise(),
179 #[cfg(feature = "month_end")]
180 T::MonthEnd => FunctionOptions::elementwise(),
181 #[cfg(feature = "timezones")]
182 T::BaseUtcOffset | T::DSTOffset => FunctionOptions::elementwise(),
183 T::Truncate => FunctionOptions::elementwise(),
184 #[cfg(feature = "offset_by")]
185 T::OffsetBy => FunctionOptions::elementwise(),
186 T::Round => FunctionOptions::elementwise(),
187 T::Replace => FunctionOptions::elementwise(),
188 T::Duration(_) => FunctionOptions::elementwise(),
189 #[cfg(feature = "timezones")]
190 T::ReplaceTimeZone(_, _) => FunctionOptions::elementwise(),
191 T::Combine(_) => FunctionOptions::elementwise(),
192 T::DatetimeFunction { .. } => {
193 FunctionOptions::elementwise().with_flags(|f| f | FunctionFlags::ALLOW_RENAME)
194 },
195 }
196 }
197}
198
199impl Display for TemporalFunction {
200 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
201 use TemporalFunction::*;
202 let s = match self {
203 Millennium => "millennium",
204 Century => "century",
205 Year => "year",
206 IsLeapYear => "is_leap_year",
207 IsoYear => "iso_year",
208 Quarter => "quarter",
209 Month => "month",
210 Week => "week",
211 WeekDay => "weekday",
212 Day => "day",
213 OrdinalDay => "ordinal_day",
214 Time => "time",
215 Date => "date",
216 Datetime => "datetime",
217 Duration(_) => "duration",
218 Hour => "hour",
219 Minute => "minute",
220 Second => "second",
221 Millisecond => "millisecond",
222 Microsecond => "microsecond",
223 Nanosecond => "nanosecond",
224 TotalDays => "total_days",
225 TotalHours => "total_hours",
226 TotalMinutes => "total_minutes",
227 TotalSeconds => "total_seconds",
228 TotalMilliseconds => "total_milliseconds",
229 TotalMicroseconds => "total_microseconds",
230 TotalNanoseconds => "total_nanoseconds",
231 ToString(_) => "to_string",
232 #[cfg(feature = "timezones")]
233 ConvertTimeZone(_) => "convert_time_zone",
234 CastTimeUnit(_) => "cast_time_unit",
235 WithTimeUnit(_) => "with_time_unit",
236 TimeStamp(tu) => return write!(f, "dt.timestamp({tu})"),
237 Truncate => "truncate",
238 #[cfg(feature = "offset_by")]
239 OffsetBy => "offset_by",
240 #[cfg(feature = "month_start")]
241 MonthStart => "month_start",
242 #[cfg(feature = "month_end")]
243 MonthEnd => "month_end",
244 #[cfg(feature = "timezones")]
245 BaseUtcOffset => "base_utc_offset",
246 #[cfg(feature = "timezones")]
247 DSTOffset => "dst_offset",
248 Round => "round",
249 Replace => "replace",
250 #[cfg(feature = "timezones")]
251 ReplaceTimeZone(_, _) => "replace_time_zone",
252 DatetimeFunction { .. } => return write!(f, "dt.datetime"),
253 Combine(_) => "combine",
254 };
255 write!(f, "dt.{s}")
256 }
257}
258
259pub(super) fn millennium(s: &Column) -> PolarsResult<Column> {
260 s.as_materialized_series()
261 .millennium()
262 .map(|ca| ca.into_column())
263}
264pub(super) fn century(s: &Column) -> PolarsResult<Column> {
265 s.as_materialized_series()
266 .century()
267 .map(|ca| ca.into_column())
268}
269pub(super) fn year(s: &Column) -> PolarsResult<Column> {
270 s.as_materialized_series().year().map(|ca| ca.into_column())
271}
272pub(super) fn is_leap_year(s: &Column) -> PolarsResult<Column> {
273 s.as_materialized_series()
274 .is_leap_year()
275 .map(|ca| ca.into_column())
276}
277pub(super) fn iso_year(s: &Column) -> PolarsResult<Column> {
278 s.as_materialized_series()
279 .iso_year()
280 .map(|ca| ca.into_column())
281}
282pub(super) fn month(s: &Column) -> PolarsResult<Column> {
283 s.as_materialized_series()
284 .month()
285 .map(|ca| ca.into_column())
286}
287pub(super) fn quarter(s: &Column) -> PolarsResult<Column> {
288 s.as_materialized_series()
289 .quarter()
290 .map(|ca| ca.into_column())
291}
292pub(super) fn week(s: &Column) -> PolarsResult<Column> {
293 s.as_materialized_series().week().map(|ca| ca.into_column())
294}
295pub(super) fn weekday(s: &Column) -> PolarsResult<Column> {
296 s.as_materialized_series()
297 .weekday()
298 .map(|ca| ca.into_column())
299}
300pub(super) fn day(s: &Column) -> PolarsResult<Column> {
301 s.as_materialized_series().day().map(|ca| ca.into_column())
302}
303pub(super) fn ordinal_day(s: &Column) -> PolarsResult<Column> {
304 s.as_materialized_series()
305 .ordinal_day()
306 .map(|ca| ca.into_column())
307}
308pub(super) fn time(s: &Column) -> PolarsResult<Column> {
309 match s.dtype() {
310 #[cfg(feature = "timezones")]
311 DataType::Datetime(_, Some(_)) => polars_ops::prelude::replace_time_zone(
312 s.datetime().unwrap(),
313 None,
314 &StringChunked::from_iter(std::iter::once("raise")),
315 NonExistent::Raise,
316 )?
317 .cast(&DataType::Time)
318 .map(Column::from),
319 DataType::Datetime(_, _) => s
320 .datetime()
321 .unwrap()
322 .cast(&DataType::Time)
323 .map(Column::from),
324 DataType::Time => Ok(s.clone()),
325 dtype => polars_bail!(ComputeError: "expected Datetime or Time, got {}", dtype),
326 }
327}
328pub(super) fn date(s: &Column) -> PolarsResult<Column> {
329 match s.dtype() {
330 #[cfg(feature = "timezones")]
331 DataType::Datetime(_, Some(_)) => {
332 let mut out = {
333 polars_ops::chunked_array::replace_time_zone(
334 s.datetime().unwrap(),
335 None,
336 &StringChunked::from_iter(std::iter::once("raise")),
337 NonExistent::Raise,
338 )?
339 .cast(&DataType::Date)?
340 };
341 out.set_sorted_flag(s.is_sorted_flag());
347 Ok(out.into())
348 },
349 DataType::Datetime(_, _) => s
350 .datetime()
351 .unwrap()
352 .cast(&DataType::Date)
353 .map(Column::from),
354 DataType::Date => Ok(s.clone()),
355 dtype => polars_bail!(ComputeError: "expected Datetime or Date, got {}", dtype),
356 }
357}
358pub(super) fn datetime(s: &Column) -> PolarsResult<Column> {
359 match s.dtype() {
360 #[cfg(feature = "timezones")]
361 DataType::Datetime(tu, Some(_)) => polars_ops::chunked_array::replace_time_zone(
362 s.datetime().unwrap(),
363 None,
364 &StringChunked::from_iter(std::iter::once("raise")),
365 NonExistent::Raise,
366 )?
367 .cast(&DataType::Datetime(*tu, None))
368 .map(|x| x.into()),
369 DataType::Datetime(tu, _) => s
370 .datetime()
371 .unwrap()
372 .cast(&DataType::Datetime(*tu, None))
373 .map(Column::from),
374 dtype => polars_bail!(ComputeError: "expected Datetime, got {}", dtype),
375 }
376}
377pub(super) fn hour(s: &Column) -> PolarsResult<Column> {
378 s.as_materialized_series().hour().map(|ca| ca.into_column())
379}
380pub(super) fn minute(s: &Column) -> PolarsResult<Column> {
381 s.as_materialized_series()
382 .minute()
383 .map(|ca| ca.into_column())
384}
385pub(super) fn second(s: &Column) -> PolarsResult<Column> {
386 s.as_materialized_series()
387 .second()
388 .map(|ca| ca.into_column())
389}
390pub(super) fn millisecond(s: &Column) -> PolarsResult<Column> {
391 s.as_materialized_series()
392 .nanosecond()
393 .map(|ca| (ca.wrapping_trunc_div_scalar(1_000_000)).into_column())
394}
395pub(super) fn microsecond(s: &Column) -> PolarsResult<Column> {
396 s.as_materialized_series()
397 .nanosecond()
398 .map(|ca| (ca.wrapping_trunc_div_scalar(1_000)).into_column())
399}
400pub(super) fn nanosecond(s: &Column) -> PolarsResult<Column> {
401 s.as_materialized_series()
402 .nanosecond()
403 .map(|ca| ca.into_column())
404}
405#[cfg(feature = "dtype-duration")]
406pub(super) fn total_days(s: &Column) -> PolarsResult<Column> {
407 s.as_materialized_series()
408 .duration()
409 .map(|ca| ca.days().into_column())
410}
411#[cfg(feature = "dtype-duration")]
412pub(super) fn total_hours(s: &Column) -> PolarsResult<Column> {
413 s.as_materialized_series()
414 .duration()
415 .map(|ca| ca.hours().into_column())
416}
417#[cfg(feature = "dtype-duration")]
418pub(super) fn total_minutes(s: &Column) -> PolarsResult<Column> {
419 s.as_materialized_series()
420 .duration()
421 .map(|ca| ca.minutes().into_column())
422}
423#[cfg(feature = "dtype-duration")]
424pub(super) fn total_seconds(s: &Column) -> PolarsResult<Column> {
425 s.as_materialized_series()
426 .duration()
427 .map(|ca| ca.seconds().into_column())
428}
429#[cfg(feature = "dtype-duration")]
430pub(super) fn total_milliseconds(s: &Column) -> PolarsResult<Column> {
431 s.as_materialized_series()
432 .duration()
433 .map(|ca| ca.milliseconds().into_column())
434}
435#[cfg(feature = "dtype-duration")]
436pub(super) fn total_microseconds(s: &Column) -> PolarsResult<Column> {
437 s.as_materialized_series()
438 .duration()
439 .map(|ca| ca.microseconds().into_column())
440}
441#[cfg(feature = "dtype-duration")]
442pub(super) fn total_nanoseconds(s: &Column) -> PolarsResult<Column> {
443 s.as_materialized_series()
444 .duration()
445 .map(|ca| ca.nanoseconds().into_column())
446}
447pub(super) fn timestamp(s: &Column, tu: TimeUnit) -> PolarsResult<Column> {
448 s.as_materialized_series()
449 .timestamp(tu)
450 .map(|ca| ca.into_column())
451}
452pub(super) fn to_string(s: &Column, format: &str) -> PolarsResult<Column> {
453 TemporalMethods::to_string(s.as_materialized_series(), format).map(Column::from)
454}
455
456#[cfg(feature = "timezones")]
457pub(super) fn convert_time_zone(s: &Column, time_zone: &TimeZone) -> PolarsResult<Column> {
458 match s.dtype() {
459 DataType::Datetime(_, _) => {
460 let mut ca = s.datetime()?.clone();
461 ca.set_time_zone(time_zone.clone())?;
462 Ok(ca.into_column())
463 },
464 dtype => polars_bail!(ComputeError: "expected Datetime, got {}", dtype),
465 }
466}
467pub(super) fn with_time_unit(s: &Column, tu: TimeUnit) -> PolarsResult<Column> {
468 match s.dtype() {
469 DataType::Datetime(_, _) => {
470 let mut ca = s.datetime()?.clone();
471 ca.set_time_unit(tu);
472 Ok(ca.into_column())
473 },
474 #[cfg(feature = "dtype-duration")]
475 DataType::Duration(_) => {
476 let mut ca = s.as_materialized_series().duration()?.clone();
477 ca.set_time_unit(tu);
478 Ok(ca.into_column())
479 },
480 dt => polars_bail!(ComputeError: "dtype `{}` has no time unit", dt),
481 }
482}
483pub(super) fn cast_time_unit(s: &Column, tu: TimeUnit) -> PolarsResult<Column> {
484 match s.dtype() {
485 DataType::Datetime(_, _) => {
486 let ca = s.datetime()?;
487 Ok(ca.cast_time_unit(tu).into_column())
488 },
489 #[cfg(feature = "dtype-duration")]
490 DataType::Duration(_) => {
491 let ca = s.as_materialized_series().duration()?;
492 Ok(ca.cast_time_unit(tu).into_column())
493 },
494 dt => polars_bail!(ComputeError: "dtype `{}` has no time unit", dt),
495 }
496}
497
498pub(super) fn truncate(s: &[Column]) -> PolarsResult<Column> {
499 let time_series = &s[0];
500 let every = s[1].str()?;
501
502 let mut out = match time_series.dtype() {
503 DataType::Datetime(_, tz) => match tz {
504 #[cfg(feature = "timezones")]
505 Some(tz) => time_series
506 .datetime()?
507 .truncate(tz.parse::<Tz>().ok().as_ref(), every)?
508 .into_column(),
509 _ => time_series.datetime()?.truncate(None, every)?.into_column(),
510 },
511 DataType::Date => time_series.date()?.truncate(None, every)?.into_column(),
512 dt => polars_bail!(opq = round, got = dt, expected = "date/datetime"),
513 };
514 out.set_sorted_flag(time_series.is_sorted_flag());
515 Ok(out)
516}
517
518#[cfg(feature = "offset_by")]
519pub(super) fn offset_by(s: &[Column]) -> PolarsResult<Column> {
520 impl_offset_by(s[0].as_materialized_series(), s[1].as_materialized_series()).map(Column::from)
521}
522
523#[cfg(feature = "month_start")]
524pub(super) fn month_start(s: &Column) -> PolarsResult<Column> {
525 Ok(match s.dtype() {
526 DataType::Datetime(_, tz) => match tz {
527 #[cfg(feature = "timezones")]
528 Some(tz) => s
529 .datetime()
530 .unwrap()
531 .month_start(tz.parse::<Tz>().ok().as_ref())?
532 .into_column(),
533 _ => s.datetime().unwrap().month_start(None)?.into_column(),
534 },
535 DataType::Date => s.date().unwrap().month_start(None)?.into_column(),
536 dt => polars_bail!(opq = month_start, got = dt, expected = "date/datetime"),
537 })
538}
539
540#[cfg(feature = "month_end")]
541pub(super) fn month_end(s: &Column) -> PolarsResult<Column> {
542 Ok(match s.dtype() {
543 DataType::Datetime(_, tz) => match tz {
544 #[cfg(feature = "timezones")]
545 Some(tz) => s
546 .datetime()
547 .unwrap()
548 .month_end(tz.parse::<Tz>().ok().as_ref())?
549 .into_column(),
550 _ => s.datetime().unwrap().month_end(None)?.into_column(),
551 },
552 DataType::Date => s.date().unwrap().month_end(None)?.into_column(),
553 dt => polars_bail!(opq = month_end, got = dt, expected = "date/datetime"),
554 })
555}
556
557#[cfg(feature = "timezones")]
558pub(super) fn base_utc_offset(s: &Column) -> PolarsResult<Column> {
559 match s.dtype() {
560 DataType::Datetime(time_unit, Some(tz)) => {
561 let tz = tz
562 .parse::<Tz>()
563 .expect("Time zone has already been validated");
564 Ok(base_utc_offset_fn(s.datetime().unwrap(), time_unit, &tz).into_column())
565 },
566 dt => polars_bail!(
567 opq = base_utc_offset,
568 got = dt,
569 expected = "time-zone-aware datetime"
570 ),
571 }
572}
573#[cfg(feature = "timezones")]
574pub(super) fn dst_offset(s: &Column) -> PolarsResult<Column> {
575 match s.dtype() {
576 DataType::Datetime(time_unit, Some(tz)) => {
577 let tz = tz
578 .parse::<Tz>()
579 .expect("Time zone has already been validated");
580 Ok(dst_offset_fn(s.datetime().unwrap(), time_unit, &tz).into_column())
581 },
582 dt => polars_bail!(
583 opq = dst_offset,
584 got = dt,
585 expected = "time-zone-aware datetime"
586 ),
587 }
588}
589
590pub(super) fn round(s: &[Column]) -> PolarsResult<Column> {
591 let time_series = &s[0];
592 let every = s[1].str()?;
593
594 Ok(match time_series.dtype() {
595 DataType::Datetime(_, tz) => match tz {
596 #[cfg(feature = "timezones")]
597 Some(tz) => time_series
598 .datetime()
599 .unwrap()
600 .round(every, tz.parse::<Tz>().ok().as_ref())?
601 .into_column(),
602 _ => time_series
603 .datetime()
604 .unwrap()
605 .round(every, None)?
606 .into_column(),
607 },
608 DataType::Date => time_series
609 .date()
610 .unwrap()
611 .round(every, None)?
612 .into_column(),
613 dt => polars_bail!(opq = round, got = dt, expected = "date/datetime"),
614 })
615}
616
617pub(super) fn replace(s: &[Column]) -> PolarsResult<Column> {
618 let time_series = &s[0];
619 let s_year = &s[1].strict_cast(&DataType::Int32)?;
620 let s_month = &s[2].strict_cast(&DataType::Int8)?;
621 let s_day = &s[3].strict_cast(&DataType::Int8)?;
622 let year = s_year.i32()?;
623 let month = s_month.i8()?;
624 let day = s_day.i8()?;
625
626 match time_series.dtype() {
627 DataType::Datetime(_, _) => {
628 let s_hour = &s[4].strict_cast(&DataType::Int8)?;
629 let s_minute = &s[5].strict_cast(&DataType::Int8)?;
630 let s_second = &s[6].strict_cast(&DataType::Int8)?;
631 let s_microsecond = &s[7].strict_cast(&DataType::Int32)?;
632 let hour = s_hour.i8()?;
633 let minute = s_minute.i8()?;
634 let second = s_second.i8()?;
635 let nanosecond = &(s_microsecond.i32()? * 1_000);
636 let s_ambiguous = &s[8].strict_cast(&DataType::String)?;
637 let ambiguous = s_ambiguous.str()?;
638
639 let out = replace_datetime(
640 time_series.datetime().unwrap(),
641 year,
642 month,
643 day,
644 hour,
645 minute,
646 second,
647 nanosecond,
648 ambiguous,
649 );
650 out.map(|s| s.into_column())
651 },
652 DataType::Date => {
653 let out = replace_date(time_series.date().unwrap(), year, month, day);
654 out.map(|s| s.into_column())
655 },
656 dt => polars_bail!(opq = round, got = dt, expected = "date/datetime"),
657 }
658}