class Date; #my subtype Month of Int where { 1 <= $^a <= 12 }; #my subtype Day of Int where { 1 <= $^a <= 31 }; has Int $.year; has Int $.month; has Int $.day; # where { }; XXX - check that day is valid for month & year my @MonthLengths = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); my @LeapYearMonthLengths = @MonthLengths; @LeapYearMonthLengths[1]++; my @PreviousMonthDoY = ( 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ); my @PreviousMonthDoLY = ( 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 ); # has DateTime::Locale $.locale # probably this should be done as "multi submethod BUILD", but that # makes pugs barf last I checked multi submethod BUILD () returns Date { self.BUILD(time); } multi submethod BUILD (Int|Num $epoch) returns Date { # waiting for localtime in Pugs my $time = localtime(int $epoch); $!year = $time.year; $!month = $time.month; $!day = $time.day; } multi submethod BUILD (Str $_) returns Date { when 'now' { self.BUILD(); } when 'today' { self.BUILD(); } default { fail "Cannot parse $_ in date format"; } } # day as Str where { rx:i/^last$/ } multi submethod BUILD (Int :$year is mandatory, Int :$month = 1, Int|Str :$day is copy = 1) returns Date { if $day.lc eq 'last' { my @lengths := _is_leap_year($year) ?? @LeapYearMonthLengths !! @MonthLengths; $day = @lengths[ $month - 1 ]; } $.year = $year; $.month = $month; $.day = $day; } method today () returns Date { return Date.new( epoch => time ); } method now () returns Date { return Date.new( epoch => time ); } method tomorrow () returns Date { return Date.new( epoch => time ).add( days => 1 ); } method yesterday () returns Date { return Date.new( epoch => time ).subtract( days => 1 ); } sub _is_leap_year (Int $year) returns bool { if $year % 400 == 0 { return Bool::True; } elsif $year % 100 == 0 { return Bool::False; } elsif $year % 4 == 0 { return Bool::True; } return Bool::False; } method quarter () returns Int { return int( ( 1.0 / 3.1 ) * $.month ) + 1; } method day_of_quarter () returns Int { my $doy = self.day_of_year; my @doy := _is_leap_year($.year) ?? @PreviousMonthDoLY !! @PreviousMonthDoY; return $doy - @doy[ ( 3 * self.quarter ) - 3 ]; } method day_of_year () returns Int { my @doy := _is_leap_year($.year) ?? @PreviousMonthDoLY !! @PreviousMonthDoY; @doy[$.month - 1] + $.day; } method ymd (Str $sep = "-") returns Str { return [$.year, $.month, $.day].join($sep); } method mdy (Str $sep = "-") returns Str { return [$.month, $.day, $.year].join($sep); } method dmy (Str $sep = "-") returns Str { return [$.day, $.month, $.year].join($sep); } =kwid = NAME Date - An object representing a single date (without a time) = SYNOPSIS use Date; my $date = Date.new( year => 2005, month => 6, day => 29 ); say $date.year; say $date.ymd; = DESCRIPTION This class represents a date /without a time/. Because it is just a date, it does not handle time zones or leap seconds. All methods take named parameters unless otherwise specified. = CONSTRUCTORS - `new()` Without any parameters, this returns an object representing the current /local/ date. - `new( epoch => Int|Real $epoch)` Given an epoch time, returns a Date object based on that epoch. - `new( 'now' | 'today' | 'tomorrow' | 'yesterday' | $date_string )` Given a string, this module attempts to parse it. The strings "now", "today", "tomorrow", and "yesterday" return the appropriate date. Any other string will be passed to `Date::Something::WaveHands` for parsing. - `new( year => $year, month => $month, day => $day )` Returns a date object for the given values. The month and day default to 1 if not given. The value for day can also be the string "last", in which case the object returned represents the last day for the specified month. - `today()` - `now()` Synonyms for `Date.new('today')` - `tomorrow()` Synonym for `Date.new('tomorrow')` - `yesterday()` Synonym for `Date.new('yesterday')` = OBJECT METHODS The following methods are available for Date objects: - `year()` Returns the year for the object. - `month()` Returns the month for the object, from 1 to 12. - `day()` Returns the day for the object, from 1 to 31. - `day_of_year()` Returns the day of the year, from 1 to 366. - `quarter()` Returns the quarter of the year, from 1 to 4. - `day_of_quarter()` Returns the day of the quarter, from 1 to 92. = AUTHOR Dave Rolsky, = COPYRIGHT Copyright (c) 2005, Dave Rolsky. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut