use std::ops::{Div, Mul};
pub struct Duration {
seconds: i32,
denominator: u32,
}
impl Duration {
pub const fn new(seconds: i32, denominator: u32) -> Duration {
Duration {
seconds,
denominator,
}
}
}
impl Div<i32> for Duration {
type Output = Duration;
#[allow(clippy::suspicious_arithmetic_impl)]
fn div(mut self, mut other: i32) -> Self::Output {
if other.is_negative() {
self.seconds = -self.seconds;
other = -other;
}
Duration {
seconds: self.seconds,
denominator: self.denominator * (other as u32),
}
}
}
impl Mul<i32> for Duration {
type Output = Duration;
fn mul(mut self, mut other: i32) -> Self::Output {
if other.is_negative() {
self.seconds = -self.seconds;
other = -other;
}
Duration {
seconds: self.seconds * (other as i32),
denominator: self.denominator,
}
}
}
impl Display for Duration {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "{}/{}", self.seconds, self.denominator)
}
}
use chrono::{Datelike, TimeZone, Timelike};
use std::fmt::*;
pub const NANOSECOND: Duration = Duration::new(1, 1_000_000_000);
pub const MICROSECOND: Duration = Duration::new(1, 1_000_000);
pub const MILLISECOND: Duration = Duration::new(1, 1_000);
pub const SECOND: Duration = Duration::new(1, 1);
pub const MINUTE: Duration = Duration::new(60, 1);
pub const HOUR: Duration = Duration::new(60 * 60, 1);
pub const DAY: Duration = Duration::new(24 * 60 * 60, 1);
#[repr(u8)]
pub enum Month {
Jan = 1u8,
Feb = 2,
Mar = 3,
Apr = 4,
May = 5,
Jun = 6,
Jul = 7,
Aug = 8,
Sep = 9,
Oct = 10,
Nov = 11,
Dec = 12,
}
#[repr(u8)]
pub enum DayOfWeek {
Sunday = 0u8,
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6,
}
pub struct Clock(chrono::NaiveDateTime);
impl Clock {
pub fn new() -> Self {
Clock(chrono::offset::Utc::now().naive_utc())
}
pub fn utc(
year: i32,
month: u8,
day: u8,
hour: u8,
min: u8,
sec: u8,
) -> Option<Self> {
let date = chrono::offset::Utc
.ymd(year, u32::from(month), u32::from(day))
.and_hms(u32::from(hour), u32::from(min), u32::from(sec));
Some(Clock(date.naive_utc()))
}
pub fn local(
year: i32,
month: u8,
day: u8,
hour: u8,
min: u8,
sec: u8,
) -> Option<Self> {
let date = chrono::offset::Local
.ymd(year, u32::from(month), u32::from(day))
.and_hms(u32::from(hour), u32::from(min), u32::from(sec))
.with_timezone(&chrono::Utc);
Some(Clock(date.naive_utc()))
}
pub fn year(&self) -> i32 {
self.0.year()
}
pub fn month(&self) -> Month {
let month = self.0.month() as u8;
unsafe { std::mem::transmute(month) }
}
pub fn day(&self) -> u8 {
self.0.day() as u8
}
pub fn dayofweek(&self) -> DayOfWeek {
let dayofweek = self.0.weekday().num_days_from_sunday() as u8;
unsafe { std::mem::transmute(dayofweek) }
}
pub fn hour(&self) -> u8 {
self.0.hour() as u8
}
pub fn minute(&self) -> u8 {
self.0.minute() as u8
}
pub fn second(&self) -> u8 {
self.0.second() as u8
}
pub fn nanosecond(&self) -> u32 {
self.0.nanosecond()
}
pub fn since(&self, other: &Self, frac: Duration) -> i64 {
let duration = self.0 - other.0;
let seconds: i64 = duration.num_seconds();
let nanos: i64 = (duration
- chrono::Duration::seconds(duration.num_seconds()))
.num_nanoseconds()
.unwrap();
let frac_den = i128::from(frac.denominator);
let frac_num = i128::from(frac.seconds);
let seconds = i128::from(seconds) * frac_num;
let nanos = i128::from(nanos) * frac_num;
let seconds_remaining = seconds % frac_den; let nanos = nanos + (seconds_remaining * 1_000_000_000);
let nanos = (nanos / frac_den) as i64;
let seconds = (seconds / frac_den) as i64;
seconds + (nanos / 1_000_000_000)
}
}
impl Default for Clock {
fn default() -> Self {
Self::new()
}
}
impl Debug for Clock {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "{}", self.0)
}
}
impl Display for Clock {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(
f,
"{}",
chrono::DateTime::<chrono::Local>::from_utc(
self.0,
chrono::offset::Local.offset_from_utc_datetime(&self.0)
)
.naive_local()
)
}
}