proof_of_sql_parser/posql_time/
unit.rsuse super::PoSQLTimestampError;
use core::fmt;
use serde::{Deserialize, Serialize};
#[allow(clippy::module_name_repetitions)]
#[derive(Debug, Clone, Copy, Hash, Serialize, Deserialize, PartialEq, Eq)]
pub enum PoSQLTimeUnit {
Second,
Millisecond,
Microsecond,
Nanosecond,
}
impl From<PoSQLTimeUnit> for u64 {
fn from(value: PoSQLTimeUnit) -> u64 {
match value {
PoSQLTimeUnit::Second => 0,
PoSQLTimeUnit::Millisecond => 3,
PoSQLTimeUnit::Microsecond => 6,
PoSQLTimeUnit::Nanosecond => 9,
}
}
}
impl TryFrom<&str> for PoSQLTimeUnit {
type Error = PoSQLTimestampError;
fn try_from(value: &str) -> Result<Self, PoSQLTimestampError> {
match value {
"0" => Ok(PoSQLTimeUnit::Second),
"3" => Ok(PoSQLTimeUnit::Millisecond),
"6" => Ok(PoSQLTimeUnit::Microsecond),
"9" => Ok(PoSQLTimeUnit::Nanosecond),
_ => Err(PoSQLTimestampError::UnsupportedPrecision {
error: value.into(),
}),
}
}
}
impl fmt::Display for PoSQLTimeUnit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PoSQLTimeUnit::Second => write!(f, "seconds (precision: 0)"),
PoSQLTimeUnit::Millisecond => write!(f, "milliseconds (precision: 3)"),
PoSQLTimeUnit::Microsecond => write!(f, "microseconds (precision: 6)"),
PoSQLTimeUnit::Nanosecond => write!(f, "nanoseconds (precision: 9)"),
}
}
}
#[cfg(test)]
#[allow(deprecated, clippy::missing_panics_doc)]
mod time_unit_tests {
use super::*;
use crate::posql_time::{PoSQLTimestamp, PoSQLTimestampError};
use chrono::{TimeZone, Utc};
#[test]
fn test_valid_precisions() {
assert_eq!(PoSQLTimeUnit::try_from("0"), Ok(PoSQLTimeUnit::Second));
assert_eq!(PoSQLTimeUnit::try_from("3"), Ok(PoSQLTimeUnit::Millisecond));
assert_eq!(PoSQLTimeUnit::try_from("6"), Ok(PoSQLTimeUnit::Microsecond));
assert_eq!(PoSQLTimeUnit::try_from("9"), Ok(PoSQLTimeUnit::Nanosecond));
}
#[test]
fn test_invalid_precision() {
let invalid_precisions = [
"1", "2", "4", "5", "7", "8", "10", "zero", "three", "cat", "-1", "-2",
]; for &value in &invalid_precisions {
let result = PoSQLTimeUnit::try_from(value);
assert!(matches!(
result,
Err(PoSQLTimestampError::UnsupportedPrecision { .. })
));
}
}
#[test]
fn test_rfc3339_timestamp_with_milliseconds() {
let input = "2023-06-26T12:34:56.123Z";
let expected = Utc.ymd(2023, 6, 26).and_hms_milli(12, 34, 56, 123);
let result = PoSQLTimestamp::try_from(input).unwrap();
assert_eq!(result.timeunit(), PoSQLTimeUnit::Millisecond);
assert_eq!(
result.timestamp().timestamp_millis(),
expected.timestamp_millis()
);
}
#[test]
fn test_rfc3339_timestamp_with_microseconds() {
let input = "2023-06-26T12:34:56.123456Z";
let expected = Utc.ymd(2023, 6, 26).and_hms_micro(12, 34, 56, 123_456);
let result = PoSQLTimestamp::try_from(input).unwrap();
assert_eq!(result.timeunit(), PoSQLTimeUnit::Microsecond);
assert_eq!(
result.timestamp().timestamp_micros(),
expected.timestamp_micros()
);
}
#[test]
fn test_rfc3339_timestamp_with_nanoseconds() {
let input = "2023-06-26T12:34:56.123456789Z";
let expected = Utc.ymd(2023, 6, 26).and_hms_nano(12, 34, 56, 123_456_789);
let result = PoSQLTimestamp::try_from(input).unwrap();
assert_eq!(result.timeunit(), PoSQLTimeUnit::Nanosecond);
assert_eq!(
result.timestamp().timestamp_nanos_opt().unwrap(),
expected.timestamp_nanos_opt().unwrap()
);
}
}