The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

class Duration::Gregorian is Duration;

use Date::Format::ISO8601;

our $iso8601_duration_re_anchored = rx:perl5/^$iso8601_duration_re$/;

has Int $.year;
has Int $.month;
has Int $.day;
has Int $.hour;
has Int $.minute;
has $.second;

# do subs that get declared first "win" the MMD war?
multi sub duration( Int|Real ?$seconds ) returns Duration::Gregorian is export {
    duration(:second($seconds));
}

multi sub duration( Int ?$year, Int ?$month, Int ?$day,
                    Int ?$hour, Int ?$minute, Int|Real ?$second #)
                     )
    returns Duration::Gregorian is export {
    Duration::Gregorian.new( :year($year), :month($month), :day($day),
                             :hour($hour), :minute($minute), :second($second),
                           );
}

# convert from an iso duration
multi method duration( Str $iso8601 ) returns Duration::Gregorian is export {

    # FIXME - missing XXXX 
    $iso8601 ~~ $iso8601_duration_re_anchored
        or die "can't match '$iso8601' to available ISO-8601 duration formats";

=pod

    my $duration;
    if ( defined $0 ) {
        $duration = duration($/[1..7]);
        if ( defined $8 ) {
            $duration.end = duration($/[9..17]);
        }
    }
    elsif ( defined $/[18] ) {
        my $start = date($/[19..27]);

        if ( defined $/[28] ) {
            $duration = duration($/[29..35]);
            $duration.start = $start;
        } else {
            my $end = date($/[37..35]);
            $duration = Duration::Gregorian.new
                ( :start($start), :end($end) );
        }
    } else {
        !!!
    }

=cut


    return $duration;
}

# operations with Duration::Gregorian constructors..
##multi method infix:<+>( $self: Str|Int|Real $iso8601_dur ) {
    #$self + duration($iso8601_dur);
#}

##multi method infix:<->( $self: Int|Real $iso8601_dur ) {
    #$self + duration($iso8601_dur);
#}

#multi method infix:<->( $self: Str $what ) {
    #my $other = eval { date($what) };
    #if ( $other ) {
        #return $self - $other;
    #} else {
        #return $self - duration($what);
    #}
#}