1
1
//! Timestamp formatting.
2
2
3
- use std:: time:: Duration ;
3
+ use std:: time:: { SystemTime , UNIX_EPOCH } ;
4
4
5
5
use datetime:: { LocalDateTime , TimeZone , DatePiece , TimePiece } ;
6
6
use datetime:: fmt:: DateFormat ;
@@ -51,7 +51,7 @@ pub enum TimeFormat {
51
51
// timestamps are separate types.
52
52
53
53
impl TimeFormat {
54
- pub fn format_local ( & self , time : Duration ) -> String {
54
+ pub fn format_local ( & self , time : SystemTime ) -> String {
55
55
match * self {
56
56
TimeFormat :: DefaultFormat ( ref fmt) => fmt. format_local ( time) ,
57
57
TimeFormat :: ISOFormat ( ref iso) => iso. format_local ( time) ,
@@ -60,7 +60,7 @@ impl TimeFormat {
60
60
}
61
61
}
62
62
63
- pub fn format_zoned ( & self , time : Duration , zone : & TimeZone ) -> String {
63
+ pub fn format_zoned ( & self , time : SystemTime , zone : & TimeZone ) -> String {
64
64
match * self {
65
65
TimeFormat :: DefaultFormat ( ref fmt) => fmt. format_zoned ( time, zone) ,
66
66
TimeFormat :: ISOFormat ( ref iso) => iso. format_zoned ( time, zone) ,
@@ -146,11 +146,11 @@ impl DefaultFormat {
146
146
}
147
147
148
148
#[ allow( trivial_numeric_casts) ]
149
- fn format_local ( & self , time : Duration ) -> String {
150
- if time. as_nanos ( ) == 0 {
149
+ fn format_local ( & self , time : SystemTime ) -> String {
150
+ if time == UNIX_EPOCH {
151
151
return "-" . to_string ( ) ;
152
152
}
153
- let date = LocalDateTime :: at ( time . as_secs ( ) as i64 ) ;
153
+ let date = LocalDateTime :: at ( systemtime_epoch ( time ) ) ;
154
154
155
155
if self . is_recent ( date) {
156
156
format ! ( "{:2} {} {:02}:{:02}" ,
@@ -163,12 +163,12 @@ impl DefaultFormat {
163
163
}
164
164
165
165
#[ allow( trivial_numeric_casts) ]
166
- fn format_zoned ( & self , time : Duration , zone : & TimeZone ) -> String {
167
- if time. as_nanos ( ) == 0 {
166
+ fn format_zoned ( & self , time : SystemTime , zone : & TimeZone ) -> String {
167
+ if time == UNIX_EPOCH {
168
168
return "-" . to_string ( ) ;
169
169
}
170
170
171
- let date = zone. to_zoned ( LocalDateTime :: at ( time . as_secs ( ) as i64 ) ) ;
171
+ let date = zone. to_zoned ( LocalDateTime :: at ( systemtime_epoch ( time ) ) ) ;
172
172
173
173
if self . is_recent ( date) {
174
174
format ! ( "{:2} {} {:02}:{:02}" ,
@@ -181,43 +181,55 @@ impl DefaultFormat {
181
181
}
182
182
}
183
183
184
+ fn systemtime_epoch ( time : SystemTime ) -> i64 {
185
+ time
186
+ . duration_since ( UNIX_EPOCH )
187
+ . map ( |t| t. as_secs ( ) as i64 )
188
+ . unwrap_or_else ( |e| -( e. duration ( ) . as_secs ( ) as i64 ) )
189
+ }
184
190
191
+ fn systemtime_nanos ( time : SystemTime ) -> u32 {
192
+ time
193
+ . duration_since ( UNIX_EPOCH )
194
+ . map ( |t| t. subsec_nanos ( ) )
195
+ . unwrap_or_else ( |e| e. duration ( ) . subsec_nanos ( ) )
196
+ }
185
197
186
198
#[ allow( trivial_numeric_casts) ]
187
- fn long_local ( time : Duration ) -> String {
188
- let date = LocalDateTime :: at ( time . as_secs ( ) as i64 ) ;
199
+ fn long_local ( time : SystemTime ) -> String {
200
+ let date = LocalDateTime :: at ( systemtime_epoch ( time ) ) ;
189
201
format ! ( "{:04}-{:02}-{:02} {:02}:{:02}" ,
190
202
date. year( ) , date. month( ) as usize , date. day( ) ,
191
203
date. hour( ) , date. minute( ) )
192
204
}
193
205
194
206
#[ allow( trivial_numeric_casts) ]
195
- fn long_zoned ( time : Duration , zone : & TimeZone ) -> String {
196
- let date = zone. to_zoned ( LocalDateTime :: at ( time . as_secs ( ) as i64 ) ) ;
207
+ fn long_zoned ( time : SystemTime , zone : & TimeZone ) -> String {
208
+ let date = zone. to_zoned ( LocalDateTime :: at ( systemtime_epoch ( time ) ) ) ;
197
209
format ! ( "{:04}-{:02}-{:02} {:02}:{:02}" ,
198
210
date. year( ) , date. month( ) as usize , date. day( ) ,
199
211
date. hour( ) , date. minute( ) )
200
212
}
201
213
202
214
203
215
#[ allow( trivial_numeric_casts) ]
204
- fn full_local ( time : Duration ) -> String {
205
- let date = LocalDateTime :: at ( time . as_secs ( ) as i64 ) ;
216
+ fn full_local ( time : SystemTime ) -> String {
217
+ let date = LocalDateTime :: at ( systemtime_epoch ( time ) ) ;
206
218
format ! ( "{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:09}" ,
207
219
date. year( ) , date. month( ) as usize , date. day( ) ,
208
- date. hour( ) , date. minute( ) , date. second( ) , time . subsec_nanos ( ) )
220
+ date. hour( ) , date. minute( ) , date. second( ) , systemtime_nanos ( time ) )
209
221
}
210
222
211
223
#[ allow( trivial_numeric_casts) ]
212
- fn full_zoned ( time : Duration , zone : & TimeZone ) -> String {
224
+ fn full_zoned ( time : SystemTime , zone : & TimeZone ) -> String {
213
225
use datetime:: Offset ;
214
226
215
- let local = LocalDateTime :: at ( time . as_secs ( ) as i64 ) ;
227
+ let local = LocalDateTime :: at ( systemtime_epoch ( time ) ) ;
216
228
let date = zone. to_zoned ( local) ;
217
229
let offset = Offset :: of_seconds ( zone. offset ( local) as i32 ) . expect ( "Offset out of range" ) ;
218
230
format ! ( "{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:09} {:+03}{:02}" ,
219
231
date. year( ) , date. month( ) as usize , date. day( ) ,
220
- date. hour( ) , date. minute( ) , date. second( ) , time . subsec_nanos ( ) ,
232
+ date. hour( ) , date. minute( ) , date. second( ) , systemtime_nanos ( time ) ,
221
233
offset. hours( ) , offset. minutes( ) . abs( ) )
222
234
}
223
235
@@ -244,8 +256,8 @@ impl ISOFormat {
244
256
}
245
257
246
258
#[ allow( trivial_numeric_casts) ]
247
- fn format_local ( & self , time : Duration ) -> String {
248
- let date = LocalDateTime :: at ( time . as_secs ( ) as i64 ) ;
259
+ fn format_local ( & self , time : SystemTime ) -> String {
260
+ let date = LocalDateTime :: at ( systemtime_epoch ( time ) ) ;
249
261
250
262
if self . is_recent ( date) {
251
263
format ! ( "{:02}-{:02} {:02}:{:02}" ,
@@ -259,8 +271,8 @@ impl ISOFormat {
259
271
}
260
272
261
273
#[ allow( trivial_numeric_casts) ]
262
- fn format_zoned ( & self , time : Duration , zone : & TimeZone ) -> String {
263
- let date = zone. to_zoned ( LocalDateTime :: at ( time . as_secs ( ) as i64 ) ) ;
274
+ fn format_zoned ( & self , time : SystemTime , zone : & TimeZone ) -> String {
275
+ let date = zone. to_zoned ( LocalDateTime :: at ( systemtime_epoch ( time ) ) ) ;
264
276
265
277
if self . is_recent ( date) {
266
278
format ! ( "{:02}-{:02} {:02}:{:02}" ,
0 commit comments