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
use crate::internal_prelude::*;
use crate::time::constants::*;
#[cfg(feature = "radix_engine_fuzzing")]
use arbitrary::Arbitrary;
use sbor::*;

/// Represents a Unix timestamp, capturing the seconds since the unix epoch.
///
/// See also the [`UtcDateTime`](super::UtcDateTime) type which supports conversion to/from `Instant`.
#[cfg_attr(feature = "radix_engine_fuzzing", derive(Arbitrary))]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Categorize, Encode, Decode, BasicDescribe)]
#[sbor(transparent)]
pub struct Instant {
    pub seconds_since_unix_epoch: i64,
}

impl Describe<ScryptoCustomTypeKind> for Instant {
    const TYPE_ID: RustTypeId =
        RustTypeId::WellKnown(well_known_scrypto_custom_types::INSTANT_TYPE);

    fn type_data() -> ScryptoTypeData<RustTypeId> {
        well_known_scrypto_custom_types::instant_type_data()
    }
}

impl Instant {
    pub fn new(seconds_since_unix_epoch: i64) -> Instant {
        Instant {
            seconds_since_unix_epoch,
        }
    }

    pub fn compare(&self, other: Instant, operator: TimeComparisonOperator) -> bool {
        let self_seconds = self.seconds_since_unix_epoch;
        let other_seconds = other.seconds_since_unix_epoch;
        match operator {
            TimeComparisonOperator::Eq => self_seconds == other_seconds,
            TimeComparisonOperator::Lt => self_seconds < other_seconds,
            TimeComparisonOperator::Lte => self_seconds <= other_seconds,
            TimeComparisonOperator::Gt => self_seconds > other_seconds,
            TimeComparisonOperator::Gte => self_seconds >= other_seconds,
        }
    }

    pub fn add_days(&self, days_to_add: i64) -> Option<Instant> {
        days_to_add
            .checked_mul(SECONDS_IN_A_DAY)
            .and_then(|to_add| self.seconds_since_unix_epoch.checked_add(to_add))
            .map(Instant::new)
    }

    pub fn add_hours(&self, hours_to_add: i64) -> Option<Instant> {
        hours_to_add
            .checked_mul(SECONDS_IN_AN_HOUR)
            .and_then(|to_add| self.seconds_since_unix_epoch.checked_add(to_add))
            .map(Instant::new)
    }

    pub fn add_minutes(&self, minutes_to_add: i64) -> Option<Instant> {
        minutes_to_add
            .checked_mul(SECONDS_IN_A_MINUTE)
            .and_then(|to_add| self.seconds_since_unix_epoch.checked_add(to_add))
            .map(Instant::new)
    }

    pub fn add_seconds(&self, seconds_to_add: i64) -> Option<Instant> {
        self.seconds_since_unix_epoch
            .checked_add(seconds_to_add)
            .map(Instant::new)
    }
}

#[derive(Sbor, Copy, Clone, Debug, Eq, PartialEq)]
pub enum TimeComparisonOperator {
    Eq,
    Lt,
    Lte,
    Gt,
    Gte,
}