|
Packit |
9002b2 |
# we need to comment this out or PAUSE might index it
|
|
Packit |
9002b2 |
# pack age DateTime::Format::W3CDTF;
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
use strict;
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
use DateTime::Format::Builder (
|
|
Packit |
9002b2 |
parsers => {
|
|
Packit |
9002b2 |
parse_datetime => [
|
|
Packit |
9002b2 |
[ preprocess => \&_parse_tz ],
|
|
Packit |
9002b2 |
{
|
|
Packit |
9002b2 |
params => [qw( year month day hour minute second)],
|
|
Packit |
9002b2 |
regex =>
|
|
Packit |
9002b2 |
qr/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)\.(\d\d)$/,
|
|
Packit |
9002b2 |
length => 22,
|
|
Packit |
9002b2 |
},
|
|
Packit |
9002b2 |
{
|
|
Packit |
9002b2 |
params => [qw( year month day hour minute second)],
|
|
Packit |
9002b2 |
regex => qr/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/,
|
|
Packit |
9002b2 |
length => 19,
|
|
Packit |
9002b2 |
},
|
|
Packit |
9002b2 |
{
|
|
Packit |
9002b2 |
params => [qw( year month day hour minute)],
|
|
Packit |
9002b2 |
regex => qr/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)$/,
|
|
Packit |
9002b2 |
length => 16,
|
|
Packit |
9002b2 |
},
|
|
Packit |
9002b2 |
{
|
|
Packit |
9002b2 |
params => [qw( year month day )],
|
|
Packit |
9002b2 |
regex => qr/^(\d{4})-(\d\d)-(\d\d)$/,
|
|
Packit |
9002b2 |
length => 10,
|
|
Packit |
9002b2 |
},
|
|
Packit |
9002b2 |
{
|
|
Packit |
9002b2 |
params => [qw( year month )],
|
|
Packit |
9002b2 |
regex => qr/^(\d{4})-(\d\d)$/,
|
|
Packit |
9002b2 |
length => 7,
|
|
Packit |
9002b2 |
extra => { day => 1 },
|
|
Packit |
9002b2 |
},
|
|
Packit |
9002b2 |
{
|
|
Packit |
9002b2 |
params => [qw( year )],
|
|
Packit |
9002b2 |
regex => qr/^(\d\d\d\d)$/,
|
|
Packit |
9002b2 |
length => 4,
|
|
Packit |
9002b2 |
extra => { month => 1, day => 1 }
|
|
Packit |
9002b2 |
}
|
|
Packit |
9002b2 |
]
|
|
Packit |
9002b2 |
}
|
|
Packit |
9002b2 |
);
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
sub _parse_tz {
|
|
Packit |
9002b2 |
my %args = @_;
|
|
Packit |
9002b2 |
my ( $date, $p ) = @args{qw( input parsed )};
|
|
Packit |
9002b2 |
if ( $date =~ s/([+-]\d\d:\d\d)$// ) {
|
|
Packit |
9002b2 |
$p->{time_zone} = $1;
|
|
Packit |
9002b2 |
}
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
# Z at end means UTC
|
|
Packit |
9002b2 |
elsif ( $date =~ s/Z$// ) {
|
|
Packit |
9002b2 |
$p->{time_zone} = 'UTC';
|
|
Packit |
9002b2 |
}
|
|
Packit |
9002b2 |
else {
|
|
Packit |
9002b2 |
$p->{time_zone} = 'floating';
|
|
Packit |
9002b2 |
}
|
|
Packit |
9002b2 |
return $date;
|
|
Packit |
9002b2 |
}
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
sub format_datetime {
|
|
Packit |
9002b2 |
my ( $self, $dt ) = @_;
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
my $base = (
|
|
Packit |
9002b2 |
$dt->hour || $dt->min || $dt->sec
|
|
Packit |
9002b2 |
? sprintf(
|
|
Packit |
9002b2 |
'%04d-%02d-%02dT%02d:%02d:%02d',
|
|
Packit |
9002b2 |
$dt->year, $dt->month, $dt->day,
|
|
Packit |
9002b2 |
$dt->hour, $dt->minute, $dt->second
|
|
Packit |
9002b2 |
)
|
|
Packit |
9002b2 |
: sprintf( '%04d-%02d-%02d', $dt->year, $dt->month, $dt->day )
|
|
Packit |
9002b2 |
);
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
my $tz = $dt->time_zone;
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
return $base if $tz->is_floating;
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
# if there is a time component
|
|
Packit |
9002b2 |
if ( $dt->hour || $dt->min || $dt->sec ) {
|
|
Packit |
9002b2 |
return $base . 'Z' if $tz->is_utc;
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
if ( $tz->{'offset'} ) {
|
|
Packit |
9002b2 |
return $base . offset_as_string( $tz->{'offset'} );
|
|
Packit |
9002b2 |
}
|
|
Packit |
9002b2 |
}
|
|
Packit |
9002b2 |
else {
|
|
Packit |
9002b2 |
return $base;
|
|
Packit |
9002b2 |
}
|
|
Packit |
9002b2 |
}
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
# minor offset_as_string variant w/ :
|
|
Packit |
9002b2 |
#
|
|
Packit |
9002b2 |
sub offset_as_string {
|
|
Packit |
9002b2 |
my $offset = shift;
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
return undef unless defined $offset;
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
my $sign = $offset < 0 ? '-' : '+';
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
my $hours = $offset / ( 60 * 60 );
|
|
Packit |
9002b2 |
$hours = abs($hours) % 24;
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
my $mins = ( $offset % ( 60 * 60 ) ) / 60;
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
my $secs = $offset % 60;
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
return (
|
|
Packit |
9002b2 |
$secs
|
|
Packit |
9002b2 |
? sprintf( '%s%02d:%02d:%02d', $sign, $hours, $mins, $secs )
|
|
Packit |
9002b2 |
: sprintf( '%s%02d:%02d', $sign, $hours, $mins )
|
|
Packit |
9002b2 |
);
|
|
Packit |
9002b2 |
}
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
1;
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
__END__
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
=head1 NAME
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
DateTime::Format::W3CDTF - Parse and format W3CDTF datetime strings
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
=head1 SYNOPSIS
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
use DateTime::Format::W3CDTF;
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
my $f = DateTime::Format::W3CDTF->new;
|
|
Packit |
9002b2 |
my $dt = $f->parse_datetime( '2003-02-15T13:50:05-05:00' );
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
# 2003-02-15T13:50:05-05:00
|
|
Packit |
9002b2 |
$f->format_datetime($dt);
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
=head1 DESCRIPTION
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
This module understands the W3CDTF date/time format, an ISO 8601 profile,
|
|
Packit |
9002b2 |
defined at http://www.w3.org/TR/NOTE-datetime. This format as the native
|
|
Packit |
9002b2 |
date format of RSS 1.0.
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
It can be used to parse these formats in order to create the appropriate
|
|
Packit |
9002b2 |
objects.
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
=head1 METHODS
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
This API is currently experimental and may change in the future.
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
=over 4
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
=item * parse_datetime($string)
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
Given a W3CDTF datetime string, this method will return a new
|
|
Packit |
9002b2 |
C<DateTime> object.
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
If given an improperly formatted string, this method may die.
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
=item * format_datetime($datetime)
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
Given a C<DateTime> object, this methods returns a W3CDTF datetime
|
|
Packit |
9002b2 |
string.
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
=back
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
=head1 SUPPORT
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
Support for this module is provided via the datetime@perl.org email
|
|
Packit |
9002b2 |
list. See http://lists.perl.org/ for more details.
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
=head1 AUTHOR
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
Kellan Elliott-McCrea <kellan@protest.net>
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
This module was inspired by C<DateTime::Format::ICal>
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
=head1 COPYRIGHT
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
Copyright (c) 2003 Kellan Elliott-McCrea. All rights reserved. This program
|
|
Packit |
9002b2 |
is free software; you can redistribute it and/or modify it under the
|
|
Packit |
9002b2 |
same terms as Perl itself.
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
The full text of the license can be found in the LICENSE file included
|
|
Packit |
9002b2 |
with this module.
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
=head1 SEE ALSO
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
datetime@perl.org mailing list
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
http://datetime.perl.org/
|
|
Packit |
9002b2 |
|
|
Packit |
9002b2 |
=cut
|