Date::Piece - efficient dates with Time::Piece interoperability


NAME

Date::Piece - efficient dates with Time::Piece interoperability

Back to Top


SYNOPSIS

  use Date::Piece qw(date);
  my $date = date('2007-11-22');
  my $time = $date->at('16:42:35');
  print $time, "\n"; # is a Time::Piece

You can also start from a Time::Piece object.

  use Time::Piece;
  use Date::Piece;
  my $time = localtime;
  my $date = $time->date; # also ymd()
  $date+=7;
  # seven days later
  print $date, "\n";
  # seven days later at the original time
  print $date->at($time), "\n";

Back to Top


ABOUT

This module allows you to do nominal math on dates. That is, rather than worrying about time zones and DST while adding increments of 24*60**2 seconds to a date&time object, you simply discard the time component and do math directly on the date. If you need a time-of-day on the calculated date, the at() method returns a Time::Piece object, thus allowing you to be specific about the endpoints of a nominal interval.

This is useful for constructs such as "tomorrow", "yesterday", "this time tomorrow", "one week from today", "one month later", "my 31st birthday", and various other not-necessarily-numeric intervals on the arbitrary and edge-case-laden division of time known by most earthlings as "the calendar." That is, adding days or months is analogous to counting squares or turning pages on a calendar.

This module extends Date::Simple and connects it to Time::Piece. See Date::Simple for more details.

Back to Top


Immutable

A Date::Piece object never changes. This means that methods like add_months() always return a new object.

This does not appear to be true with constructs such as $date++ or $date+=7, but what is actually happening is that perl treats the variable as an lvalue and assigns the new object to it. Thus, the following is true:

  my $also_date = my $date = today;
  $date++;
  $date > $also_date;

Back to Top


Validation

Where Date::Simple returns false for invalid dates, I throw errors.

Back to Top


Convenient Syntax

You may import the functions 'date' and 'today' as well as the unit-qualifiers 'years', 'months', and 'weeks'.

When loaded as -MDate::Piece with perl -e (and/or -E in 5.10), these extremely short versions are exported by default:

  years  => 'Y',
  months => 'M',
  weeks  => 'W',
  date   => 'D',
  today  => 'CD', # mnemonic: Current Date

You may unimport any imported functions with the 'no Date::Piece' directive.

Back to Top


Functions

today

This returns the current date. Don't be afraid to use it in arithmetic.

  my $today = today;
  my $tomorrow = today + 1;

date

  my $new_year_is_coming = date('2007-12-31');

Equivalent to Date::Piece->new('2007-12-31');

Also takes year, month, day arguments.

  my $d = date($year, $month, $day);

unimport

Clean-out the imported methods from your namespace.

  no Date::Piece;

new

Takes the same arguments as date().

Back to Top


Methods

TODO paste most of the Date::Simple documentation here?

Note: lack of complete API compatibility with Time::Piece

Ideally, we should have the Time::Piece API, but Date::Simple doesn't do that. I'm trying to avoid a complete fork of Date::Simple, but will likely need to do that just to make e.g. month() do the same thing that it does in Time::Piece. Ultimately, a Date::Piece should act exactly like a Time::Piece where the time is always midnight (which implies that adding seconds upgrades the result to a Time::Piece and etc.)

iso_dow

Returns the day of the week (0-6) with Monday = 0 (as per ISO 8601.)

  my $dow = $date->iso_dow;

See day_of_week() if you want Sunday as the first day (as in localtime.)

iso_wday

Returns 1-7 where Monday is 1.

  my $wday = $date->iso_wday;

Back to Top


Setting the Time on a Date

at

Returns a Time::Piece object at the given time on the date $date.

  my $timepiece = $date->at($time);

$time can be in 24-hour format (seconds optional) or have an 'am' or 'pm' (case insensitive) suffix.

$time may also be of the form '1268s', which will be taken as a number of seconds to be added to midnight on the given day (and may be negative.)

The time is constructed via Time::Local. For concerns about daylight savings, see the caveats in Time::Local.

If $time is a Time::Piece from a different time zone, we *should* respect that, but currently do the wrong thing.

Back to Top


Endpoints

These are all very simple, but convenient.

start_of_year

January 1st of the year containing $date.

  my $start = $date->start_of_year;

end_of_year

December 31st of the year containing $date.

  my $end = $date->end_of_year;

start_of_month

Returns the 1st of the month containing $date.

  my $start = $date->start_of_month;

end_of_month

Returns the last day of the month containing $date.

  my $end = $date->end_of_month;

days_in_month

Returns the number of days in the month containing $date.

  my $num = $date->days_in_month;

See also Date::Simple::days_in_month($year, $month).

leap_year

Returns true if Date is in a leap year.

  my $bool = $date->leap_year;

See also Date::Simple::leap_year($year).

thru

Returns a list ala $start..$end (because overloading doesn't work with the '..' construct.)

  my @list = $date->thru($other_date);

iterator

Returns a subref which iterates through the dates between $date and $other_date (inclusive.)

  my $subref = $date->iterator($other_date);
  while(my $day = $subref->()) {
    # do something with $day
  }

Back to Top


Fuzzy Math

We can do math with months and years as long as you're flexible about the day of the month. The theme here is to keep the answer within the destination calendar month rather than adding e.g. 30 days.

adjust_day_of_month

Returns a valid date even if the given day is beyond the last day of the month (returns the last day of that month.)

  $date = adjust_day_of_month($y, $m, $maybe_day);

add_months

Adds $n nominal months to $date. This will just be a simple increment of the months (rolling-over at 12) as long as the day part is less than 28. If the destination month doesn't have as many days as the origin month, the answer will be the last day of the destination month (via adjust_day_of_month().)

  my $shifted = $date->add_months($n);

Note that if $day > 28 this is not reversible. One should not rely on it for incrementing except in trivial cases where $day <= 28 (because calling $date = $date->add_months(1) twice is not necessarily the same result as $date = $date->add_months(2).)

add_years

Equivalent to adding $n*12 months.

  my $shifted = $date->add_years($n);

Back to Top


Year, Month, and etc "units"

The constants 'years', 'months', and 'weeks' may be multiplied by an integer and added to (or subtracted from) a date.

  use Date::Piece qw(today years);
  my $distant_future = today + 10*years;
  perl -MDate::Piece -e 'print CD+10*Y, "\n";'

The unit objects stringify as e.g. '10years'.

You may also divide time units by a number as long as the result is an integer. You may not use units as a divisor.

Any math done on these units which yields other than an integer will throw a run-time error.

Also available are 'centuries' and 'days' (the latter is convenient as a stricture to ensure that your days are integers.)

Conversion between these units only makes sense for centuries => years and weeks => days, but is currently not available.

_add

  $date = $date->_add($thing);

_subtract

  $date = $date->_subtract($thing);

Back to Top


Examples

These all assume imported syntactical sugar ala:

  use Date::Piece qw(date today years months weeks);
  use Time::Piece;

Turning 40 is pretty arbitrary, but alarming!

  my $bd = date('1970-12-02');
  my $big40 = $bd+40*years;
  $SIG{ALRM} = sub { print "dude!  You're 'old' now.\n"; exit; }
  my $eggtimer = localtime - $big40->at('06:57');
  alarm($eggtimer);
  while(1) {
    my $countdown = $big40-today;
    print "$countdown days till the top of the hill\n";
    sleep(3600*24);
  }

Wake me when the ball drops (in my time zone.)

  my $date = today+1*years;
  $date = $date->start_of_year;
  $SIG{ALRM} = sub { print "Happy new year!\n"; exit; }
  alarm(localtime - $date->at('0s'));

Back to Top


Constructor

Back to Top


AUTHOR

Eric Wilhelm @ <ewilhelm at cpan dot org>

http://scratchcomputing.com/

Back to Top


BUGS

If you found this module on CPAN, please report any bugs or feature requests through the web interface at http://rt.cpan.org. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

If you pulled this development version from my /svn/, please contact me directly.

Back to Top


COPYRIGHT

Copyright (C) 2007 Eric L. Wilhelm, All Rights Reserved.

Back to Top


NO WARRANTY

Absolutely, positively NO WARRANTY, neither express or implied, is offered with this software. You use this software at your own risk. In case of loss, no person or entity owes you anything whatsoever. You have been warned.

Back to Top


LICENSE

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

Back to Top

 Date::Piece - efficient dates with Time::Piece interoperability