use chrono::DateTime;
use chrono::Utc;
use serde::Deserialize;
use serde::Serialize;
use crate::Str;
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Clock {
#[serde(rename = "is_open")]
pub open: bool,
#[serde(rename = "timestamp")]
pub current: DateTime<Utc>,
#[serde(rename = "next_open")]
pub next_open: DateTime<Utc>,
#[serde(rename = "next_close")]
pub next_close: DateTime<Utc>,
}
Endpoint! {
pub Get(()),
Ok => Clock, [
OK,
],
Err => GetError, []
#[inline]
fn path(_input: &Self::Input) -> Str {
"/v2/clock".into()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr as _;
use chrono::Duration;
use serde_json::from_str as from_json;
use serde_json::to_string as to_json;
use test_log::test;
use crate::api::API_BASE_URL;
use crate::api_info::ApiInfo;
use crate::Client;
use crate::RequestError;
#[test]
fn deserialize_serialize_reference_clock() {
let json = r#"{
"timestamp": "2018-04-01T12:00:00.000Z",
"is_open": true,
"next_open": "2018-04-01T12:00:00.000Z",
"next_close": "2018-04-01T12:00:00.000Z"
}"#;
let clock = from_json::<Clock>(&to_json(&from_json::<Clock>(json).unwrap()).unwrap()).unwrap();
assert!(clock.open);
assert_eq!(
clock.next_open,
DateTime::<Utc>::from_str("2018-04-01T12:00:00.000Z").unwrap()
);
}
#[test(tokio::test)]
async fn current_market_clock() {
let api_info = ApiInfo::from_env().unwrap();
let client = Client::new(api_info);
let clock = client.issue::<Get>(&()).await.unwrap();
let now = Utc::now();
assert!(now > clock.current - Duration::hours(1));
assert!(now < clock.current + Duration::hours(1));
assert!(clock.current < clock.next_open);
assert!(clock.current < clock.next_close);
if clock.open {
assert!(clock.next_open > clock.next_close);
} else {
assert!(clock.next_open < clock.next_close);
}
}
#[test(tokio::test)]
#[ignore]
async fn request_clock_with_invalid_credentials() {
let api_info = ApiInfo::from_parts(API_BASE_URL, "invalid", "invalid-too").unwrap();
let client = Client::new(api_info);
let result = client.issue::<Get>(&()).await;
let err = result.unwrap_err();
match err {
RequestError::Endpoint(GetError::AuthenticationFailed(_)) => (),
e => panic!("received unexpected error: {e:?}"),
}
}
}