package DateTime::Format::JavaScript;

use warnings;
use strict;

our $VERSION = '0.02';

use DateTime::TimeZone;

use constant WDAYS  => qw/Mon Tue Wed Thu Fri Sat Sun/;
use constant MONTHS => qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/;
use constant RE_WDAYS  => qr/@{[ join "|", WDAYS ]}/;
use constant RE_MONTHS => qr/@{[ join "|", MONTHS ]}/;

{
    my %mon2num;
    my $i = 1;
    foreach ( MONTHS ) {
        $mon2num{$_} = $i++;
    }

    sub _fix_month {
        my %args = @_;
        my $p = $args{parsed};
        $p->{month} = $mon2num{$p->{month}};
        return 1;
    }
}

use DateTime::Format::Builder (
    parsers => {
        parse_datetime => [
            {  # UTC for IE style, GMT for Mozilla style
                params => [qw/ month day hour minute second time_zone year /],
                regex  => qr/^@{[RE_WDAYS]} (@{[RE_MONTHS]}) (\d{1,2}) (\d\d):(\d\d):(\d\d) (?:UTC|GMT)([-+]\d{4}) (\d{4})$/,
                postprocess => \&_fix_month,
            },
            {  # For IE (when Date constructor called as function, it returns string representing current time without time-zone).
                params => [qw/ month day hour minute second year /],
                regex  => qr/^@{[RE_WDAYS]} (@{[RE_MONTHS]}) (\d{1,2}) (\d\d):(\d\d):(\d\d) (\d{4})$/,
                postprocess => \&_fix_month,
            },
            {  # For Opera 9
                params => [qw/ day month year hour minute second time_zone /],
                regex  => qr/^@{[RE_WDAYS]}, (\d{1,2}) (@{[RE_MONTHS]}) (\d{4}) (\d\d):(\d\d):(\d\d) GMT([-+]\d{4})$/,
                postprocess => \&_fix_month,
            },
            {  # Safari 7 / Chrome 36 / Firefox 30
                params => [qw/ month day year hour minute second time_zone /],
                regex  => qr/^@{[RE_WDAYS]} (@{[RE_MONTHS]}) (\d{1,2}) (\d{4}) (\d\d):(\d\d):(\d\d) GMT([-+]\d{4})/,
                postprocess => \&_fix_month,
            },
        ],
    }
);


sub format_datetime {
    my ($self, $dt) = @_;
    sprintf "%s %s %d %02d:%02d:%02d UTC%+05d %04d",
            (WDAYS)[$dt->wday-1],
            (MONTHS)[$dt->mon-1],
            $dt->day,
            $dt->hour,
            $dt->min,
            $dt->sec,
            DateTime::TimeZone->offset_as_string($dt->offset),
            $dt->year;
}



1;
__END__

=encoding utf-8

=head1 NAME

DateTime::Format::JavaScript - Parses and formats Date of JavaScript

=head1 SYNOPSIS

    use DateTime::Format::JavaScript;

    # Modern browsers
    my $dt = DateTime::Format::JavaScript->parse_datetime("Sat Jul 26 2014 16:37:29 GMT+0900 (JST)");
    print $dt;  # 2014-07-26T16:37:29

    # Ancient Opera
    my $dt = DateTime::Format::JavaScript->parse_datetime("Sat, 26 Jul 2014 16:37:29 GMT+0900");
    print $dt;  # 2014-07-26T16:37:29

=head1 DESCRIPTION

DateTime::Format::JavaScript - Parse Date string generated by JavaScript engines
of Web browsers.

=head1 METHODS

=head2 DateTime::Format::JavaScript->parse_datetime( I<$str> )

Given a JavaScript's C<Date> string, this will return a new C<DateTime> object.

If I<$str> is improperly formatted, this will croak.

=head2 DateTime::Format::JavaScript->format_datetime( I<$dt> )

Given a C<DateTime> object, this will return formatted string.

B<CAVEAT>: this method cannot return time-zone string properly.

=head1 LICENSE

Copyright (C) Daisuke (yet another) Maki.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=head1 AUTHOR

Daisuke (yet another) Maki

=cut
