use chrono::{DateTime, Local, TimeDelta, TimeZone, Utc};
use core::fmt;
use std::fmt::Display;
use std::num::ParseIntError;
use std::ops::{Add, Sub};
use std::str::FromStr;
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Default,
serde::Serialize,
serde::Deserialize,
)]
pub struct Timestamp(i64);
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Default,
serde::Serialize,
serde::Deserialize,
)]
pub struct TimestampDelta(i64);
impl Timestamp {
pub const fn zero() -> Self {
Self(0)
}
pub const fn as_secs(&self) -> i64 {
self.0 / 1_000_000_000
}
pub const fn as_millis(&self) -> i64 {
self.0 / 1_000_000
}
pub const fn as_micros(&self) -> i64 {
self.0 / 1_000
}
pub const fn as_nanos(&self) -> i64 {
self.0
}
pub fn local(&self) -> DateTime<Local> {
DateTime::<Local>::from(*self)
}
pub fn utc(&self) -> DateTime<Utc> {
DateTime::<Utc>::from(*self)
}
pub const fn from_hours(hours: i64) -> Self {
Self(hours * 60 * 60 * 1_000_000_000)
}
pub const fn from_minutes(minutes: i64) -> Self {
Self(minutes * 60 * 1_000_000_000)
}
pub const fn from_secs(secs: i64) -> Self {
Self(secs * 1_000_000_000)
}
pub const fn from_millis(millis: i64) -> Self {
Self(millis * 1_000_000)
}
pub const fn from_micros(micros: i64) -> Self {
Self(micros * 1_000)
}
pub const fn from_nanos(nanos: i64) -> Self {
Self(nanos)
}
}
impl TimestampDelta {
pub const fn zero() -> Self {
Self(0)
}
pub const fn as_secs(&self) -> i64 {
self.0 / 1_000_000_000
}
pub const fn as_millis(&self) -> i64 {
self.0 / 1_000_000
}
pub const fn as_micros(&self) -> i64 {
self.0 / 1_000
}
pub const fn as_nanos(&self) -> i64 {
self.0
}
pub const fn from_hours(hours: i64) -> Self {
Self(hours * 60 * 60 * 1_000_000_000)
}
pub const fn from_minutes(minutes: i64) -> Self {
Self(minutes * 60 * 1_000_000_000)
}
pub const fn from_secs(secs: i64) -> Self {
Self(secs * 1_000_000_000)
}
pub const fn from_millis(millis: i64) -> Self {
Self(millis * 1_000_000)
}
pub const fn from_micros(micros: i64) -> Self {
Self(micros * 1_000)
}
pub const fn from_nanos(nanos: i64) -> Self {
Self(nanos)
}
}
impl Display for Timestamp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<i64> for Timestamp {
fn from(nanos: i64) -> Self {
Self(nanos)
}
}
impl Add<TimeDelta> for Timestamp {
type Output = Timestamp;
fn add(self, rhs: TimeDelta) -> Self::Output {
Timestamp::from(self.0 + rhs.num_nanoseconds().unwrap())
}
}
impl Add<Timestamp> for Timestamp {
type Output = Timestamp;
fn add(self, rhs: Timestamp) -> Self::Output {
Timestamp::from(self.0 + rhs.0)
}
}
impl Add<TimestampDelta> for Timestamp {
type Output = Timestamp;
fn add(self, rhs: TimestampDelta) -> Self::Output {
Timestamp::from(self.0 + rhs.0)
}
}
impl Sub<TimeDelta> for Timestamp {
type Output = TimestampDelta;
fn sub(self, rhs: TimeDelta) -> Self::Output {
TimestampDelta::from(self.0 - rhs.num_nanoseconds().unwrap())
}
}
impl Sub<Timestamp> for Timestamp {
type Output = TimestampDelta;
fn sub(self, rhs: Timestamp) -> Self::Output {
TimestampDelta::from(self.0 - rhs.0)
}
}
impl FromStr for Timestamp {
type Err = ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let nanos = i64::from_str(s)?;
Ok(Timestamp::from(nanos))
}
}
impl From<DateTime<Utc>> for Timestamp {
fn from(dt: DateTime<Utc>) -> Self {
Self(dt.timestamp_nanos_opt().unwrap())
}
}
impl From<DateTime<Local>> for Timestamp {
fn from(dt: DateTime<Local>) -> Self {
Self(dt.with_timezone(&Utc).timestamp_nanos_opt().unwrap())
}
}
impl From<Timestamp> for DateTime<Utc> {
fn from(ts: Timestamp) -> Self {
Utc.timestamp_nanos(ts.0)
}
}
impl From<Timestamp> for DateTime<Local> {
fn from(ts: Timestamp) -> Self {
let utc: DateTime<Utc> = ts.into();
utc.with_timezone(&Local)
}
}
impl From<Timestamp> for TimeDelta {
fn from(ts: Timestamp) -> Self {
TimeDelta::nanoseconds(ts.0)
}
}
impl Display for TimestampDelta {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<i64> for TimestampDelta {
fn from(nanos: i64) -> Self {
Self(nanos)
}
}
impl Add<TimeDelta> for TimestampDelta {
type Output = TimestampDelta;
fn add(self, rhs: TimeDelta) -> Self::Output {
TimestampDelta::from(self.0 + rhs.num_nanoseconds().unwrap())
}
}
impl Add<TimestampDelta> for TimestampDelta {
type Output = TimestampDelta;
fn add(self, rhs: TimestampDelta) -> Self::Output {
TimestampDelta::from(self.0 + rhs.0)
}
}
impl Sub<TimeDelta> for TimestampDelta {
type Output = TimestampDelta;
fn sub(self, rhs: TimeDelta) -> Self::Output {
TimestampDelta::from(self.0 - rhs.num_nanoseconds().unwrap())
}
}
impl Sub<TimestampDelta> for TimestampDelta {
type Output = TimestampDelta;
fn sub(self, rhs: TimestampDelta) -> Self::Output {
TimestampDelta::from(self.0 - rhs.0)
}
}
impl From<TimeDelta> for TimestampDelta {
fn from(delta: TimeDelta) -> Self {
TimestampDelta::from(delta.num_nanoseconds().unwrap())
}
}
impl From<TimestampDelta> for TimeDelta {
fn from(delta: TimestampDelta) -> Self {
TimeDelta::nanoseconds(delta.0)
}
}