polars_core/chunked_array/temporal/
time.rs1use std::fmt::Write;
2
3use arrow::temporal_conversions::{time64ns_to_time, NANOSECONDS};
4use chrono::Timelike;
5
6use super::*;
7use crate::prelude::*;
8
9const SECONDS_IN_MINUTE: i64 = 60;
10const SECONDS_IN_HOUR: i64 = 3_600;
11
12pub fn time_to_time64ns(time: &NaiveTime) -> i64 {
13 (time.hour() as i64 * SECONDS_IN_HOUR
14 + time.minute() as i64 * SECONDS_IN_MINUTE
15 + time.second() as i64)
16 * NANOSECONDS
17 + time.nanosecond() as i64
18}
19
20impl TimeChunked {
21 pub fn to_string(&self, format: &str) -> StringChunked {
24 let mut ca: StringChunked = self.apply_kernel_cast(&|arr| {
25 let mut buf = String::new();
26 let format = if format == "iso" || format == "iso:strict" {
27 "%T%.9f"
28 } else {
29 format
30 };
31 let mut mutarr = MutablePlString::with_capacity(arr.len());
32
33 for opt in arr.into_iter() {
34 match opt {
35 None => mutarr.push_null(),
36 Some(v) => {
37 buf.clear();
38 let timefmt = time64ns_to_time(*v).format(format);
39 write!(buf, "{timefmt}").unwrap();
40 mutarr.push_value(&buf)
41 },
42 }
43 }
44
45 mutarr.freeze().boxed()
46 });
47
48 ca.rename(self.name().clone());
49 ca
50 }
51
52 pub fn strftime(&self, format: &str) -> StringChunked {
57 self.to_string(format)
58 }
59
60 pub fn as_time_iter(&self) -> impl TrustedLen<Item = Option<NaiveTime>> + '_ {
61 unsafe {
63 self.downcast_iter()
64 .flat_map(|iter| {
65 iter.into_iter()
66 .map(|opt_v| opt_v.copied().map(time64ns_to_time))
67 })
68 .trust_my_length(self.len())
69 }
70 }
71
72 pub fn from_naive_time<I: IntoIterator<Item = NaiveTime>>(name: PlSmallStr, v: I) -> Self {
74 let vals = v
75 .into_iter()
76 .map(|nt| time_to_time64ns(&nt))
77 .collect::<Vec<_>>();
78 Int64Chunked::from_vec(name, vals).into_time()
79 }
80
81 pub fn from_naive_time_options<I: IntoIterator<Item = Option<NaiveTime>>>(
83 name: PlSmallStr,
84 v: I,
85 ) -> Self {
86 let vals = v.into_iter().map(|opt| opt.map(|nt| time_to_time64ns(&nt)));
87 Int64Chunked::from_iter_options(name, vals).into_time()
88 }
89}