ps_uuid/methods/
system_time_to_ticks.rs1use std::time::SystemTime;
2
3use crate::{Gregorian, UuidConstructionError, UUID};
4
5impl UUID {
6 pub fn system_time_to_ticks(time: SystemTime) -> Result<u64, UuidConstructionError> {
24 let Ok(duration_since_epoch) = time.duration_since(Gregorian::epoch()) else {
27 return Err(UuidConstructionError::TimestampBeforeEpoch);
28 };
29
30 let ticks = Self::duration_to_ticks(duration_since_epoch)?;
34
35 Ok(ticks)
36 }
37}
38
39#[allow(clippy::cast_possible_truncation)]
40#[cfg(test)]
41mod tests {
42 use std::time::Duration;
43
44 use crate::DurationToTicksError;
45
46 use super::*;
47
48 #[test]
51 fn time_now_is_valid() {
52 let now = SystemTime::now();
54 let result = UUID::system_time_to_ticks(now);
55 assert!(result.is_ok());
56 }
57
58 #[test]
59 fn time_before_gregorian_epoch_fails() {
60 let before_epoch = Gregorian::epoch() - Duration::from_secs(1);
62 assert_eq!(
63 UUID::system_time_to_ticks(before_epoch),
64 Err(UuidConstructionError::TimestampBeforeEpoch)
65 );
66 }
67
68 #[test]
69 fn time_at_gregorian_epoch_is_zero_ticks() {
70 assert_eq!(UUID::system_time_to_ticks(Gregorian::epoch()), Ok(0));
72 }
73
74 #[test]
75 fn time_far_in_future_causes_overflow() {
76 let overflow_nanos = (1u128 << 60) * 100;
79 let overflow_duration = Duration::new(
80 (overflow_nanos / 1_000_000_000) as u64,
81 (overflow_nanos % 1_000_000_000) as u32,
82 );
83 let future_time = Gregorian::epoch() + overflow_duration;
84
85 assert_eq!(
86 UUID::system_time_to_ticks(future_time),
87 Err(UuidConstructionError::TimestampOverflow)
88 );
89 }
90
91 #[test]
94 fn zero_duration_yields_zero_ticks() {
95 let duration = Duration::from_nanos(0);
96 assert_eq!(UUID::duration_to_ticks(duration), Ok(0));
97 }
98
99 #[test]
100 fn maximum_allowed_duration() {
101 let max_ticks = (1u128 << 60) - 1;
102 let nanos = max_ticks * 100;
103 let duration = Duration::new(
104 (nanos / 1_000_000_000) as u64,
105 (nanos % 1_000_000_000) as u32,
106 );
107 assert_eq!(UUID::duration_to_ticks(duration), Ok(max_ticks as u64));
108 }
109
110 #[test]
111 fn duration_that_overflows() {
112 let overflow_ticks = 1u128 << 60;
113 let nanos = overflow_ticks * 100;
114 let duration = Duration::new(
115 (nanos / 1_000_000_000) as u64,
116 (nanos % 1_000_000_000) as u32,
117 );
118 assert_eq!(
119 UUID::duration_to_ticks(duration),
120 Err(DurationToTicksError::TimestampOverflow)
121 );
122 }
123}