Skip to main content

polars_core/chunked_array/temporal/
conversion.rs

1use chrono::*;
2use polars_arrow::temporal_conversions::*;
3
4use crate::prelude::*;
5
6pub(crate) const NS_IN_DAY: i64 = 86_400_000_000_000;
7pub(crate) const US_IN_DAY: i64 = 86_400_000_000;
8pub(crate) const MS_IN_DAY: i64 = 86_400_000;
9pub(crate) const SECONDS_IN_DAY: i64 = 86_400;
10
11impl From<&AnyValue<'_>> for NaiveDateTime {
12    fn from(v: &AnyValue) -> Self {
13        match v {
14            #[cfg(feature = "dtype-date")]
15            AnyValue::Date(v) => date32_to_datetime(*v),
16            #[cfg(feature = "dtype-datetime")]
17            AnyValue::Datetime(v, tu, _) => tu.timestamp_to_datetime(*v),
18            _ => panic!("can only convert date/datetime to NaiveDateTime"),
19        }
20    }
21}
22
23impl From<&AnyValue<'_>> for NaiveTime {
24    fn from(v: &AnyValue) -> Self {
25        match v {
26            #[cfg(feature = "dtype-time")]
27            AnyValue::Time(v) => time64ns_to_time(*v),
28            _ => panic!("can only convert date/datetime to NaiveTime"),
29        }
30    }
31}
32
33// Used by lazy for literal conversion
34pub fn datetime_to_timestamp_ns(v: NaiveDateTime) -> i64 {
35    let us = v.and_utc().timestamp() * 1_000_000_000; //nanos
36    us + v.and_utc().timestamp_subsec_nanos() as i64
37}
38
39pub fn datetime_to_timestamp_ms(v: NaiveDateTime) -> i64 {
40    v.and_utc().timestamp_millis()
41}
42
43pub fn datetime_to_timestamp_us(v: NaiveDateTime) -> i64 {
44    let us = v.and_utc().timestamp() * 1_000_000;
45    us + v.and_utc().timestamp_subsec_micros() as i64
46}
47
48pub(crate) fn naive_datetime_to_date(v: NaiveDateTime) -> i32 {
49    (datetime_to_timestamp_ms(v) / (MILLISECONDS * SECONDS_IN_DAY)) as i32
50}
51
52pub fn get_strftime_format(fmt: &str, dtype: &DataType) -> PolarsResult<String> {
53    if fmt == "polars" && !matches!(dtype, DataType::Duration(_)) {
54        polars_bail!(InvalidOperation: "'polars' is not a valid `to_string` format for {} dtype expressions", dtype);
55    } else {
56        let format_string = if fmt != "iso" && fmt != "iso:strict" {
57            fmt.to_string()
58        } else {
59            let sep = if fmt == "iso" { " " } else { "T" };
60            #[allow(unreachable_code)]
61            match dtype {
62                #[cfg(feature = "dtype-datetime")]
63                DataType::Datetime(tu, tz) => match (tu, tz.is_some()) {
64                    (TimeUnit::Milliseconds, true) => format!("%F{sep}%T%.3f%:z"),
65                    (TimeUnit::Milliseconds, false) => format!("%F{sep}%T%.3f"),
66                    (TimeUnit::Microseconds, true) => format!("%F{sep}%T%.6f%:z"),
67                    (TimeUnit::Microseconds, false) => format!("%F{sep}%T%.6f"),
68                    (TimeUnit::Nanoseconds, true) => format!("%F{sep}%T%.9f%:z"),
69                    (TimeUnit::Nanoseconds, false) => format!("%F{sep}%T%.9f"),
70                },
71                #[cfg(feature = "dtype-date")]
72                DataType::Date => "%F".to_string(),
73                #[cfg(feature = "dtype-time")]
74                DataType::Time => "%T%.f".to_string(),
75                _ => {
76                    let err = format!(
77                        "invalid call to `get_strftime_format`; fmt={fmt:?}, dtype={dtype}"
78                    );
79                    unimplemented!("{}", err)
80                },
81            }
82        };
83        Ok(format_string)
84    }
85}