Date manipulation
Perl 6 comes with a build-in DateTime type to support most aspects of standard civic time calculation that are not dependent on cultural idiosyncracies.
Unfortunately, Perl 6 does not yet have a date parsing module (mostly due to a reticence to inflict Western cultural imperialism on other cultures... or maybe just due to laziness), but that just gives us another opportunity to demonstrate the built-in grammar support.
my @month = <January February March April May June July August September October November December>;
my %month = flat (@month Z=> ^12), (@month».substr(0,3) Z=> ^12), 'Sept' => 8;
grammar US-DateTime {
rule TOP { <month> <day>','? <year>','? <time> <tz> }
token month {
(\w+)'.'? { make %month{$0} // die "Bad month name: $0" }
}
token day { (\d ** 1..2) { make +$0 } }
token year { (\d ** 1..4) { make +$0 } }
token time {
(\d ** 1..2) ':' (\d ** 2) \h* ( :i <[ap]> \.? m | '' )
{
my $h = $0 % 12;
my $m = $1;
$h += 12 if $2 and $2.substr(0,1).lc eq 'p';
make $h * 60 + $m;
}
}
token tz { # quick and dirty for this task
[
| EDT { make -4 }
| [ EST| CDT] { make -5 }
| [ CST| MDT] { make -6 }
| [ MST| PDT] { make -7 }
| [ PST|AKDT] { make -8 }
| [AKST|HADT] { make -9 }
| HAST
]
}
}
$/ = US-DateTime.parse('March 7 2009 7:30pm EST') or die "Can't parse date";
my $year = $<year>.ast;
my $month = $<month>.ast;
my $day = $<day>.ast;
my $hour = $<time>.ast div 60;
my $minute = $<time>.ast mod 60;
my $timezone = $<tz>.ast * 3600;
my $dt = DateTime.new(:$year, :$month, :$day, :$hour, :$minute, :$timezone).in-timezone(0);
$dt = $dt.later(hours => 12);
say "12 hours later, GMT: $dt";
say "12 hours later, PST: $dt.in-timezone(-8 * 3600)";
Output:
12 hours later, GMT: 2009-02-08T12:30:00Z
12 hours later, PST: 2009-02-08T04:30:00-0800