@@ -48,6 +48,7 @@ pub mod secp256k1;
48
48
pub mod securechip;
49
49
pub mod ui;
50
50
51
+ use :: util:: c_types:: c_int;
51
52
use core:: time:: Duration ;
52
53
53
54
pub use bitbox02_sys:: buffer_t;
@@ -116,19 +117,73 @@ pub fn reset(status: bool) {
116
117
unsafe { bitbox02_sys:: reset_reset ( status) }
117
118
}
118
119
119
- pub fn strftime ( timestamp : u32 , format : & str ) -> String {
120
- let mut out = [ 0u8 ; 100 ] ;
121
- unsafe {
122
- bitbox02_sys:: strftime (
123
- out. as_mut_ptr ( ) ,
124
- out. len ( ) as _ ,
125
- crate :: util:: str_to_cstr_vec ( format) . unwrap ( ) . as_ptr ( ) ,
126
- bitbox02_sys:: localtime ( & ( timestamp as bitbox02_sys:: time_t ) ) ,
127
- ) ;
120
+ pub struct Tm {
121
+ tm : bitbox02_sys:: tm ,
122
+ }
123
+
124
+ fn range ( low : c_int , item : c_int , high : c_int ) -> c_int {
125
+ core:: cmp:: max ( low, core:: cmp:: min ( item, high) )
126
+ }
127
+
128
+ impl Tm {
129
+ /// Returns the weekday, one of "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
130
+ pub fn weekday ( & self ) -> String {
131
+ // Same as '%a' in strftime:
132
+ // https://github.com/arnoldrobbins/strftime/blob/2011b7e82365d25220b8949e252eb5f28c0994cd/strftime.c#435
133
+ let wday = self . tm . tm_wday ;
134
+ if !( 0 ..=6 ) . contains ( & wday) {
135
+ return "?" . into ( ) ;
136
+ }
137
+ [ "Sun" , "Mon" , "Tue" , "Wed" , "Thu" , "Fri" , "Sat" ] [ wday as usize ] . into ( )
138
+ }
139
+
140
+ /// Returns 'year-month-day', e.g. 2024-07-16, equivalent of '%Y-%m-%d' in strftime.
141
+ pub fn date ( & self ) -> String {
142
+ // Same as strftime:
143
+ // %Y - https://github.com/arnoldrobbins/strftime/blob/2011b7e82365d25220b8949e252eb5f28c0994cd/strftime.c#L712
144
+ // %m - https://github.com/arnoldrobbins/strftime/blob/2011b7e82365d25220b8949e252eb5f28c0994cd/strftime.c#L600
145
+ // %d - https://github.com/arnoldrobbins/strftime/blob/2011b7e82365d25220b8949e252eb5f28c0994cd/strftime.c#L498
146
+ format ! (
147
+ "{}-{:02}-{:02}" ,
148
+ 1900 + self . tm. tm_year,
149
+ range( 0 , self . tm. tm_mon, 11 ) + 1 ,
150
+ range( 1 , self . tm. tm_mday, 31 )
151
+ )
152
+ }
153
+
154
+ /// Returns the zero-padded hour from 00-23, e.g. "07".
155
+ pub fn hour ( & self ) -> String {
156
+ // Same as '%H' in strftime:
157
+ // https://github.com/arnoldrobbins/strftime/blob/2011b7e82365d25220b8949e252eb5f28c0994cd/strftime.c#582
158
+ format ! ( "{:02}" , range( 0 , self . tm. tm_hour, 23 ) )
159
+ }
160
+
161
+ /// Returns the zero-padded minute from 00-59, e.g. "07".
162
+ pub fn minute ( & self ) -> String {
163
+ // Same as '%M' in strftime:
164
+ // https://github.com/arnoldrobbins/strftime/blob/2011b7e82365d25220b8949e252eb5f28c0994cd/strftime.c#L605
165
+ format ! ( "{:02}" , range( 0 , self . tm. tm_min, 59 ) )
128
166
}
129
- crate :: util:: str_from_null_terminated ( & out[ ..] )
130
- . unwrap ( )
131
- . into ( )
167
+
168
+ /// Returns the zero-padded second from 00-60, e.g. "07".
169
+ pub fn second ( & self ) -> String {
170
+ // Same as '%S' in strftime:
171
+ // https://github.com/arnoldrobbins/strftime/blob/2011b7e82365d25220b8949e252eb5f28c0994cd/strftime.c#L645
172
+ format ! ( "{:02}" , range( 0 , self . tm. tm_sec, 60 ) )
173
+ }
174
+ }
175
+
176
+ pub fn get_datetime ( timestamp : u32 ) -> Result < Tm , ( ) > {
177
+ Ok ( Tm {
178
+ tm : unsafe {
179
+ let localtime = bitbox02_sys:: localtime ( & ( timestamp as bitbox02_sys:: time_t ) ) ;
180
+ if localtime. is_null ( ) {
181
+ return Err ( ( ) ) ;
182
+ }
183
+
184
+ * localtime
185
+ } ,
186
+ } )
132
187
}
133
188
134
189
/// Formats the timestamp in the local timezone.
@@ -146,15 +201,19 @@ pub fn format_datetime(
146
201
if !( MAX_WEST_UTC_OFFSET ..=MAX_EAST_UTC_OFFSET ) . contains ( & timezone_offset) {
147
202
return Err ( ( ) ) ;
148
203
}
149
-
150
- Ok ( strftime (
151
- ( ( timestamp as i64 ) + ( timezone_offset as i64 ) ) as u32 ,
152
- if date_only {
153
- "%a %Y-%m-%d"
154
- } else {
155
- "%a %Y-%m-%d\n %H:%M"
156
- } ,
157
- ) )
204
+ let ts = ( ( timestamp as i64 ) + ( timezone_offset as i64 ) ) as u32 ;
205
+ let tm = get_datetime ( ts) ?;
206
+ Ok ( if date_only {
207
+ format ! ( "{} {}" , tm. weekday( ) , tm. date( ) )
208
+ } else {
209
+ format ! (
210
+ "{} {}\n {}:{}" ,
211
+ tm. weekday( ) ,
212
+ tm. date( ) ,
213
+ tm. hour( ) ,
214
+ tm. minute( )
215
+ )
216
+ } )
158
217
}
159
218
160
219
#[ cfg( not( feature = "testing" ) ) ]
@@ -200,14 +259,6 @@ pub fn println_stdout(msg: &str) {
200
259
mod tests {
201
260
use super :: * ;
202
261
203
- #[ test]
204
- fn test_strftime ( ) {
205
- assert_eq ! (
206
- strftime( 1601281809 , "%a %Y-%m-%d\n %H:%M" ) . as_str( ) ,
207
- "Mon 2020-09-28\n 08:30" ,
208
- ) ;
209
- }
210
-
211
262
#[ test]
212
263
fn test_format_datetime ( ) {
213
264
assert_eq ! (
0 commit comments