use std::ops::{Add, Sub};
use chrono;
use chrono::Timelike;
use crate::IResult;
#[derive(serde::Deserialize, serde::Serialize, Clone, Copy, PartialEq, Eq)]
pub struct TimeInt {
ticks: i32,
}
impl TimeInt {
pub fn new(ticks: i32) -> Self {
if ticks < TimeI32Const::MinTicks {
return Self::min();
}
if ticks > TimeI32Const::MaxTicks {
return Self::max();
}
TimeInt { ticks }
}
pub fn now() -> Self {
let now = chrono::prelude::Local::now();
let millisec = now.nanosecond() as i32 / 1000_000;
let ticks = now.hour() as i32 * TimeI32Const::TicksPerHour
+ now.minute() as i32 * TimeI32Const::TicksPerMinute
+ now.second() as i32 * TimeI32Const::TicksPerSecond
+ millisec;
Self { ticks }
}
pub fn fromHmsS(hour: i32, minute: i32, second: i32, millisec: i32) -> IResult<Self> {
if hour > 23 {
return Err(format!("TimeInt::Ctor: Hour {} is not in [0 ~ 23]", hour))?;
}
if minute > 59 {
return Err(format!(
"TimeInt::Ctor: Minute {} is not in [0 ~ 59]",
minute
))?;
}
if second > 59 {
return Err(format!(
"TimeInt::Ctor: Second {} is not in [0 ~ 59]",
second
))?;
}
if millisec > 999 {
return Err(format!(
"TimeInt::Ctor: Millisec {} is not in [0 ~ 999]",
millisec
))?;
}
let ticks = hour * TimeI32Const::TicksPerHour
+ minute * TimeI32Const::TicksPerMinute
+ second * TimeI32Const::TicksPerSecond
+ millisec;
Ok(TimeInt { ticks })
}
pub fn fromInt9(time9: i32) -> IResult<Self> {
let hour = time9 / 1_00_00_000;
let mm_ss_SSS = time9 % 1_00_00_000;
let minute = mm_ss_SSS / 100_000;
let ss_SSS = mm_ss_SSS % 100_000;
return TimeInt::fromHmsS(hour, minute, ss_SSS / 1000, ss_SSS % 1000);
}
pub fn from_string9_safe(time9: &str) -> Self {
if time9.len() != 9 {
error!("Error time_int string: {}", time9);
return TimeInt::min();
}
let i_time9 = match time9.parse::<i32>() {
Ok(v) => v,
Err(_) => {
error!("Error time_int string: {}", time9);
return TimeInt::min();
},
};
Self::fromInt9(i_time9).unwrap_or_else(|_| Default::default())
}
pub fn fromInt9_safe(time9: i32) -> Self {
Self::fromInt9(time9).unwrap_or_else(|_| Default::default())
}
pub fn fromLong17_safe(date_time: i64) -> Self {
let tm9 = date_time % 10_0000_0000;
let me = Self::fromInt9(tm9 as i32).unwrap_or_else(|_| Default::default());
me
}
}
impl Add for TimeInt {
type Output = Self;
fn add(self, other: Self) -> Self {
let ticks = self.ticks + other.ticks;
Self::new(ticks)
}
}
impl Sub for TimeInt {
type Output = Self;
fn sub(self, other: Self) -> Self {
let ticks = self.ticks - other.ticks;
Self::new(ticks)
}
}
impl std::default::Default for TimeInt {
fn default() -> Self {
TimeInt::min()
}
}
impl std::fmt::Display for TimeInt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{:0>2}:{:0>2}:{:0>2}-{:0>3}",
self.hour(),
self.minute(),
self.second(),
self.millisecond()
)
}
}
impl std::fmt::Debug for TimeInt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TimeInt").field("ticks", &self.ticks).field("friendly", &self.to_string9b()).finish()
}
}
pub mod TimeI32Const {
pub const TicksPerSecond: i32 = 1000;
pub const TicksPerMinute: i32 = TicksPerSecond * 60;
pub const TicksPerHour: i32 = TicksPerMinute * 60;
pub const TicksPerDay: i32 = TicksPerHour * 24;
pub const MinTicks: i32 = 0;
pub const MaxTicks: i32 = 86_399_999;
}
impl TimeInt {
pub fn min() -> Self {
TimeInt {
ticks: TimeI32Const::MinTicks,
}
}
pub fn max() -> Self {
TimeInt {
ticks: TimeI32Const::MaxTicks,
}
}
}
impl TimeInt {
pub fn ticks(&self) -> i32 {
self.ticks
}
pub fn hour(&self) -> i32 {
self.ticks / TimeI32Const::TicksPerHour
}
pub fn minute(&self) -> i32 {
(self.ticks / TimeI32Const::TicksPerMinute) % 60
}
pub fn second(&self) -> i32 {
(self.ticks / TimeI32Const::TicksPerSecond) % 60
}
pub fn millisecond(&self) -> i32 {
self.ticks % TimeI32Const::TicksPerSecond
}
pub fn milliseconds_from(&self, tm_before: &Self) -> i32 {
self.ticks as i32 - tm_before.ticks as i32
}
pub fn seconds_from(&self, tm_before: &Self) -> f64 {
(self.ticks - tm_before.ticks) as f64 / 1000_f64
}
pub fn to_int4(&self) -> i32 {
let hour = self.ticks / TimeI32Const::TicksPerHour;
let minute = (self.ticks / TimeI32Const::TicksPerMinute) % 60;
hour * 100 + minute
}
pub fn to_int6(&self) -> i32 {
let hour = self.ticks / TimeI32Const::TicksPerHour;
let minute = (self.ticks / TimeI32Const::TicksPerMinute) % 60;
let second = (self.ticks / TimeI32Const::TicksPerSecond) % 60;
hour * 100_00 + minute * 100 + second
}
pub fn to_int9(&self) -> i32 {
let hour = self.ticks / TimeI32Const::TicksPerHour;
let minute = (self.ticks / TimeI32Const::TicksPerMinute) % 60;
let second = (self.ticks / TimeI32Const::TicksPerSecond) % 60;
let millisec = self.ticks % TimeI32Const::TicksPerSecond;
hour * 100_00_000 + minute * 100_000 + second * 1000 + millisec
}
pub fn to_string6(&self) -> String {
let hour = self.ticks / TimeI32Const::TicksPerHour;
let minute = (self.ticks / TimeI32Const::TicksPerMinute) % 60;
let second = (self.ticks / TimeI32Const::TicksPerSecond) % 60;
format!("{:02}{:02}{:02}", hour, minute, second)
}
pub fn to_string6b(&self) -> String {
let hour = self.ticks / TimeI32Const::TicksPerHour;
let minute = (self.ticks / TimeI32Const::TicksPerMinute) % 60;
let second = (self.ticks / TimeI32Const::TicksPerSecond) % 60;
format!("{:02}:{:02}:{:02}", hour, minute, second)
}
pub fn to_string9(&self) -> String {
let hour = self.ticks / TimeI32Const::TicksPerHour;
let minute = (self.ticks / TimeI32Const::TicksPerMinute) % 60;
let second = (self.ticks / TimeI32Const::TicksPerSecond) % 60;
let millisec = self.ticks % TimeI32Const::TicksPerSecond;
format!("{:02}{:02}{:02}{:03}", hour, minute, second, millisec)
}
pub fn to_string9b(&self) -> String {
let hour = self.ticks / TimeI32Const::TicksPerHour;
let minute = (self.ticks / TimeI32Const::TicksPerMinute) % 60;
let second = (self.ticks / TimeI32Const::TicksPerSecond) % 60;
let millisec = self.ticks % TimeI32Const::TicksPerSecond;
format!("{:02}:{:02}:{:02}-{:03}", hour, minute, second, millisec)
}
}
#[test]
fn test_to_int9() {
let now = TimeInt::now();
let now = now.to_int9();
println!("now: {now}");
}
#[test]
fn test_from_int9() {
let r = TimeInt::fromInt9(1_23_45_678);
println!("{:?}", r);
let r = TimeInt::fromInt9(11_23_45_678);
println!("{:?}", r);
let r = TimeInt::fromInt9(1_02_03_004);
println!("{:?}", r);
let r = TimeInt::fromInt9(11_02_03_004);
println!("{:?}", r);
let r = TimeInt::fromInt9(12_02_03_004);
println!("{:?}", r);
let r = TimeInt::fromInt9(00_01_02_003);
println!("{:?}", r);
let r = TimeInt::fromInt9(00_11_22_333);
println!("{:?}", r);
}