rustalib/util/
time_utils.rs1use chrono::{Datelike, NaiveDate, NaiveDateTime, Timelike};
2use polars::prelude::*;
3use std::f64::consts::PI;
4
5pub fn parse_date(date_str: &str) -> Result<NaiveDate, chrono::ParseError> {
15 NaiveDate::parse_from_str(date_str, "%Y-%m-%d")
16}
17
18pub fn format_date(date: &NaiveDate) -> String {
28 date.format("%Y-%m-%d").to_string()
29}
30
31pub fn create_cyclical_time_features(
43 df: &DataFrame,
44 time_column: &str,
45 time_format: &str,
46) -> PolarsResult<Vec<Series>> {
47 let time_series = df.column(time_column)?;
49 let time_strs = time_series.str()?;
50
51 let mut hour_sin = Vec::with_capacity(df.height());
53 let mut hour_cos = Vec::with_capacity(df.height());
54 let mut day_sin = Vec::with_capacity(df.height());
55 let mut day_cos = Vec::with_capacity(df.height());
56
57 let format_str = time_format.replace(" UTC", "");
59
60 for i in 0..df.height() {
61 let time_str = time_strs.get(i).unwrap_or("");
62 let datetime = match NaiveDateTime::parse_from_str(time_str, &format_str) {
63 Ok(dt) => dt,
64 Err(_) => {
65 hour_sin.push(0.0);
67 hour_cos.push(1.0);
68 day_sin.push(0.0);
69 day_cos.push(1.0);
70 continue;
71 }
72 };
73
74 let hour = datetime.hour() as f64;
76 let day = datetime.weekday().num_days_from_monday() as f64;
77
78 hour_sin.push((2.0 * PI * hour / 24.0).sin());
80 hour_cos.push((2.0 * PI * hour / 24.0).cos());
81 day_sin.push((2.0 * PI * day / 7.0).sin());
82 day_cos.push((2.0 * PI * day / 7.0).cos());
83 }
84
85 let result = vec![
87 Series::new("hour_sin".into(), hour_sin),
88 Series::new("hour_cos".into(), hour_cos),
89 Series::new("day_of_week_sin".into(), day_sin),
90 Series::new("day_of_week_cos".into(), day_cos),
91 ];
92
93 Ok(result)
94}