|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Date::PeriodParser;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
272106
 | 
 use 5.010;  | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
48
 | 
    | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
480
 | 
    | 
| 
4
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
75
 | 
 use strict;  | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
    | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
460
 | 
    | 
| 
5
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
80
 | 
 use warnings;  | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
    | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
477
 | 
    | 
| 
6
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
6863
 | 
 use Time::Local;  | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19771
 | 
    | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
787
 | 
    | 
| 
7
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
11969
 | 
 use Lingua::EN::Words2Nums qw(words2nums);  | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
42618
 | 
    | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1693
 | 
    | 
| 
8
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1614
 | 
 use Date::Calc qw(  | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Add_Delta_Days  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Add_Delta_YM  | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Date_to_Time  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Day_of_Week  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Days_in_Month  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Decode_Month  | 
| 
15
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
12125
 | 
 );  | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
557116
 | 
    | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
17
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
170
 | 
 use constant GIBBERISH => -1;  | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
    | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
927
 | 
    | 
| 
18
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
67
 | 
 use constant AMBIGUOUS => -2;  | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
    | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
548
 | 
    | 
| 
19
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
70
 | 
 use constant DEPENDENCY => -3;  | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
    | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46797
 | 
    | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Boring administrative details  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 require Exporter;  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our @ISA = qw(Exporter);  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our %EXPORT_TAGS = ( 'all' => [ qw( parse_period) ] );  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our @EXPORT = qw( parse_period);  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $VERSION = '0.17';  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $Date::PeriodParser::DEBUG = 0;  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $TestTime; # This is set by our tests so we don't have to   | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                # dynamically figure out acceptable ranges for our test results  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $roughly = qr/((?:a?round(?: about)?|about|roughly|circa|sometime)\s*)+/;  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Emit debug messages if the package global $DEBUG is set.  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _debug {  | 
| 
39
 | 
407
 | 
  
 50
  
 | 
 
 | 
  
407
  
 | 
 
 | 
1012
 | 
     print STDERR "# @_\n" if $Date::PeriodParser::DEBUG;  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # The actual parsing routine. Detailed below in the pod.  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub parse_period {  | 
| 
45
 | 
171
 | 
 
 | 
  
100
  
 | 
  
171
  
 | 
  
1
  
 | 
214689
 | 
     local $_ = lc (shift // ''); # Since we're doing lots of regexps on it.  | 
| 
46
 | 
171
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
492
 | 
     my $now = $TestTime || time;  | 
| 
47
 | 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3253
 | 
     my ($s, $m, $h, $day, $mon, $year) = my @now =   | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         (localtime $now)[0..5];  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Tidy slightly.  | 
| 
51
 | 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
561
 | 
     s/^\s+//;s/\s+$//;  | 
| 
 
 | 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
521
 | 
    | 
| 
52
 | 
171
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
416
 | 
     return (GIBBERISH, "You didn't supply an argument.") unless $_;  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # We're trying to find two things: from and to.  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # We also want to keep track of how vague the user's being, so we  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # provide a flexibility score - for instance "about two weeks ago"  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # means maybe three days either side, but "around last September"  | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # means perhaps twelve days either side.   | 
| 
59
 | 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
207
 | 
     my ($from, $to, $leeway);  | 
| 
60
 | 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1921
 | 
     my $vague = s/^$roughly\s*//;  | 
| 
61
 | 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
404
 | 
     _debug("this is a vague time");  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Stupid cases first.  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # "now": precisely now, or +/- 5 minutes if vague (e.g. "about now")  | 
| 
65
 | 
168
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
438
 | 
     return _apply_leeway($now, $now, 300 * $vague)   | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if /^now$/;  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
68
 | 
164
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
448
 | 
     if ($_ eq "" and $vague) { # Biggest range possible.  | 
| 
69
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         $from = 0; $to = 2**31-1;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
70
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
         return ($from, $to);  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # "this week", "last week", "next week"  | 
| 
74
 | 
162
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
441
 | 
     if ( m/(this|last|next) week/ ) {  | 
| 
75
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
         my $modifier = $1;  | 
| 
76
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
         my @today = _today();  | 
| 
77
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
21
 | 
         if ( $modifier eq 'last' ) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
78
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
             @today = Add_Delta_Days( @today, -7 );  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         elsif ( $modifier eq 'next' ) {  | 
| 
81
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
             @today = Add_Delta_Days( @today, +7 );  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
83
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
286
 | 
         my $today = Day_of_Week(@today);  | 
| 
84
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
169
 | 
         my $monday = 1;  | 
| 
85
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
         my $sunday = 7;  | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # Monday at midnight and sunday just before midnight  | 
| 
88
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
         my @monday = ( Add_Delta_Days(@today, $monday - $today),  0,  0,  0 );  | 
| 
89
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
418
 | 
         my @sunday = ( Add_Delta_Days(@today, $sunday - $today), 23, 59, 59 );  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           | 
| 
91
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
332
 | 
         return ( _timelocal(@monday), _timelocal(@sunday) );  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # "this month", "last month", "next month"  | 
| 
95
 | 
156
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
384
 | 
     if (m/(this|last|next) month/) {  | 
| 
96
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
         my $modifier = $1;  | 
| 
97
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
         my ( $year, $month, $day ) = _today();  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # find a day in the previous month  | 
| 
100
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
22
 | 
         if ( $modifier eq 'last' ) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
101
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
             ( $year, $month ) = Add_Delta_YM( $year, $month, $day, 0, -1 );  | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         elsif ( $modifier eq 'next' ) {  | 
| 
104
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
             ( $year, $month ) = Add_Delta_YM( $year, $month, $day, 0, 1 );  | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
107
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
154
 | 
         my @first = ( $year, $month, 1, 0, 0, 0 );    # first day at midnight  | 
| 
108
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
         my $last_day_of_month = Days_in_Month( $year, $month );  | 
| 
109
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
70
 | 
         my @last = ( $year, $month, $last_day_of_month , 23, 59, 59 );  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
111
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
         return ( _timelocal(@first), _timelocal(@last) );  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # "january 2007", "dec 1991", etc  | 
| 
115
 | 
150
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
736
 | 
     if (m{\A (\w+) \s+ (\d{4}) \z}xms) {  | 
| 
116
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
         my $month = $1;  | 
| 
117
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
         my $year  = $2;  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
119
 | 
15
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
48
 | 
         if ( $month = Decode_Month($month) ) {  | 
| 
120
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2354
 | 
             my @first = ( $year, $month, 1, 0, 0, 0 );   # first day at midnight  | 
| 
121
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
66
 | 
             my $last_day_of_month = Days_in_Month( $year, $month );  | 
| 
122
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
206
 | 
             my @last = ( $year, $month, $last_day_of_month, 23, 59, 59 );  | 
| 
123
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
             return ( _timelocal(@first), _timelocal(@last) );  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Recent times  | 
| 
128
 | 
135
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
1828
 | 
     if (/(the day (before|after) )?(yesterday|today|tomorrow)/ ||  | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
               /^this (morning|afternoon|evening|lunchtime)/   ||  | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             /^at lunchtime$/ ||  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             /^(in the) (morning|afternoon|evening)/ ||  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             /^(last |to)night/) {  | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
134
 | 
36
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
144
 | 
         if (s/the day (before|after)//) {  | 
| 
135
 | 
13
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
48
 | 
             my $wind = $1 eq "before" ? -1 : 1;  | 
| 
136
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
             _debug("Modifying day by $wind");  | 
| 
137
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
             $day += $wind;  | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
139
 | 
36
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
140
 | 
         if (/yesterday/)   { $day--; _debug("Back 1 day") }  | 
| 
 
 | 
11
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
15
 | 
    | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
64
 | 
    | 
| 
140
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
         elsif (/tomorrow/) { $day++; _debug("Forward 1 day") }  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
    | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # if it's later than the morning and the phrase is   | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # "in the morning", add a day.  | 
| 
144
 | 
36
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
435
 | 
         if ($h>12 and /in the morning$/) {$day++}  | 
| 
 
 | 
1
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
  
100
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # if it's later than the afternoon and the phrase is   | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # "in the afternoon", add a day.  | 
| 
148
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
         elsif ($h>18 and /in the afternoon$/) {$day++}  | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # if it's nighttime, and the phrase is "in the evening", add a day.  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         elsif (($h>21 or $h<6) and /in the evening$/) {$day++}  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
153
 | 
36
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
281
 | 
         $day-- if /last/;  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
155
 | 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
81
 | 
         ($day, $mon, $year) = _zyprexa($day, $mon, $year);  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
157
 | 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
102
 | 
         ($from, $to, $leeway) = _period_or_all_day($day, $mon, $year, $now);  | 
| 
158
 | 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
99
 | 
         return _apply_leeway($from, $to, $leeway * $vague);  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # "ago" and "from now" are both pretty limited: only an offset in  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # days is currently supported.  | 
| 
164
 | 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
150
 | 
     s/a (week|month|day|year)/one $1/g;  | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
166
 | 
99
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
537
 | 
     if (/^(.*) day(?:s)? ago$/ || /^in (.*) day(?:s)?(?: time)?$/ ||   | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         /^(.*) day(?:s)? (?:away)?\s*(?:from now)?$/) {  | 
| 
168
 | 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
207
 | 
         my $days = $1;  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         {  | 
| 
170
 | 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
143
 | 
             local $_;   | 
| 
 
 | 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
106
 | 
    | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # words2nums() trashes $_.  | 
| 
172
 | 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
296
 | 
             $days = Lingua::EN::Words2Nums::words2nums($days);  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
174
 | 
94
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5730
 | 
         if (defined $days) {   | 
| 
175
 | 
94
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
304
 | 
             $days *= -1 if /ago/;  | 
| 
176
 | 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
252
 | 
             _debug("Modifying day by $days");  | 
| 
177
 | 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
131
 | 
             $day += $days;  | 
| 
178
 | 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
196
 | 
             ($day, $mon, $year) = _zyprexa($day, $mon, $year);  | 
| 
179
 | 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
206
 | 
             ($from, $to, $leeway) =   | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 _period_or_all_day($day, $mon, $year, $now);  | 
| 
181
 | 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
277
 | 
             return _apply_leeway($from, $to, $leeway * $vague);  | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      }  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
185
 | 
5
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
54
 | 
     if (/^(.*) week(?:s)? ago$/ || /^in (.*) week(?:s)?(?: time)?$/ ||   | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         /^(.*) week(?:s)? (?:away)?\s*(?:from now)?$/) {  | 
| 
187
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
         my $weeks = $1;  | 
| 
188
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         my $days;  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         {  | 
| 
190
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
             local $_;   | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
    | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # words2nums() trashes $_.  | 
| 
192
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
             $days = 7 * Lingua::EN::Words2Nums::words2nums($weeks);  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
194
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
73
 | 
         if (defined $days) {   | 
| 
195
 | 
2
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
8
 | 
             $days *= -1 if /ago/;  | 
| 
196
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
             _debug("Modifying day by $days");  | 
| 
197
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
             $day += $days;  | 
| 
198
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
             ($day, $mon, $year) = _zyprexa($day, $mon, $year);  | 
| 
199
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
             ($from, $to, $leeway) =   | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 _period_or_all_day($day, $mon, $year, $now);  | 
| 
201
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
             return _apply_leeway($from, $to, $leeway * $vague);  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      }  | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
205
 | 
3
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
61
 | 
     if (/^(.*) month(?:s)? ago$/ || /^in (.*) month(?:s)?(?: time)?$/ ||   | 
| 
 
 | 
 
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         /^(.*) month(?:s)? (?:away)?\s*(?:from now)?$/) {  | 
| 
207
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         my $months = $1;  | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         {  | 
| 
209
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
             local $_;   | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # words2nums() trashes $_.  | 
| 
211
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
             $months = Lingua::EN::Words2Nums::words2nums($months);  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
213
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
46
 | 
         if (defined $months) {   | 
| 
214
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5
 | 
             $months *= -1 if /ago/;  | 
| 
215
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
             _debug("Modifying month by $months");  | 
| 
216
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
             $mon += $months;  | 
| 
217
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
             ($day, $mon, $year) = _zyprexa($day, $mon, $year);  | 
| 
218
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
             ($from, $to, $leeway) =   | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 _period_or_all_day($day, $mon, $year, $now);  | 
| 
220
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
             return _apply_leeway($from, $to, $leeway * $vague);  | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      }  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
224
 | 
2
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
24
 | 
     if (/^(.*) year(?:s)? ago$/ || /^in (.*) year(?:s)?(?: time)?$/ ||   | 
| 
 
 | 
 
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         /^(.*) year(?:s)? (?:away)?\s*(?:from now)?$/) {  | 
| 
226
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         my $years = $1;  | 
| 
227
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         {  | 
| 
228
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
             local $_;   | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # words2nums() trashes $_.  | 
| 
230
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
             $years = Lingua::EN::Words2Nums::words2nums($years);  | 
| 
231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
232
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
44
 | 
         if (defined $years) {   | 
| 
233
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5
 | 
             $years *= -1 if /ago/;  | 
| 
234
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
             _debug("Modifying year by $years");  | 
| 
235
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
             $year += $years;  | 
| 
236
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
             ($day, $mon, $year) = _zyprexa($day, $mon, $year);  | 
| 
237
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
             ($from, $to, $leeway) =   | 
| 
238
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 _period_or_all_day($day, $mon, $year, $now);  | 
| 
239
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
             return _apply_leeway($from, $to, $leeway * $vague);  | 
| 
240
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      }  | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
243
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # We got nothing. Warn the caller.  | 
| 
244
 | 
1
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
15
 | 
     if (!$from and !$to) {  | 
| 
245
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
         return (GIBBERISH, "I couldn't parse that at all.");  | 
| 
246
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
249
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Define the basic ranges for a day. (earliest,latest) pairs.  | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my %points_of_day = (  | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Technically, after midnight is the morning of the next day.  | 
| 
253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Morning runs until noon.  | 
| 
254
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     morning   => [  | 
| 
255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     [0,   0,  0],  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     [12,  0,  0]  | 
| 
257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                  ],  | 
| 
258
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Must be English rules for how long lunch is :) [JM]  | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     lunchtime => [  | 
| 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     [12,  0,  0],  | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     [13, 30,  0]  | 
| 
263
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                  ],  | 
| 
264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Afternoon runs till 6 PM.  | 
| 
265
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     afternoon => [  | 
| 
266
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     [13, 30,  0], # "It is not afternoon until a gentleman  | 
| 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     [18,  0,  0]  # has had his luncheon."  | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                  ],  | 
| 
269
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Evening runs up to but not including midnight.  | 
| 
270
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     evening   => [  | 
| 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     [18,  0,  0], # Regardless of what Mediterraneans think  | 
| 
272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     [23, 59, 59]  | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                  ],  | 
| 
274
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # The entire day.  | 
| 
275
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     day       => [  | 
| 
276
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     [0,   0,  0],  | 
| 
277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     [23, 59, 59],  | 
| 
278
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                  ]  | 
| 
279
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
280
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # _apply_point_of_day takes the word specifying the portion of the   | 
| 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # day and transforms it into a range of hours.  | 
| 
283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _apply_point_of_day {  | 
| 
285
 | 
140
 | 
 
 | 
 
 | 
  
140
  
 | 
 
 | 
4365
 | 
     my ($d, $m, $y, $point) = @_;  | 
| 
286
 | 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
141
 | 
     my ($from, $to);   | 
| 
287
 | 
140
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
318
 | 
     if ($point eq "night") { # Special case  | 
| 
288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # Nights are a special case because they run over the  | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # day boundary. (9PM to 5:59:59AM the next day).  | 
| 
290
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
         $from = timelocal(0,0,21,$d,$m,$y);  | 
| 
291
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
276
 | 
         $to   = timelocal(59,59,5,$d+1,$m,$y);  | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # Look up the appropriate range and set the hours  | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # in the specified day.  | 
| 
295
 | 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
262
 | 
         my $spec = $points_of_day{$point};  | 
| 
296
 | 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
163
 | 
         my @from = (reverse(@{$spec->[0]}),$d,$m,$y);  | 
| 
 
 | 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
426
 | 
    | 
| 
297
 | 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
169
 | 
         my @to   = (reverse(@{$spec->[1]}),$d,$m,$y);  | 
| 
 
 | 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
312
 | 
    | 
| 
298
 | 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
370
 | 
         $from = timelocal(@from);  | 
| 
299
 | 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6899
 | 
         $to   = timelocal(@to);  | 
| 
300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
301
 | 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6945
 | 
     return ($from, $to);  | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # _period_or_all_day determines the size of leeway to  | 
| 
305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # be applied to a date (closer dates get less, dates  | 
| 
306
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # further in the future or past get more). It also  | 
| 
307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # applies the appropriate point-of-day.  | 
| 
308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _period_or_all_day {  | 
| 
309
 | 
134
 | 
 
 | 
 
 | 
  
134
  
 | 
 
 | 
145
 | 
     my $point;  | 
| 
310
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
177
 | 
     my ($day, $mon, $year, $now) = @_;  | 
| 
311
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
133
 | 
     my $leeway;  | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
313
 | 
134
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
559
 | 
     if (/(morning|afternoon|evening|lunchtime|night)/) {  | 
| 
314
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
         $leeway = 60*60*2;  | 
| 
315
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
64
 | 
         $point = $1;  | 
| 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # To determine the leeway, consider how many days ago this was;  | 
| 
318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # we want to be more specific about recent events than ancient  | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # ones.  | 
| 
320
 | 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
303
 | 
         my $was = timelocal(0,0,0, $day, $mon, $year);  | 
| 
321
 | 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6113
 | 
         my $days_ago = int(($now-$was)/(60*60*24))+1;  | 
| 
322
 | 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
130
 | 
         $leeway = 60*60*3*$days_ago;  | 
| 
323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # Up to a maximum of five days  | 
| 
324
 | 
107
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
238
 | 
         $leeway > 24*60*60*5 and $leeway = 24*60*60*5;  | 
| 
325
 | 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
351
 | 
         _debug("Wanted around $days_ago, allowing $leeway either side");  | 
| 
326
 | 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
172
 | 
         $point = "day";  | 
| 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
328
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
260
 | 
     return (_apply_point_of_day($day, $mon, $year, $point), $leeway);  | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # _apply_leeway just applies the necessary leeway to the  | 
| 
332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # current date range.  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _apply_leeway {  | 
| 
334
 | 
141
 | 
 
 | 
 
 | 
  
141
  
 | 
 
 | 
2415
 | 
     my ($from, $to, $leeway) = @_;  | 
| 
335
 | 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
184
 | 
     my $new_from = $from - $leeway;  | 
| 
336
 | 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
175
 | 
     my $new_to   = $to   + $leeway;  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # watch for daylight savings crossovers!  | 
| 
338
 | 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
591
 | 
     for my $pair ( [\$new_from, $from], [\$new_to, $to] ) {  | 
| 
339
 | 
282
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
326
 | 
         if ( _isnt_dst(${ $pair->[0] }) and _is_dst($pair->[1]) ) {  | 
| 
 
 | 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
626
 | 
    | 
| 
340
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
             ${ $pair->[0] } += 60 * 60; # forward an hour to match  | 
| 
 
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
    | 
| 
341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
342
 | 
282
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
534
 | 
         if ( _is_dst(${ $pair->[0] }) and _isnt_dst($pair->[1]) ) {  | 
| 
 
 | 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
554
 | 
    | 
| 
343
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
             ${ $pair->[0] } -= 60 * 60; # back an hour to match  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
    | 
| 
344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
346
 | 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
775
 | 
     return ($new_from, $new_to);  | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
348
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _is_dst {  | 
| 
350
 | 
846
 | 
 
 | 
 
 | 
  
846
  
 | 
 
 | 
1002
 | 
     my ($given_time) = shift;  | 
| 
351
 | 
846
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10229
 | 
     return (localtime $given_time)[-1];  | 
| 
352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
353
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
354
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _isnt_dst {  | 
| 
355
 | 
304
 | 
 
 | 
 
 | 
  
304
  
 | 
 
 | 
545
 | 
     return not _is_dst(@_);  | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # similar to Time::Local::timelocal but accepts the offsets returned by  | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Date::Calc::Today_and_Now()  | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _timelocal {  | 
| 
361
 | 
54
 | 
 
 | 
 
 | 
  
54
  
 | 
 
 | 
1277
 | 
     my ( $year, $mon, $day, $hour, $min, $sec ) = @_;  | 
| 
362
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
363
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # make offsets as expected by timelocal  | 
| 
364
 | 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
66
 | 
     $year -= 1900;  | 
| 
365
 | 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
54
 | 
     $mon--;  | 
| 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
367
 | 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
133
 | 
     return timelocal( $sec, $min, $hour, $day, $mon, $year );  | 
| 
368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
369
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
370
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # same as Date::Calc::Today but respect $TestTime so that  | 
| 
371
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # we can test periods based on today's date  | 
| 
372
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _today {  | 
| 
373
 | 
12
 | 
 
 | 
  
 33
  
 | 
  
12
  
 | 
 
 | 
27
 | 
     my $now = $TestTime || time;  | 
| 
374
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
192
 | 
     my ( $day, $month, $year ) = ( localtime $now )[ 3 .. 5 ];  | 
| 
375
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
52
 | 
     $year += 1900;  | 
| 
376
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
     $month++;  | 
| 
377
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
129
 | 
     return ($year, $month, $day);  | 
| 
378
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
379
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
380
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Our date math can lead to days or months out of range, so we need to get   | 
| 
381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # them back to something sane before we pass them to any of the date functions.  | 
| 
382
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # (Zyprexa is an anti-psychotic.)  | 
| 
383
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _zyprexa {  | 
| 
384
 | 
134
 | 
 
 | 
 
 | 
  
134
  
 | 
 
 | 
188
 | 
     my( $day, $month, $year) = @_;  | 
| 
385
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
386
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
138
 | 
     $day++;  | 
| 
387
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
137
 | 
     $month++;  | 
| 
388
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
171
 | 
     $year += 1900;  | 
| 
389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
390
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
302
 | 
     while ($month > 12) {  | 
| 
391
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
         $year++;  | 
| 
392
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         $month -= 12;  | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
394
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
395
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
274
 | 
     while ($month < 1) {  | 
| 
396
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $year--;  | 
| 
397
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $month += 12;  | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
399
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
400
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
450
 | 
     while ($day > Days_in_Month($year, $month)) {  | 
| 
401
 | 
32856
 | 
 
 | 
 
 | 
 
 | 
 
 | 
355130
 | 
         $day -= Days_in_Month ($year, $month);  | 
| 
402
 | 
32856
 | 
 
 | 
 
 | 
 
 | 
 
 | 
298582
 | 
         $month++;  | 
| 
403
 | 
32856
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
94094
 | 
         if ($month > 12) {  | 
| 
404
 | 
2738
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3035
 | 
             $month = 1;  | 
| 
405
 | 
2738
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6030
 | 
             $year++;  | 
| 
406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
408
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
409
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2076
 | 
     while ($day < 0) {  | 
| 
410
 | 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
707
 | 
         $month--;  | 
| 
411
 | 
69
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
123
 | 
         if ($month < 1) {  | 
| 
412
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
             $month = 12;  | 
| 
413
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
             $year--;  | 
| 
414
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
415
 | 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
148
 | 
         $day += Days_in_Month($year, $month);  | 
| 
416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
417
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
418
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
160
 | 
     $day--;  | 
| 
419
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
129
 | 
     $month--;  | 
| 
420
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
160
 | 
     $year -= 1900;  | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
422
 | 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
327
 | 
     return ($day, $month, $year);  | 
| 
423
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
424
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
425
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |