1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
//! GraphQL support for [`chrono-tz`] crate types.
//!
//! # Supported types
//!
//! | Rust type | Format | GraphQL scalar |
//! |-----------|--------------------|----------------|
//! | [`Tz`] | [IANA database][1] | `TimeZone` |
//!
//! [`chrono-tz`]: chrono_tz
//! [`Tz`]: chrono_tz::Tz
//! [1]: http://www.iana.org/time-zones
use crate::{graphql_scalar, InputValue, ScalarValue, Value};
/// Timezone based on [`IANA` database][1].
///
/// See ["List of tz database time zones"][2] `TZ database name` column for
/// available names.
///
/// See also [`chrono_tz::Tz`][3] for detals.
///
/// [1]: https://www.iana.org/time-zones
/// [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
/// [3]: https://docs.rs/chrono-tz/latest/chrono_tz/enum.Tz.html
#[graphql_scalar(with = tz, parse_token(String))]
pub type TimeZone = chrono_tz::Tz;
mod tz {
use super::*;
pub(super) fn to_output<S: ScalarValue>(v: &TimeZone) -> Value<S> {
Value::scalar(v.name().to_owned())
}
pub(super) fn from_input<S: ScalarValue>(v: &InputValue<S>) -> Result<TimeZone, String> {
v.as_string_value()
.ok_or_else(|| format!("Expected `String`, found: {v}"))
.and_then(|s| {
s.parse::<TimeZone>()
.map_err(|e| format!("Failed to parse `TimeZone`: {e}"))
})
}
}
#[cfg(test)]
mod test {
use super::TimeZone;
mod from_input_value {
use super::TimeZone;
use crate::{graphql_input_value, FromInputValue, InputValue, IntoFieldError};
fn tz_input_test(raw: &'static str, expected: Result<TimeZone, &str>) {
let input: InputValue = graphql_input_value!((raw));
let parsed = FromInputValue::from_input_value(&input);
assert_eq!(
parsed.as_ref(),
expected.map_err(IntoFieldError::into_field_error).as_ref(),
);
}
#[test]
fn europe_zone() {
tz_input_test("Europe/London", Ok(chrono_tz::Europe::London));
}
#[test]
fn etc_minus() {
tz_input_test("Etc/GMT-3", Ok(chrono_tz::Etc::GMTMinus3));
}
mod invalid {
use super::tz_input_test;
#[test]
fn forward_slash() {
tz_input_test(
"Abc/Xyz",
Err("Failed to parse `TimeZone`: received invalid timezone"),
);
}
#[test]
fn number() {
tz_input_test(
"8086",
Err("Failed to parse `TimeZone`: received invalid timezone"),
);
}
#[test]
fn no_forward_slash() {
tz_input_test(
"AbcXyz",
Err("Failed to parse `TimeZone`: received invalid timezone"),
);
}
}
}
}