@@ -40,11 +40,22 @@ impl Instant {
4040}
4141
4242impl SystemTime {
43+ pub ( crate ) const ZERO : SystemTime = SystemTime ( Duration :: ZERO ) ;
44+
45+ pub ( crate ) const fn new ( t : r_efi:: efi:: Time ) -> Self {
46+ Self ( system_time_internal:: uefi_time_to_duration ( t) )
47+ }
48+
4349 pub fn now ( ) -> SystemTime {
4450 system_time_internal:: now ( )
4551 . unwrap_or_else ( || panic ! ( "time not implemented on this platform" ) )
4652 }
4753
54+ #[ expect( dead_code) ]
55+ pub ( crate ) const fn to_uefi_time ( & self , daylight : u8 , timezone : i16 ) -> r_efi:: efi:: Time {
56+ system_time_internal:: uefi_time_from_duration ( self . 0 , daylight, timezone)
57+ }
58+
4859 pub fn sub_time ( & self , other : & SystemTime ) -> Result < Duration , Duration > {
4960 self . 0 . checked_sub ( other. 0 ) . ok_or_else ( || other. 0 - self . 0 )
5061 }
@@ -79,7 +90,7 @@ pub(crate) mod system_time_internal {
7990
8091 let t = unsafe { t. assume_init ( ) } ;
8192
82- Some ( SystemTime ( uefi_time_to_duration ( t ) ) )
93+ Some ( SystemTime :: new ( t ) )
8394 }
8495
8596 // This algorithm is based on the one described in the post
@@ -112,6 +123,52 @@ pub(crate) mod system_time_internal {
112123
113124 Duration :: new ( utc_epoch, t. nanosecond )
114125 }
126+
127+ /// This algorithm is taken from: http://howardhinnant.github.io/date_algorithms.html
128+ pub ( crate ) const fn uefi_time_from_duration (
129+ dur : crate :: time:: Duration ,
130+ daylight : u8 ,
131+ timezone : i16 ,
132+ ) -> r_efi:: system:: Time {
133+ const SECS_IN_MINUTE : u64 = 60 ;
134+ const SECS_IN_HOUR : u64 = SECS_IN_MINUTE * 60 ;
135+ const SECS_IN_DAY : u64 = SECS_IN_HOUR * 24 ;
136+
137+ let secs = if timezone == r_efi:: efi:: UNSPECIFIED_TIMEZONE {
138+ dur. as_secs ( )
139+ } else {
140+ dur. as_secs ( ) . checked_add_signed ( -timezone as i64 ) . unwrap ( )
141+ } ;
142+ let days = secs / SECS_IN_DAY ;
143+ let remaining_secs = secs % SECS_IN_DAY ;
144+ let z = days + 719468 ;
145+ let era = z / 146097 ;
146+ let doe = z - ( era * 146097 ) ;
147+ let yoe = ( doe - doe / 1460 + doe / 36524 - doe / 146096 ) / 365 ;
148+ let mut y = yoe + era * 400 ;
149+ let doy = doe - ( 365 * yoe + yoe / 4 - yoe / 100 ) ;
150+ let mp = ( 5 * doy + 2 ) / 153 ;
151+ let d = doy - ( 153 * mp + 2 ) / 5 + 1 ;
152+ let m = if mp < 10 { mp + 3 } else { mp - 9 } ;
153+
154+ if m <= 2 {
155+ y += 1 ;
156+ }
157+
158+ r_efi:: system:: Time {
159+ year : y as u16 ,
160+ month : m as u8 ,
161+ day : d as u8 ,
162+ hour : ( remaining_secs / SECS_IN_HOUR ) as u8 ,
163+ minute : ( ( remaining_secs % SECS_IN_HOUR ) / SECS_IN_MINUTE ) as u8 ,
164+ second : ( ( remaining_secs % SECS_IN_HOUR ) % SECS_IN_MINUTE ) as u8 ,
165+ pad1 : 0 ,
166+ nanosecond : dur. subsec_nanos ( ) ,
167+ timezone,
168+ daylight,
169+ pad2 : 0 ,
170+ }
171+ }
115172}
116173
117174pub ( crate ) mod instant_internal {
0 commit comments