use crate::database_control::*; use chrono::TimeZone; use reqwest::{Client, ClientBuilder}; use serde::Deserialize; use std::time::{SystemTime, UNIX_EPOCH}; use tokio::{join, time::*}; // structure for checking server time and local time #[derive(Debug)] pub struct UserTime { pub server_epoch: u128, // server time in Unix Epoch Time pub local_epoch: u128, // local time where the tradingbot is running in Unix Epoch Time. pub epoch_difference: i64, // epoch difference from server time to local time in Unix Epoch Time. (can be used as RTT) // positive value means server is leading to local, negative value means server is lagging to local. server_ymdhs: String, // human-readable date form of server time in UTC (y: year, m: month, d: day, h: hour, s: second) local_ymdhs: String, // human-readable date form of local time in UTC (y: year, m: month, d: day, h: hour, s: second) last_server_epoch: u128, // the last server epoch until the server is turned off. last_server_ymdhs: String, // the last server date until the server is turned off. } impl UserTime { // make an instance and initialize fields pub fn new() -> UserTime { UserTime { server_epoch: 0, local_epoch: 0, epoch_difference: 0, server_ymdhs: String::new(), local_ymdhs: String::new(), last_server_epoch: 0, last_server_ymdhs: String::from("----"), } } // update all field in Time struct. async fn update( &mut self, client: &Client, ) -> Result<(), Box> { let (servertime, localtime) = join!(Self::get_server_time(&client), Self::get_local_time()); self.server_epoch = servertime?; self.local_epoch = localtime?; self.epoch_difference = Self::get_difference_time(self.server_epoch, self.local_epoch).await; self.server_ymdhs = Self::convert_epoch_to_ymdhs(self.server_epoch); self.local_ymdhs = Self::convert_epoch_to_ymdhs(self.local_epoch); Ok(()) } // to record the last server-on time when request doesn't work. pub async fn update_last_server(&mut self) { self.last_server_epoch = self.server_epoch; if self.server_epoch == 0 { self.last_server_ymdhs = String::from("server has been shutdown before the bot was executed."); } else { self.last_server_ymdhs = self.server_ymdhs.clone(); } } async fn get_server_time( client: &Client, ) -> Result> { #[derive(Deserialize)] struct ServerTime { serverTime: u128, } let mut servertime = ServerTime { serverTime: 0 }; let response = client .get("https://api.binance.com/api/v3/time") .send() .await?; servertime = response.json::().await?; Ok(servertime.serverTime) } // function to get the current local time async fn get_local_time() -> Result { match SystemTime::now().duration_since(UNIX_EPOCH) { Ok(T) => Ok(T.as_millis()), Err(E) => Err(E), } } // function to get the difference time from the local to the server async fn get_difference_time(servertime: u128, localtime: u128) -> i64 { if servertime >= localtime { (servertime - localtime) as i64 } else { 0 - ((localtime - servertime) as i64) } } // function to convert Unix Epoch time of server to human-readable date in UTC fn convert_epoch_to_ymdhs(epoch_time: u128) -> String { let time_i64 = (epoch_time / 1000) as i64; chrono::offset::Utc.timestamp(time_i64, 0).to_string() } } // run time checking and store data into database. pub async fn execute_time_check( usertime: &mut UserTime, client: &Client, ) -> Result<(), Box> { usertime.update(&client).await?; let table_name = String::from("time"); let mut record: Vec<(&str, &str)> = Vec::new(); let condition = vec![("id", "1")]; let server_epoch = usertime.server_epoch.to_string(); let local_epoch = usertime.local_epoch.to_string(); let epoch_difference = usertime.epoch_difference.to_string(); let last_server_epoch = usertime.last_server_epoch.to_string(); record.push(("server_epoch", server_epoch.as_str())); record.push(("local_epoch", local_epoch.as_str())); record.push(("epoch_difference", epoch_difference.as_str())); record.push(("server_ymdhs", usertime.server_ymdhs.as_str())); record.push(("local_ymdhs", usertime.local_ymdhs.as_str())); record.push(("last_server_epoch", last_server_epoch.as_str())); record.push(("last_server_ymdhs", usertime.last_server_ymdhs.as_str())); update_record(&table_name, &record, &condition).await?; // println!("time check 완료"); Ok(()) } impl Clone for UserTime { fn clone(&self) -> Self { UserTime { server_epoch: self.server_epoch, local_epoch: self.local_epoch, epoch_difference: self.epoch_difference, server_ymdhs: self.last_server_ymdhs.clone(), local_ymdhs: self.local_ymdhs.clone(), last_server_epoch: self.last_server_epoch, last_server_ymdhs: self.last_server_ymdhs.clone(), } } }