clickhouse_data_type/
date_time64.rs

1use core::num::ParseIntError;
2
3use chrono_tz::Tz;
4use pest::iterators::Pairs;
5
6use crate::{type_name_parser::Rule, ParseError};
7
8const PRECISION_MAX: usize = 9;
9
10#[derive(PartialEq, Eq, Debug, Clone)]
11pub struct DateTime64Precision(pub usize);
12impl TryFrom<&str> for DateTime64Precision {
13    type Error = ParseError;
14    fn try_from(s: &str) -> Result<Self, Self::Error> {
15        let n: usize = s
16            .parse()
17            .map_err(|err: ParseIntError| ParseError::ValueInvalid(err.to_string()))?;
18
19        if n > PRECISION_MAX {
20            return Err(ParseError::ValueInvalid(
21                "invalid datetime64 precision".to_string(),
22            ));
23        }
24
25        Ok(Self(n))
26    }
27}
28
29pub(crate) fn get_precision_and_timezone(
30    mut date_time64_pairs: Pairs<'_, Rule>,
31) -> Result<(DateTime64Precision, Option<Tz>), ParseError> {
32    let precision_pair = date_time64_pairs.next().ok_or(ParseError::Unknown)?;
33    let precision = DateTime64Precision::try_from(precision_pair.as_str())?;
34
35    let timezone = if let Some(pair_timezone) = date_time64_pairs.next() {
36        Some(
37            pair_timezone
38                .as_str()
39                .parse::<Tz>()
40                .map_err(|err: &str| ParseError::ValueInvalid(err.to_string()))?,
41        )
42    } else {
43        None
44    };
45
46    Ok((precision, timezone))
47}