athena_rs 1.1.0

Database gateway API
Documentation
use chrono::{DateTime, Datelike, Duration, Timelike, Utc};
use serde_json::Value;
use std::collections::HashMap;

use crate::data::DataTimeseries;

// implementation of the group_by_interval function
/// Groups the data by the specified interval (hour, day, week, year) based on the date key.
/// The function takes a JSON array of objects and groups them by the specified interval.
///     
impl DataTimeseries {
    pub fn group_by_interval(
        &self,
        data: &Value,
        date_key: &str,
        interval: &str,
    ) -> HashMap<String, Vec<Value>> {
        group_by_interval(data, date_key, interval)
    }
}

pub fn group_by_interval(
    data: &Value,
    date_key: &str,
    interval: &str,
) -> HashMap<String, Vec<Value>> {
    let mut grouped_data: HashMap<String, Vec<Value>> = HashMap::new();

    if let Value::Array(items) = data {
        for item in items {
            if let Some(date_value) = item.get(date_key) {
                if let Some(date_str) = date_value.as_str() {
                    if let Ok(date) = DateTime::parse_from_rfc3339(date_str) {
                        let date: DateTime<Utc> = date.with_timezone(&Utc);
                        let key: String = match interval {
                            "hour" => format!(
                                "{:04}-{:02}-{:02} {:02}:00",
                                date.year(),
                                date.month(),
                                date.day(),
                                date.hour()
                            ),
                            "day" => {
                                format!("{:04}-{:02}-{:02}", date.year(), date.month(), date.day())
                            }
                            "week" => {
                                let week_start = date
                                    - Duration::days(date.weekday().num_days_from_monday() as i64);
                                format!(
                                    "Week of {:04}-{:02}-{:02}",
                                    week_start.year(),
                                    week_start.month(),
                                    week_start.day()
                                )
                            }
                            "year" => format!("{:04}", date.year()),
                            _ => continue,
                        };

                        grouped_data
                            .entry(key)
                            .or_insert_with(Vec::new)
                            .push(item.clone());
                    }
                }
            }
        }
    }

    grouped_data
}