sui_graphql_rpc/types/
date_time.rs1use std::str::FromStr;
5
6use async_graphql::*;
7use chrono::{
8 prelude::{DateTime as ChronoDateTime, TimeZone, Utc as ChronoUtc},
9 ParseError as ChronoParseError,
10};
11
12use crate::error::Error;
13
14#[derive(Clone, Debug, Eq, PartialEq)]
17pub(crate) struct DateTime(ChronoDateTime<ChronoUtc>);
18
19impl DateTime {
20 pub fn from_ms(timestamp_ms: i64) -> Result<Self, Error> {
21 ChronoUtc
22 .timestamp_millis_opt(timestamp_ms)
23 .single()
24 .ok_or_else(|| Error::Internal("Cannot convert timestamp into DateTime".to_string()))
25 .map(Self)
26 }
27}
28
29#[Scalar(use_type_description = true)]
32impl ScalarType for DateTime {
33 fn parse(value: Value) -> InputValueResult<Self> {
34 match value {
35 Value::String(s) => DateTime::from_str(&s)
36 .map_err(|e| InputValueError::custom(format!("Error parsing DateTime: {}", e))),
37 _ => Err(InputValueError::expected_type(value)),
38 }
39 }
40
41 fn to_value(&self) -> Value {
42 Value::String(format!("{:?}", self.0))
44 }
45}
46
47impl Description for DateTime {
48 fn description() -> &'static str {
49 "ISO-8601 Date and Time: RFC3339 in UTC with format: YYYY-MM-DDTHH:MM:SS.mmmZ. Note that the milliseconds part is optional, and it may be omitted if its value is 0."
50 }
51}
52
53impl FromStr for DateTime {
54 type Err = ChronoParseError;
55
56 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
57 Ok(DateTime(s.parse::<ChronoDateTime<ChronoUtc>>()?))
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn test_parse() {
67 let dt: &str = "2023-08-19T15:37:24.761850Z";
68 let date_time = DateTime::from_str(dt).unwrap();
69 let Value::String(s) = async_graphql::ScalarType::to_value(&date_time) else {
70 panic!("Invalid date time scalar");
71 };
72 assert_eq!(dt, s);
73
74 let dt: &str = "2023-08-19T15:37:24.700Z";
75 let date_time = DateTime::from_str(dt).unwrap();
76 let Value::String(s) = async_graphql::ScalarType::to_value(&date_time) else {
77 panic!("Invalid date time scalar");
78 };
79 assert_eq!(dt, s);
80
81 let dt: &str = "2023-08-";
82 assert!(DateTime::from_str(dt).is_err());
83 }
84}