1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
//! Unix timestamp.
use std;
use std::ops::Deref;
use std::time::{Duration, SystemTime, UNIX_EPOCH};

use atomic::AtomicI64;

const NO_VALUE: i64 = std::i64::MIN;

/// Unix timestamp in milliseconds.
#[derive(Debug)]
pub struct Timestamp(AtomicI64);
impl Timestamp {
    /// Returns the value of this timestamp.
    pub fn get(&self) -> Option<i64> {
        let v = self.0.get();
        if v == NO_VALUE {
            None
        } else {
            Some(v)
        }
    }

    pub(crate) fn new() -> Self {
        Timestamp(AtomicI64::new(NO_VALUE))
    }
    pub(crate) fn from_value(v: Option<i64>) -> Self {
        Timestamp(AtomicI64::new(v.unwrap_or(NO_VALUE)))
    }
    fn clear(&self) {
        self.0.set(NO_VALUE);
    }
    fn set(&self, timestamp: i64) {
        assert_ne!(timestamp, NO_VALUE);
        self.0.set(timestamp);
    }
    fn set_time(&self, time: SystemTime) {
        fn to_millis(d: Duration) -> i64 {
            d.as_secs() as i64 * 1000 + i64::from(d.subsec_nanos()) / 1000 / 1000
        }
        if let Ok(duration) = time.duration_since(UNIX_EPOCH) {
            self.set(to_millis(duration));
        } else {
            let duration = UNIX_EPOCH.duration_since(time).expect("Never fails");
            self.set(-to_millis(duration));
        }
    }
    fn set_now(&self) {
        self.set_time(SystemTime::now());
    }
}

/// Mutable variant of `Timestamp`.
#[derive(Debug)]
pub struct TimestampMut<'a>(&'a Timestamp);
impl<'a> TimestampMut<'a> {
    /// Sets the value of this timestamp to `timestamp`.
    pub fn set(&mut self, timestamp: i64) {
        self.0.set(timestamp)
    }

    /// Sets the value of this timestamp to the current unixtime in milliseconds.
    pub fn set_now(&mut self) {
        self.0.set_now()
    }

    /// Sets the value of this timestamp to `time`.
    pub fn set_time(&mut self, time: SystemTime) {
        self.0.set_time(time)
    }

    /// Clears the value of this timestamp.
    pub fn clear(&mut self) {
        self.0.clear()
    }

    pub(crate) fn new(inner: &'a Timestamp) -> Self {
        TimestampMut(inner)
    }
}
impl<'a> Deref for TimestampMut<'a> {
    type Target = Timestamp;
    fn deref(&self) -> &Self::Target {
        self.0
    }
}

pub(crate) fn now_unixtime_seconds() -> f64 {
    let now = SystemTime::now();
    if let Ok(d) = now.duration_since(UNIX_EPOCH) {
        duration_to_seconds(d)
    } else {
        let d = UNIX_EPOCH.duration_since(now).expect("Never fails");
        -duration_to_seconds(d)
    }
}

/// Converts `Duration` to `f64` in seconds.
pub fn duration_to_seconds(d: Duration) -> f64 {
    d.as_secs() as f64 + f64::from(d.subsec_nanos()) / 1_000_000_000.0
}