]> Sergey Matveev's repositories - public-inbox.git/blob - lib/PublicInbox/MsgTime.pm
favor Received: date over Date: header globally
[public-inbox.git] / lib / PublicInbox / MsgTime.pm
1 # Copyright (C) 2018 all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
3 package PublicInbox::MsgTime;
4 use strict;
5 use warnings;
6 use base qw(Exporter);
7 our @EXPORT_OK = qw(msg_timestamp);
8 use Date::Parse qw(str2time);
9 use Time::Zone qw(tz_offset);
10
11 sub msg_timestamp ($) {
12         my ($hdr) = @_; # Email::MIME::Header
13         my ($ts, $zone);
14         my $mid;
15         my @recvd = $hdr->header_raw('Received');
16         foreach my $r (@recvd) {
17                 $zone = undef;
18                 $r =~ /\s*(\d+\s+[[:alpha:]]+\s+\d{2,4}\s+
19                         \d+\D\d+(?:\D\d+)\s+([\+\-]\d+))/sx or next;
20                 $zone = $2;
21                 $ts = eval { str2time($1) } and last;
22                 $mid ||= $hdr->header_raw('Message-ID');
23                 warn "no date in $mid Received: $r\n";
24         }
25         unless (defined $ts) {
26                 my @date = $hdr->header_raw('Date');
27                 foreach my $d (@date) {
28                         $zone = undef;
29                         $ts = eval { str2time($d) };
30                         if ($@) {
31                                 $mid ||= $hdr->header_raw('Message-ID');
32                                 warn "bad Date: $d in $mid: $@\n";
33                         } elsif ($d =~ /\s+([\+\-]\d+)\s*\z/) {
34                                 $zone = $1;
35                         }
36                 }
37         }
38         $ts = time unless defined $ts;
39         return $ts unless wantarray;
40
41         $zone ||= '+0000';
42         # "-1200" is the furthest westermost zone offset,
43         # but git fast-import is liberal so we use "-1400"
44         if ($zone >= 1400 || $zone <= -1400) {
45                 warn "bogus TZ offset: $zone, ignoring and assuming +0000\n";
46                 $zone = '+0000';
47         }
48         ($ts, $zone);
49 }
50
51 1;