/rust/registry/src/index.crates.io-6f17d22bba15001f/ulid-1.1.4/src/time.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use crate::{bitmask, Ulid}; |
2 | | use std::time::{Duration, SystemTime}; |
3 | | |
4 | | impl Ulid { |
5 | | /// Creates a new Ulid with the current time (UTC) |
6 | | /// |
7 | | /// Using this function to generate Ulids will not guarantee monotonic sort order. |
8 | | /// See [ulid::Generator] for a monotonic sort order. |
9 | | /// # Example |
10 | | /// ```rust |
11 | | /// use ulid::Ulid; |
12 | | /// |
13 | | /// let my_ulid = Ulid::new(); |
14 | | /// ``` |
15 | 0 | pub fn new() -> Ulid { |
16 | 0 | Ulid::from_datetime(crate::time_utils::now()) |
17 | 0 | } |
18 | | |
19 | | /// Creates a new Ulid using data from the given random number generator |
20 | | /// |
21 | | /// # Example |
22 | | /// ```rust |
23 | | /// use rand::prelude::*; |
24 | | /// use ulid::Ulid; |
25 | | /// |
26 | | /// let mut rng = StdRng::from_entropy(); |
27 | | /// let ulid = Ulid::with_source(&mut rng); |
28 | | /// ``` |
29 | 0 | pub fn with_source<R: rand::Rng>(source: &mut R) -> Ulid { |
30 | 0 | Ulid::from_datetime_with_source(crate::time_utils::now(), source) |
31 | 0 | } |
32 | | |
33 | | /// Creates a new Ulid with the given datetime |
34 | | /// |
35 | | /// This can be useful when migrating data to use Ulid identifiers. |
36 | | /// |
37 | | /// This will take the maximum of the `[SystemTime]` argument and `[SystemTime::UNIX_EPOCH]` |
38 | | /// as earlier times are not valid for a Ulid timestamp |
39 | | /// |
40 | | /// # Example |
41 | | /// ```rust |
42 | | /// use std::time::{SystemTime, Duration}; |
43 | | /// use ulid::Ulid; |
44 | | /// |
45 | | /// let ulid = Ulid::from_datetime(SystemTime::now()); |
46 | | /// ``` |
47 | 0 | pub fn from_datetime(datetime: SystemTime) -> Ulid { |
48 | 0 | Ulid::from_datetime_with_source(datetime, &mut rand::thread_rng()) |
49 | 0 | } |
50 | | |
51 | | /// Creates a new Ulid with the given datetime and random number generator |
52 | | /// |
53 | | /// This will take the maximum of the `[SystemTime]` argument and `[SystemTime::UNIX_EPOCH]` |
54 | | /// as earlier times are not valid for a Ulid timestamp |
55 | | /// |
56 | | /// # Example |
57 | | /// ```rust |
58 | | /// use std::time::{SystemTime, Duration}; |
59 | | /// use rand::prelude::*; |
60 | | /// use ulid::Ulid; |
61 | | /// |
62 | | /// let mut rng = StdRng::from_entropy(); |
63 | | /// let ulid = Ulid::from_datetime_with_source(SystemTime::now(), &mut rng); |
64 | | /// ``` |
65 | 0 | pub fn from_datetime_with_source<R>(datetime: SystemTime, source: &mut R) -> Ulid |
66 | 0 | where |
67 | 0 | R: rand::Rng + ?Sized, |
68 | 0 | { |
69 | 0 | let timestamp = datetime |
70 | 0 | .duration_since(SystemTime::UNIX_EPOCH) |
71 | 0 | .unwrap_or(Duration::ZERO) |
72 | 0 | .as_millis(); |
73 | 0 | let timebits = (timestamp & bitmask!(Self::TIME_BITS)) as u64; |
74 | 0 |
|
75 | 0 | let msb = timebits << 16 | u64::from(source.gen::<u16>()); |
76 | 0 | let lsb = source.gen::<u64>(); |
77 | 0 | Ulid::from((msb, lsb)) |
78 | 0 | } |
79 | | |
80 | | /// Gets the datetime of when this Ulid was created accurate to 1ms |
81 | | /// |
82 | | /// # Example |
83 | | /// ```rust |
84 | | /// use std::time::{SystemTime, Duration}; |
85 | | /// use ulid::Ulid; |
86 | | /// |
87 | | /// let dt = SystemTime::now(); |
88 | | /// let ulid = Ulid::from_datetime(dt); |
89 | | /// |
90 | | /// assert!( |
91 | | /// dt + Duration::from_millis(1) >= ulid.datetime() |
92 | | /// && dt - Duration::from_millis(1) <= ulid.datetime() |
93 | | /// ); |
94 | | /// ``` |
95 | 0 | pub fn datetime(&self) -> SystemTime { |
96 | 0 | let stamp = self.timestamp_ms(); |
97 | 0 | SystemTime::UNIX_EPOCH + Duration::from_millis(stamp) |
98 | 0 | } |
99 | | } |
100 | | |
101 | | #[cfg(test)] |
102 | | mod tests { |
103 | | use super::*; |
104 | | |
105 | | #[test] |
106 | | fn test_dynamic() { |
107 | | let ulid = Ulid::new(); |
108 | | let encoded = ulid.to_string(); |
109 | | let ulid2 = Ulid::from_string(&encoded).expect("failed to deserialize"); |
110 | | |
111 | | println!("{}", encoded); |
112 | | println!("{:?}", ulid); |
113 | | println!("{:?}", ulid2); |
114 | | assert_eq!(ulid, ulid2); |
115 | | } |
116 | | |
117 | | #[test] |
118 | | fn test_source() { |
119 | | use rand::rngs::mock::StepRng; |
120 | | let mut source = StepRng::new(123, 0); |
121 | | |
122 | | let u1 = Ulid::with_source(&mut source); |
123 | | let dt = SystemTime::now() + Duration::from_millis(1); |
124 | | let u2 = Ulid::from_datetime_with_source(dt, &mut source); |
125 | | let u3 = Ulid::from_datetime_with_source(dt, &mut source); |
126 | | |
127 | | assert!(u1 < u2); |
128 | | assert_eq!(u2, u3); |
129 | | } |
130 | | |
131 | | #[test] |
132 | | fn test_order() { |
133 | | let dt = SystemTime::now(); |
134 | | let ulid1 = Ulid::from_datetime(dt); |
135 | | let ulid2 = Ulid::from_datetime(dt + Duration::from_millis(1)); |
136 | | assert!(ulid1 < ulid2); |
137 | | } |
138 | | |
139 | | #[test] |
140 | | fn test_datetime() { |
141 | | let dt = SystemTime::now(); |
142 | | let ulid = Ulid::from_datetime(dt); |
143 | | |
144 | | println!("{:?}, {:?}", dt, ulid.datetime()); |
145 | | assert!(ulid.datetime() <= dt); |
146 | | assert!(ulid.datetime() + Duration::from_millis(1) >= dt); |
147 | | } |
148 | | |
149 | | #[test] |
150 | | fn test_timestamp() { |
151 | | let dt = SystemTime::now(); |
152 | | let ulid = Ulid::from_datetime(dt); |
153 | | let ts = dt |
154 | | .duration_since(SystemTime::UNIX_EPOCH) |
155 | | .unwrap() |
156 | | .as_millis(); |
157 | | |
158 | | assert_eq!(u128::from(ulid.timestamp_ms()), ts); |
159 | | } |
160 | | |
161 | | #[test] |
162 | | fn default_is_nil() { |
163 | | assert_eq!(Ulid::default(), Ulid::nil()); |
164 | | } |
165 | | |
166 | | #[test] |
167 | | fn nil_is_at_unix_epoch() { |
168 | | assert_eq!(Ulid::nil().datetime(), SystemTime::UNIX_EPOCH); |
169 | | } |
170 | | |
171 | | #[test] |
172 | | fn truncates_at_unix_epoch() { |
173 | | if let Some(before_epoch) = SystemTime::UNIX_EPOCH.checked_sub(Duration::from_secs(100)) { |
174 | | assert!(before_epoch < SystemTime::UNIX_EPOCH); |
175 | | assert_eq!( |
176 | | Ulid::from_datetime(before_epoch).datetime(), |
177 | | SystemTime::UNIX_EPOCH |
178 | | ); |
179 | | } else { |
180 | | // Prior dates are not representable (e.g. wasm32-wasi) |
181 | | } |
182 | | } |
183 | | } |