@@ -94,9 +94,8 @@ pub struct Datetime {
94
94
95
95
/// Error returned from parsing a `Datetime` in the `FromStr` implementation.
96
96
#[ derive( Debug , Clone ) ]
97
- pub struct DatetimeParseError {
98
- _private : ( ) ,
99
- }
97
+ #[ non_exhaustive]
98
+ pub struct DatetimeParseError { }
100
99
101
100
// Currently serde itself doesn't have a datetime type, so we map our `Datetime`
102
101
// to a special value in the serde data model. Namely one with these special
@@ -180,11 +179,8 @@ pub enum Offset {
180
179
181
180
/// Offset between local time and UTC
182
181
Custom {
183
- /// Hours: -12 to +12
184
- hours : i8 ,
185
-
186
- /// Minutes: 0 to 59
187
- minutes : u8 ,
182
+ /// Minutes: -1_440..1_440
183
+ minutes : i16 ,
188
184
} ,
189
185
}
190
186
@@ -247,7 +243,16 @@ impl fmt::Display for Offset {
247
243
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
248
244
match * self {
249
245
Offset :: Z => write ! ( f, "Z" ) ,
250
- Offset :: Custom { hours, minutes } => write ! ( f, "{:+03}:{:02}" , hours, minutes) ,
246
+ Offset :: Custom { mut minutes } => {
247
+ let mut sign = '+' ;
248
+ if minutes < 0 {
249
+ minutes *= -1 ;
250
+ sign = '-' ;
251
+ }
252
+ let hours = minutes / 60 ;
253
+ let minutes = minutes % 60 ;
254
+ write ! ( f, "{}{:02}:{:02}" , sign, hours, minutes)
255
+ }
251
256
}
252
257
}
253
258
}
@@ -263,7 +268,7 @@ impl FromStr for Datetime {
263
268
// 0000-00-00
264
269
// 00:00:00.00
265
270
if date. len ( ) < 3 {
266
- return Err ( DatetimeParseError { _private : ( ) } ) ;
271
+ return Err ( DatetimeParseError { } ) ;
267
272
}
268
273
let mut offset_allowed = true ;
269
274
let mut chars = date. chars ( ) ;
@@ -280,15 +285,15 @@ impl FromStr for Datetime {
280
285
281
286
match chars. next ( ) {
282
287
Some ( '-' ) => { }
283
- _ => return Err ( DatetimeParseError { _private : ( ) } ) ,
288
+ _ => return Err ( DatetimeParseError { } ) ,
284
289
}
285
290
286
291
let m1 = digit ( & mut chars) ?;
287
292
let m2 = digit ( & mut chars) ?;
288
293
289
294
match chars. next ( ) {
290
295
Some ( '-' ) => { }
291
- _ => return Err ( DatetimeParseError { _private : ( ) } ) ,
296
+ _ => return Err ( DatetimeParseError { } ) ,
292
297
}
293
298
294
299
let d1 = digit ( & mut chars) ?;
@@ -301,10 +306,10 @@ impl FromStr for Datetime {
301
306
} ;
302
307
303
308
if date. month < 1 || date. month > 12 {
304
- return Err ( DatetimeParseError { _private : ( ) } ) ;
309
+ return Err ( DatetimeParseError { } ) ;
305
310
}
306
311
if date. day < 1 || date. day > 31 {
307
- return Err ( DatetimeParseError { _private : ( ) } ) ;
312
+ return Err ( DatetimeParseError { } ) ;
308
313
}
309
314
310
315
Some ( date)
@@ -326,13 +331,13 @@ impl FromStr for Datetime {
326
331
let h2 = digit ( & mut chars) ?;
327
332
match chars. next ( ) {
328
333
Some ( ':' ) => { }
329
- _ => return Err ( DatetimeParseError { _private : ( ) } ) ,
334
+ _ => return Err ( DatetimeParseError { } ) ,
330
335
}
331
336
let m1 = digit ( & mut chars) ?;
332
337
let m2 = digit ( & mut chars) ?;
333
338
match chars. next ( ) {
334
339
Some ( ':' ) => { }
335
- _ => return Err ( DatetimeParseError { _private : ( ) } ) ,
340
+ _ => return Err ( DatetimeParseError { } ) ,
336
341
}
337
342
let s1 = digit ( & mut chars) ?;
338
343
let s2 = digit ( & mut chars) ?;
@@ -358,7 +363,7 @@ impl FromStr for Datetime {
358
363
}
359
364
}
360
365
if end == 0 {
361
- return Err ( DatetimeParseError { _private : ( ) } ) ;
366
+ return Err ( DatetimeParseError { } ) ;
362
367
}
363
368
chars = whole[ end..] . chars ( ) ;
364
369
}
@@ -371,16 +376,16 @@ impl FromStr for Datetime {
371
376
} ;
372
377
373
378
if time. hour > 24 {
374
- return Err ( DatetimeParseError { _private : ( ) } ) ;
379
+ return Err ( DatetimeParseError { } ) ;
375
380
}
376
381
if time. minute > 59 {
377
- return Err ( DatetimeParseError { _private : ( ) } ) ;
382
+ return Err ( DatetimeParseError { } ) ;
378
383
}
379
384
if time. second > 59 {
380
- return Err ( DatetimeParseError { _private : ( ) } ) ;
385
+ return Err ( DatetimeParseError { } ) ;
381
386
}
382
387
if time. nanosecond > 999_999_999 {
383
- return Err ( DatetimeParseError { _private : ( ) } ) ;
388
+ return Err ( DatetimeParseError { } ) ;
384
389
}
385
390
386
391
Some ( time)
@@ -401,21 +406,29 @@ impl FromStr for Datetime {
401
406
let sign = match next {
402
407
Some ( '+' ) => 1 ,
403
408
Some ( '-' ) => -1 ,
404
- _ => return Err ( DatetimeParseError { _private : ( ) } ) ,
409
+ _ => return Err ( DatetimeParseError { } ) ,
405
410
} ;
406
411
chars. next ( ) ;
407
- let h1 = digit ( & mut chars) ? as i8 ;
408
- let h2 = digit ( & mut chars) ? as i8 ;
412
+ let h1 = digit ( & mut chars) ? as i16 ;
413
+ let h2 = digit ( & mut chars) ? as i16 ;
409
414
match chars. next ( ) {
410
415
Some ( ':' ) => { }
411
- _ => return Err ( DatetimeParseError { _private : ( ) } ) ,
416
+ _ => return Err ( DatetimeParseError { } ) ,
417
+ }
418
+ let m1 = digit ( & mut chars) ? as i16 ;
419
+ let m2 = digit ( & mut chars) ? as i16 ;
420
+
421
+ let hours = h1 * 10 + h2;
422
+ let minutes = m1 * 10 + m2;
423
+
424
+ let total_minutes = sign * ( hours * 60 + minutes) ;
425
+
426
+ if !( ( -24 * 60 ) ..=( 24 * 60 ) ) . contains ( & total_minutes) {
427
+ return Err ( DatetimeParseError { } ) ;
412
428
}
413
- let m1 = digit ( & mut chars) ?;
414
- let m2 = digit ( & mut chars) ?;
415
429
416
430
Some ( Offset :: Custom {
417
- hours : sign * ( h1 * 10 + h2) ,
418
- minutes : m1 * 10 + m2,
431
+ minutes : total_minutes,
419
432
} )
420
433
}
421
434
} else {
@@ -425,7 +438,7 @@ impl FromStr for Datetime {
425
438
// Return an error if we didn't hit eof, otherwise return our parsed
426
439
// date
427
440
if chars. next ( ) . is_some ( ) {
428
- return Err ( DatetimeParseError { _private : ( ) } ) ;
441
+ return Err ( DatetimeParseError { } ) ;
429
442
}
430
443
431
444
Ok ( Datetime {
@@ -439,7 +452,7 @@ impl FromStr for Datetime {
439
452
fn digit ( chars : & mut str:: Chars < ' _ > ) -> Result < u8 , DatetimeParseError > {
440
453
match chars. next ( ) {
441
454
Some ( c) if ( '0' ..='9' ) . contains ( & c) => Ok ( c as u8 - b'0' ) ,
442
- _ => Err ( DatetimeParseError { _private : ( ) } ) ,
455
+ _ => Err ( DatetimeParseError { } ) ,
443
456
}
444
457
}
445
458
0 commit comments