@@ -6,7 +6,7 @@ pub struct Instant(Duration);
6
6
/// When a Timezone is specified, the stored Duration is in UTC. If timezone is unspecified, then
7
7
/// the timezone is assumed to be in UTC.
8
8
///
9
- /// UEFI SystemTime is stored as Duration from 1900-01-01-00:00:00
9
+ /// UEFI SystemTime is stored as Duration from 1900-01-01-00:00:00 with timezone -1440 as anchor
10
10
#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Debug , Hash ) ]
11
11
pub struct SystemTime ( Duration ) ;
12
12
@@ -24,6 +24,20 @@ pub const UNIX_EPOCH: SystemTime = SystemTime::from_uefi(r_efi::efi::Time {
24
24
pad2 : 0 ,
25
25
} ) ;
26
26
27
+ const MAX_UEFI_TIME : SystemTime = SystemTime :: from_uefi ( r_efi:: efi:: Time {
28
+ year : 9999 ,
29
+ month : 12 ,
30
+ day : 31 ,
31
+ hour : 23 ,
32
+ minute : 59 ,
33
+ second : 59 ,
34
+ nanosecond : 999_999_999 ,
35
+ timezone : 1440 ,
36
+ daylight : 0 ,
37
+ pad1 : 0 ,
38
+ pad2 : 0 ,
39
+ } ) ;
40
+
27
41
impl Instant {
28
42
pub fn now ( ) -> Instant {
29
43
// If we have a timestamp protocol, use it.
@@ -56,6 +70,7 @@ impl SystemTime {
56
70
Self ( system_time_internal:: from_uefi ( & t) )
57
71
}
58
72
73
+ #[ expect( dead_code) ]
59
74
pub ( crate ) const fn to_uefi ( self , timezone : i16 , daylight : u8 ) -> Option < r_efi:: efi:: Time > {
60
75
system_time_internal:: to_uefi ( & self . 0 , timezone, daylight)
61
76
}
@@ -73,14 +88,11 @@ impl SystemTime {
73
88
let temp = Self ( self . 0 . checked_add ( * other) ?) ;
74
89
75
90
// Check if can be represented in UEFI
76
- if temp. to_uefi ( 0 , 0 ) . is_some ( ) { Some ( temp) } else { None }
91
+ if temp <= MAX_UEFI_TIME { Some ( temp) } else { None }
77
92
}
78
93
79
94
pub fn checked_sub_duration ( & self , other : & Duration ) -> Option < SystemTime > {
80
- let temp = Self ( self . 0 . checked_sub ( * other) ?) ;
81
-
82
- // Check if can be represented in UEFI
83
- if temp. to_uefi ( 0 , 0 ) . is_some ( ) { Some ( temp) } else { None }
95
+ self . 0 . checked_sub ( * other) . map ( Self )
84
96
}
85
97
}
86
98
@@ -113,8 +125,19 @@ pub(crate) mod system_time_internal {
113
125
}
114
126
115
127
pub ( crate ) const fn from_uefi ( t : & Time ) -> Duration {
116
- assert ! ( t. month <= 12 ) ;
117
- assert ! ( t. month != 0 ) ;
128
+ assert ! ( t. month <= 12 && t. month != 0 ) ;
129
+ assert ! ( t. year >= 1900 && t. year <= 9999 ) ;
130
+ assert ! ( t. day <= 31 && t. day != 0 ) ;
131
+
132
+ assert ! ( t. second < 60 ) ;
133
+ assert ! ( t. minute < 60 ) ;
134
+ assert ! ( t. hour < 24 ) ;
135
+ assert ! ( t. nanosecond < 1_000_000_000 ) ;
136
+
137
+ assert ! (
138
+ ( t. timezone <= 1440 && t. timezone >= -1440 )
139
+ || t. timezone == r_efi:: efi:: UNSPECIFIED_TIMEZONE
140
+ ) ;
118
141
119
142
const YEAR_BASE : u32 = 4800 ; /* Before min year, multiple of 400. */
120
143
@@ -148,17 +171,13 @@ pub(crate) mod system_time_internal {
148
171
149
172
pub ( crate ) const fn to_uefi ( dur : & Duration , timezone : i16 , daylight : u8 ) -> Option < Time > {
150
173
// Check timzone validity
151
- assert ! ( timezone <= 1440 ) ;
152
- assert ! ( timezone >= -1440 ) ;
174
+ assert ! ( timezone <= 1440 && timezone >= -1440 ) ;
153
175
154
- let secs: u64 = if timezone == r_efi:: efi:: UNSPECIFIED_TIMEZONE {
155
- dur. as_secs ( )
156
- } else {
157
- // FIXME: use checked_sub_signed once stablized
158
- dur. as_secs ( ) . checked_add_signed ( ( -timezone as i64 ) * SECS_IN_MINUTE as i64 ) . unwrap ( )
159
- } ;
176
+ // FIXME(#126043): use checked_sub_signed once stablized
177
+ let secs =
178
+ dur. as_secs ( ) . checked_add_signed ( ( -timezone as i64 ) * SECS_IN_MINUTE as i64 ) . unwrap ( ) ;
160
179
161
- // Convert to UTC
180
+ // Convert to seconds since 1900-01-01-00:00:00 in timezone.
162
181
let Some ( secs) = secs. checked_sub ( TIMEZONE_DELTA ) else { return None } ;
163
182
164
183
let days = secs / SECS_IN_DAY ;
0 commit comments