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
use std::time::{SystemTime, UNIX_EPOCH};
use super::GrainId;
impl GrainId {
/// Creates a `GrainId` from a [`Duration`](std::time::Duration) from [`UNIX_EPOCH`] to `timestamp` based on decisecond precision.
///
/// See [`GrainId::from_duration`] and [`GrainId::from_timestamp_since`] for more details.
///
/// # Examples
///
/// ```
/// use chrono::Utc;
/// # use grain_id::*;
///
/// let timestamp = Utc::now();
/// let id = GrainId::from_timestamp_unix(timestamp);
/// assert_eq!(id.to_u64(), ((timestamp.timestamp_millis() / 100) as u64));
/// ```
pub fn from_timestamp_unix<T>(timestamp: T) -> Self
where
T: Into<SystemTime>,
{
Self::from_timestamp_since(timestamp, UNIX_EPOCH)
}
/// Creates a `GrainId` from a [`Duration`](std::time::Duration) from `base_time` to `timestamp` based on decisecond precision.
///
/// See [`GrainId::from_duration`] for more details.
///
/// # Behavior when `timestamp` is earlier than `base_time`
///
/// If `timestamp` is earlier than `base_time`, Returns the value obtained by wrapping substracting the absolute value of the duration from [`NIL`](GrainId::NIL)
///
/// # Examples
///
/// ```
/// use chrono::NaiveDate;
/// # use grain_id::*;
///
/// let base_time = NaiveDate::from_ymd_opt(2025, 1, 1)
/// .unwrap()
/// .and_hms_opt(0, 0, 0)
/// .unwrap()
/// .and_utc();
/// let timestamp = NaiveDate::from_ymd_opt(2025, 11, 28)
/// .unwrap()
/// .and_hms_micro_opt(12, 34, 56, 789)
/// .unwrap()
/// .and_utc();
/// let id = GrainId::from_timestamp_since(timestamp, base_time);
/// assert_eq!(
/// id.to_u64(),
/// (((timestamp - base_time).num_milliseconds() / 100) as u64)
/// );
/// ```
pub fn from_timestamp_since<T, U>(timestamp: T, base_time: U) -> Self
where
T: Into<SystemTime>,
U: Into<SystemTime>,
{
match timestamp.into().duration_since(base_time.into()) {
Ok(x) => Self::from_duration(x),
Err(x) => Self::NIL.wrapping_sub(Self::from_duration(x.duration())),
}
}
/// Creates a `GrainId` from a [`Duration`](std::time::Duration) from [`UNIX_EPOCH`] to [`SystemTime::now()`] based on decisecond precision.
///
/// See [`GrainId::from_duration`] and [`GrainId::from_timestamp_since`] for more details.
pub fn now_unix() -> Self {
Self::from_timestamp_unix(SystemTime::now())
}
/// Creates a `GrainId` from a [`Duration`](std::time::Duration) from `base_time` to [`SystemTime::now()`] based on decisecond precision.
///
/// See [`GrainId::from_duration`] and [`GrainId::from_timestamp_since`] for more details.
pub fn now_since<T>(base_time: T) -> Self
where
T: Into<SystemTime>,
{
Self::from_timestamp_since(SystemTime::now(), base_time)
}
}