local($_)=@_;
return "" if (! $_);
my($y,$m,$d,$h,$mn,$s,$i,$wofm,$dofw,$wk,$tmp,$z,$num,$err,$iso,$ampm)=();
my($date,$z2,$delta,$from,$falsefrom,$to,$which,$midnight)=();
# We only need to reinitialize if we have to determine what NOW is.
Date_Init() if (! $Curr{"InitDone"} or $Cnf{"UpdateCurrTZ"});
my($L)=$Cnf{"Language"};
my($type)=$Cnf{"DateFormat"};
# Mode is set in DateCalc. ParseDate only overrides it if the string
# contains a mode.
if ($Lang{$L}{"Exact"} &&
s/$Lang{$L}{"Exact"}//) {
$Curr{"Mode"}=0;
} elsif ($Lang{$L}{"Approx"} &&
s/$Lang{$L}{"Approx"}//) {
$Curr{"Mode"}=1;
} elsif ($Lang{$L}{"Business"} &&
s/$Lang{$L}{"Business"}//) {
$Curr{"Mode"}=2;
} elsif (! exists $Curr{"Mode"}) {
$Curr{"Mode"}=0;
}
# Unfortunately, some deltas can be parsed as dates. An example is
# 1 second == 1 2nd == 1 2
# But, some dates can be parsed as deltas. The most important being:
# 1998010101:00:00
#
# We'll check to see if a "date" can be parsed as a delta. If so, we'll
# assume that it is a delta (since they are much simpler, it is much
# less likely that we'll mistake a delta for a date than vice versa)
# unless it is an ISO-8601 date.
#
# This is important because we are using DateCalc to test whether a
# string is a date or a delta. Dates are tested first, so we need to
# be able to pass a delta into this routine and have it correctly NOT
# interpreted as a date.
#
# We will insist that the string contain something other than digits and
# colons so that the following will get correctly interpreted as a date
# rather than a delta:
# 12:30
# 19980101
$delta="";
$delta=ParseDateDelta($_) if (/[^:0-9]/);
# Put parse in a simple loop for an easy exit.
PARSE: {
my(@tmp)=Date_Split($_);
if (@tmp) {
($y,$m,$d,$h,$mn,$s)=@tmp;
last PARSE;
}
# Fundamental regular expressions
my($month)=$Lang{$L}{"Month"}; # (jan|january|...)
my(%month)=%{ $Lang{$L}{"MonthH"} }; # { jan=>1, ... }
my($week)=$Lang{$L}{"Week"}; # (mon|monday|...)
my(%week)=%{ $Lang{$L}{"WeekH"} }; # { mon=>1, monday=>1, ... }
my($wom)=$Lang{$L}{"WoM"}; # (1st|...|fifth|last)
my(%wom)=%{ $Lang{$L}{"WoMH"} }; # { 1st=>1,... fifth=>5,last=>-1 }
my($dom)=$Lang{$L}{"DoM"}; # (1st|first|...31st)
my(%dom)=%{ $Lang{$L}{"DoMH"} }; # { 1st=>1, first=>1, ... }
my($ampmexp)=$Lang{$L}{"AmPm"}; # (am|pm)
my($timeexp)=$Lang{$L}{"Times"}; # (noon|midnight)
my($now)=$Lang{$L}{"Now"}; # now
my($today)=$Lang{$L}{"Today"}; # today
my($offset)=$Lang{$L}{"Offset"}; # (yesterday|tomorrow)
my($zone)=$Zone{"zones"}; # (edt|est|...)
my($day)='\s*'.$Lang{$L}{"Dabb"}; # \s*(?:d|day|days)
my($mabb)='\s*'.$Lang{$L}{"Mabb"}; # \s*(?:mon|month|months)
my($wkabb)='\s*'.$Lang{$L}{"Wabb"}; # \s*(?:w|wk|week|weeks)
my($next)='\s*'.$Lang{$L}{"Next"}; # \s*(?:next)
my($prev)='\s*'.$Lang{$L}{"Prev"}; # \s*(?:last|previous)
my($past)='\s*'.$Lang{$L}{"Past"}; # \s*(?:ago)
my($future)='\s*'.$Lang{$L}{"Future"}; # \s*(?:in)
my($later)='\s*'.$Lang{$L}{"Later"}; # \s*(?:later)
my($at)=$Lang{$L}{"At"}; # (?:at)
my($of)='\s*'.$Lang{$L}{"Of"}; # \s*(?:in|of)
my($on)='(?:\s*'.$Lang{$L}{"On"}.'\s*|\s+)';
# \s*(?:on)\s* or \s+
my($last)='\s*'.$Lang{$L}{"Last"}; # \s*(?:last)
my($hm)=$Lang{$L}{"SepHM"}; # :
my($ms)=$Lang{$L}{"SepMS"}; # :
my($ss)=$Lang{$L}{"SepSS"}; # .
# Other regular expressions
my($D4)='(\d{4})'; # 4 digits (yr)
my($YY)='(\d{4}|\d{2})'; # 2 or 4 digits (yr)
my($DD)='(\d{2})'; # 2 digits (mon/day/hr/min/sec)
my($D) ='(\d{1,2})'; # 1 or 2 digit (mon/day/hr)
my($FS)="(?:$ss\\d+)?"; # fractional secs
my($sep)='[\/.-]'; # non-ISO8601 m/d/yy separators
=9= |