@@ -96,6 +96,44 @@ fn print_header() {
9696 ) ;
9797}
9898
99+ /// Format a Unix timestamp (seconds since epoch) as `YYYY-MM-DD HH:MM:SS`
100+ /// using Howard Hinnant's civil_from_days algorithm — no external dependencies.
101+ fn format_unix_secs ( secs : u64 ) -> String {
102+ fn civil_from_days ( z : i64 ) -> ( i32 , u32 , u32 ) {
103+ let z = z + 719_468 ;
104+ let era = if z >= 0 { z } else { z - 146_096 } / 146_097 ;
105+ let doe = ( z - era * 146_097 ) as u64 ;
106+ let yoe = ( doe - doe / 1460 + doe / 36524 - doe / 146_096 ) / 365 ;
107+ let y = yoe as i64 + era * 400 ;
108+ let doy = doe - ( 365 * yoe + yoe / 4 - yoe / 100 ) ;
109+ let mp = ( 5 * doy + 2 ) / 153 ;
110+ let d = doy - ( 153 * mp + 2 ) / 5 + 1 ;
111+ let m = if mp < 10 { mp + 3 } else { mp - 9 } ;
112+ let y = if m <= 2 { y + 1 } else { y } ;
113+ ( y as i32 , m as u32 , d as u32 )
114+ }
115+
116+ let days = ( secs / 86_400 ) as i64 ;
117+ let tod = secs % 86_400 ;
118+ let ( year, month, day) = civil_from_days ( days) ;
119+ format ! ( "{:04}-{:02}-{:02} {:02}:{:02}:{:02}" , year, month, day, tod / 3600 , ( tod % 3600 ) / 60 , tod % 60 )
120+ }
121+
122+ /// Reformat error messages that contain a raw `Time(Time(timestamp))` debug repr,
123+ /// replacing the opaque token with a human-readable UTC datetime.
124+ fn format_session_error ( msg : & str ) -> String {
125+ const PREFIX : & str = "Session expired at Time(Time(" ;
126+ const SUFFIX : & str = "))" ;
127+ if let Some ( rest) = msg. strip_prefix ( PREFIX ) {
128+ if let Some ( num_str) = rest. strip_suffix ( SUFFIX ) {
129+ if let Ok ( secs) = num_str. parse :: < u64 > ( ) {
130+ return format ! ( "Session expired at {} UTC" , format_unix_secs( secs) ) ;
131+ }
132+ }
133+ }
134+ msg. to_string ( )
135+ }
136+
99137enum Role {
100138 Sender ,
101139 Receiver ,
@@ -113,7 +151,7 @@ struct SessionHistoryRow<Status> {
113151 session_id : SessionId ,
114152 role : Role ,
115153 status : Status ,
116- completed_at : Option < u64 > ,
154+ completed_at : Option < String > ,
117155 error_message : Option < String > ,
118156}
119157
@@ -124,13 +162,7 @@ impl<Status: StatusText> fmt::Display for SessionHistoryRow<Status> {
124162 "{:<W_ID$} {:<W_ROLE$} {:<W_DONE$} {:<W_STATUS$}" ,
125163 self . session_id. to_string( ) ,
126164 self . role. as_str( ) ,
127- match self . completed_at {
128- None => "Not Completed" . to_string( ) ,
129- Some ( secs) => {
130- // TODO: human readable time
131- secs. to_string( )
132- }
133- } ,
165+ self . completed_at. as_deref( ) . unwrap_or( "Not Completed" ) ,
134166 self . error_message. as_deref( ) . unwrap_or( self . status. status_text( ) )
135167 )
136168 }
@@ -362,7 +394,7 @@ impl AppTrait for App {
362394 role : Role :: Sender ,
363395 status : SendSession :: Closed ( SenderSessionOutcome :: Failure ) ,
364396 completed_at : None ,
365- error_message : Some ( e. to_string ( ) ) ,
397+ error_message : Some ( format_session_error ( & e. to_string ( ) ) ) ,
366398 } ;
367399 send_rows. push ( row) ;
368400 }
@@ -388,7 +420,7 @@ impl AppTrait for App {
388420 role : Role :: Receiver ,
389421 status : ReceiveSession :: Closed ( ReceiverSessionOutcome :: Failure ) ,
390422 completed_at : None ,
391- error_message : Some ( e. to_string ( ) ) ,
423+ error_message : Some ( format_session_error ( & e. to_string ( ) ) ) ,
392424 } ;
393425 recv_rows. push ( row) ;
394426 }
@@ -415,7 +447,7 @@ impl AppTrait for App {
415447 role : Role :: Sender ,
416448 status : SendSession :: Closed ( SenderSessionOutcome :: Failure ) ,
417449 completed_at : Some ( completed_at) ,
418- error_message : Some ( e. to_string ( ) ) ,
450+ error_message : Some ( format_session_error ( & e. to_string ( ) ) ) ,
419451 } ;
420452 send_rows. push ( row) ;
421453 }
@@ -443,7 +475,7 @@ impl AppTrait for App {
443475 role : Role :: Receiver ,
444476 status : ReceiveSession :: Closed ( ReceiverSessionOutcome :: Failure ) ,
445477 completed_at : Some ( completed_at) ,
446- error_message : Some ( e. to_string ( ) ) ,
478+ error_message : Some ( format_session_error ( & e. to_string ( ) ) ) ,
447479 } ;
448480 recv_rows. push ( row) ;
449481 }
0 commit comments