Skip to content

Commit c733600

Browse files
authored
Obsolete timezones (#95)
* Expand date time tests by section 4.3 Obsolete Date and Time from RFC5322 * Needless branching * fmt * Implement obsolete time zones RFC5322 section 4.3 * Sanity check: constrain hours below 12 and minutes below 60
1 parent 76669a3 commit c733600

File tree

2 files changed

+90
-10
lines changed

2 files changed

+90
-10
lines changed

resources/date.json

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,5 +384,61 @@
384384
"tz_hour": 7,
385385
"tz_minute": 0
386386
}
387+
},
388+
{
389+
"header": "Sun, 27 Oct 2002 23:57:07 EST",
390+
"expected": {
391+
"year": 2002,
392+
"month": 10,
393+
"day": 27,
394+
"hour": 23,
395+
"minute": 57,
396+
"second": 7,
397+
"tz_before_gmt": true,
398+
"tz_hour": 5,
399+
"tz_minute": 0
400+
}
401+
},
402+
{
403+
"header": "Thu, 10 Jul 1997 14:53:31 EST5EDT",
404+
"expected": {
405+
"year": 1997,
406+
"month": 7,
407+
"day": 10,
408+
"hour": 14,
409+
"minute": 53,
410+
"second": 31,
411+
"tz_before_gmt": true,
412+
"tz_hour": 5,
413+
"tz_minute": 0
414+
}
415+
},
416+
{
417+
"header": "Thu, 10 Jul 1997 14:53:31 A",
418+
"expected": {
419+
"year": 1997,
420+
"month": 7,
421+
"day": 10,
422+
"hour": 14,
423+
"minute": 53,
424+
"second": 31,
425+
"tz_before_gmt": false,
426+
"tz_hour": 0,
427+
"tz_minute": 0
428+
}
429+
},
430+
{
431+
"header": "Thu, 10 Jul 1997 14:53:31 ZZZZ",
432+
"expected": {
433+
"year": 1997,
434+
"month": 7,
435+
"day": 10,
436+
"hour": 14,
437+
"minute": 53,
438+
"second": 31,
439+
"tz_before_gmt": false,
440+
"tz_hour": 0,
441+
"tz_minute": 0
442+
}
387443
}
388444
]

src/parsers/fields/date.rs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -338,13 +338,9 @@ impl<'x> MessageStream<'x> {
338338
parts_sizes[pos] -= 1;
339339
parts[pos] += (*ch - b'0') as u32 * u32::pow(10, parts_sizes[pos]);
340340

341-
if ignore {
342-
ignore = false;
343-
}
344-
}
345-
if is_new_token {
346-
is_new_token = false;
341+
ignore = false;
347342
}
343+
is_new_token = false;
348344
}
349345
b':' => {
350346
if !is_new_token && !ignore && (pos == 3 || pos == 4) {
@@ -372,9 +368,15 @@ impl<'x> MessageStream<'x> {
372368
}
373369
month_pos += 1;
374370
}
375-
if is_new_token {
376-
is_new_token = false;
371+
if pos == 6 {
372+
let mut buf = [*ch, 0, 0];
373+
let zone = self.obs_zone(&mut buf);
374+
is_plus = !zone.is_negative();
375+
parts[pos] = 100 * zone.unsigned_abs();
376+
parts_sizes[pos] = 0;
377+
next_part = true;
377378
}
379+
is_new_token = false;
378380
}
379381
b'(' => {
380382
comment_count += 1;
@@ -433,14 +435,36 @@ impl<'x> MessageStream<'x> {
433435
hour: parts[3] as u8,
434436
minute: parts[4] as u8,
435437
second: parts[5] as u8,
436-
tz_hour: (parts[6] / 100) as u8,
437-
tz_minute: (parts[6] % 100) as u8,
438+
tz_hour: ((parts[6] / 100) % 12) as u8,
439+
tz_minute: ((parts[6] % 100) % 60) as u8,
438440
tz_before_gmt: !is_plus,
439441
})
440442
} else {
441443
HeaderValue::Empty
442444
}
443445
}
446+
// 4.3 obsolete date and time
447+
fn obs_zone(&mut self, buf: &mut [u8; 3]) -> i32 {
448+
let mut i = 1;
449+
for &b in self.by_ref() {
450+
buf[i] = b;
451+
i += 1;
452+
if i == 3 {
453+
break;
454+
}
455+
}
456+
match buf.as_ref() {
457+
b"EDT" => -4,
458+
b"EST" => -5,
459+
b"CDT" => -5,
460+
b"CST" => -6,
461+
b"MDT" => -6,
462+
b"MST" => -7,
463+
b"PDT" => -7,
464+
b"PST" => -8,
465+
_ => 0,
466+
}
467+
}
444468
}
445469

446470
static MONTH_HASH: &[u8] = &[

0 commit comments

Comments
 (0)