1use core::fmt;
4use core::time::Duration;
5use der::asn1::{GeneralizedTime, UtcTime};
6use der::{Choice, DateTime, Sequence, ValueOrd};
7
8#[cfg(feature = "std")]
9use std::time::SystemTime;
10
11#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
25#[derive(Choice, Copy, Clone, Debug, Eq, PartialEq, ValueOrd)]
26pub enum Time {
27 #[asn1(type = "UTCTime")]
32 UtcTime(UtcTime),
33
34 #[asn1(type = "GeneralizedTime")]
36 GeneralTime(GeneralizedTime),
37}
38
39impl Time {
40 pub const INFINITY: Time =
42 Time::GeneralTime(GeneralizedTime::from_date_time(DateTime::INFINITY));
43
44 pub fn to_unix_duration(self) -> Duration {
46 match self {
47 Time::UtcTime(t) => t.to_unix_duration(),
48 Time::GeneralTime(t) => t.to_unix_duration(),
49 }
50 }
51
52 pub fn to_date_time(&self) -> DateTime {
54 match self {
55 Time::UtcTime(t) => t.to_date_time(),
56 Time::GeneralTime(t) => t.to_date_time(),
57 }
58 }
59
60 #[cfg(feature = "std")]
62 pub fn to_system_time(&self) -> SystemTime {
63 match self {
64 Time::UtcTime(t) => t.to_system_time(),
65 Time::GeneralTime(t) => t.to_system_time(),
66 }
67 }
68
69 #[cfg(feature = "builder")]
72 pub(crate) fn rfc5280_adjust_utc_time(&mut self) -> der::Result<()> {
73 if let Time::GeneralTime(t) = self {
74 let date = t.to_date_time();
75 if date.year() <= UtcTime::MAX_YEAR {
76 *self = Time::UtcTime(UtcTime::from_date_time(date)?);
77 }
78 }
79
80 Ok(())
81 }
82}
83
84impl fmt::Display for Time {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 write!(f, "{}", self.to_date_time())
87 }
88}
89
90impl From<UtcTime> for Time {
91 fn from(time: UtcTime) -> Time {
92 Time::UtcTime(time)
93 }
94}
95
96impl From<GeneralizedTime> for Time {
97 fn from(time: GeneralizedTime) -> Time {
98 Time::GeneralTime(time)
99 }
100}
101
102#[cfg(feature = "std")]
103impl From<Time> for SystemTime {
104 fn from(time: Time) -> SystemTime {
105 time.to_system_time()
106 }
107}
108
109#[cfg(feature = "std")]
110impl From<&Time> for SystemTime {
111 fn from(time: &Time) -> SystemTime {
112 time.to_system_time()
113 }
114}
115
116#[cfg(feature = "std")]
117impl TryFrom<SystemTime> for Time {
118 type Error = der::Error;
119
120 fn try_from(time: SystemTime) -> der::Result<Time> {
121 Ok(GeneralizedTime::try_from(time)?.into())
122 }
123}
124
125#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
135#[derive(Copy, Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)]
136pub struct Validity {
137 pub not_before: Time,
139
140 pub not_after: Time,
142}
143
144impl Validity {
145 #[cfg(feature = "std")]
147 pub fn from_now(duration: Duration) -> der::Result<Self> {
148 let now = SystemTime::now();
149 let then = now + duration;
150
151 Ok(Self {
152 not_before: Time::try_from(now)?,
153 not_after: Time::try_from(then)?,
154 })
155 }
156}