NAME
DateTime::Moonpig - Saner interface to DateTime
SYNOPSIS
$birthday = DateTime::Moonpig->new( year => 1969,
month => 4,
day => 2,
hour => 2,
minute => 38,
);
$now = DateTime::Moonpig->new( time() );
printf "%d\n", $now - $birthday; # returns number of seconds difference
$later = $now + 60; # one minute later
$earlier = $now - 2*3600; # two hours earlier
if ($now->follows($birthday)) { ... } # true
if ($birthday->precedes($now)) { ... } # also true
DESCRIPTION
Moonpig::DateTime
is a thin wrapper around the DateTime module to fix problems with that module's design and interface. The main points are:
Methods for mutating
DateTime::Moonpig
objects in place have been overridden to throw a fatal exception. These includeadd_duration
andsubtract_duration
,set_
* methods such asset_hour
, andtruncate
.The addition and subtraction operators have been overridden.
Adding a
DateTime::Moonpig
to an integer n returns a newDateTime::Moonpig
equal to a time n seconds later than the original. Similarly, subtracting n returns a newDateTime::Moonpig
equal to a time n seconds earlier than the original.Subtracting two
DateTime::Moonpig
s returns the number of seconds elapsed between them. It does not return an object of any kind.The
new
method can be called with a single argument, which is interpreted as a Unix epoch time, such as is returned by Perl's built-intime()
function.A few convenient methods have been added
CHANGES TO DateTime
METHODS
new
DateTime::Moonpig::new
is just like DateTime::new
, except:
The call
DateTime::Moonpig->new( $n )
is shorthand for
DateTime::Moonpig->from_epoch( epoch => $n )
If no
time_zone
argument is specified, the returned object will be created in theUTC
time zone.DateTime
creates objects in its "floating" time zone by default. Such objects can be created viaDateTime::Moonpig->new( time_zone => "floating", ... );
if you think that's what you really want. I advise against it because a
DateTime
object without an attached time zone has no definite meaning. It seems to refer to a particular time, but when pressed to say what time it refers to, you can't.new
can be called on aDateTime::Moonpig
object, which is then ignored. So for example if$dtm
is anyDateTime::Moonpig
object, then these two calls are equivalent:$dtm->new( ... ); DateTime::Moonpig->new( ... );
Mutators are fatal errors
The following DateTime
methods will throw an exception if called:
add_duration
subtract_duration
truncate
set
set_year
set_month
set_day
set_hour
set_minute
set_second
set_nanosecond
Rik has a sad story about why these are a bad idea: http://rjbs.manxome.org/rubric/entry/1929 (Summary: mutable state is the enemy.)
The following mutators don't actually mutate the time value, and are allowed:
set_time_zone
set_locale
set_formatter
The behavior of set_time_zone
is complicated by the DateTime
module's handling of time zone changes. It is possible to mutate a time by setting its time zone to "floating" and then setting it again. The normal behavior of DateTime
, to preserve the actual time represented by the object, is bypassed if you do this.
OVERLOADING
The overloading of all operators, except +
and -
, is inherited from DateTime
.
Summary
The +
and -
operators behave as follows:
You can add a
DateTime::Moonpig
to a scalar, which will be interpreted as a number of seconds to move forward in time. (Or backward, if negative.)You can similarly subtract a scalar from a
DateTime::Moonpig
. Subtracting aDateTime::Moonpig
from a scalar is a fatal error.You can subtract a
DateTime::Moonpig
from another date object, such as anotherDateTime::Moonpig
, or vice versa. The result is the number of seconds between the times represented by the two objects.An object will be treated like a scalar if it implements an
as_seconds
method; it will be treated like a date object if it implements anepoch
method.
Full details
You can add a number to a DateTime::Moonpig
object, or subtract a number from a DateTime::Moonpig
object; the number will be interpreted as a number of seconds to add or subtract:
# 1969-04-02 02:38:00
$birthday = DateTime::Moonpig->new( year => 1969,
month => 4,
day => 2,
hour => 2,
minute => 38,
second => 0,
);
$x0 = $birthday + 10; # 1969-04-02 02:38:10
$x1 = $birthday - 10; # 1969-04-02 02:37:50
$x2 = $birthday + (-10); # 1969-04-02 02:37:50
$x3 = $birthday + 100; # 1969-04-02 02:39:40
$x4 = $birthday - 100; # 1969-04-02 02:36:20
# identical to $birthday + 100
$x5 = 100 + $birthday; # 1969-04-02 02:39:40
# forbidden
$x6 = 100 - $birthday; # croaks
# handy technique
sub hours { $_[0} * 3600 }
$x7 = $birthday + hours(12); # 1969-04-02 14:38:00
$x8 = $birthday - hours(12); # 1969-04-01 14:38:00
$birthday
is never modified by any of this. The resulting objects will be in the same time zone as the original object, in this case UTC.
You can add any object to a DateTime::Moonpig
object if the other object supports an as_seconds
method. DateTime
and DateTime::Moonpig
objects do not provide this method.
package MyDaysInterval; # Silly example
sub new {
my ($class, $days) = @_;
bless { days => $days } => $class;
}
sub as_seconds { $_[0]{days} * 86400 }
package main;
my $three_days = MyDaysInterval->new(3);
$y0 = $birthday + $three_days; # 1969-04-05 02:38:00
# forbidden
$y1 = $birthday + DateTime->new(...); # croaks
$y2 = $birthday + $birthday; # croaks
Again, $birthday
is not modified by any of this arithmetic.
You can subtract any object from a DateTime::Moonpig
object, but not vice versa, if that object provides an as_seconds
method. It will be interpreted as a time interval, and the result will be a new DateTime::Moonpig
object:
$z2 = $birthday - $three_days; # 1969-03-30 02:38:00
# forbidden
$z3 = $three_days - $birthday; # croaks
If you have another object that represents a time, and that implements an epoch
method that returns its value as seconds since the Unix epoch, you may subtract it from a DateTime::Moonpig
object or vice versa. The result is the number of seconds between the second and the first operands. Since DateTime::Moonpig
implements epoch
, you can subtract one DateTime::Moonpig
object from another to get the number of seconds difference between them:
$x0 = $birthday + 10; # 1969-04-02 02:38:10
$z4 = $x0 - $birthday; # 10
$z5 = $birthday - $x0; # -10
package Feb13; # Silly example
sub new {
my ($class) = @_;
bless [ "DUMMY" ] => $class;
}
sub epoch { return 1234567890 } # Feb 13 23:31:30 2009 UTC
package main;
my $feb13 = Feb13->new();
$feb13_dt = DateTime->new( year => 2009,
month => 2,
day => 13,
hour => 23,
minute => 31,
second => 30,
time_zone => "UTC",
);
$z6 = $birthday - $feb13; # -1258232010
$z7 = $birthday - $feb13_dt; # -1258232010
$z8 = $feb13 - $birthday; # 1258232010
# WATCH OUT - will NOT return 1258232010
$z9 = $feb13_dt - $birthday; # returns a DateTime::Duration object
In this last example, DateTime
's overloading is respected, rather than DateTime::Moonpig
's, and we get back a DateTime::Duration
object that represents the elapsed difference of 40-some years. Sorry, can't fix that; it's determined by Perl, which has to decide which of the two conflicting definitions of -
to honor, and chooses the other one.
None of these subtractions will modify any of the argument objects.
interval_factory
When two time objects are subtracted, the result is normally a number. However, the numeric difference is first passed to the target object's interval_factory
method, which has the option to transform it and return an object (or something else) instead. The default interval_factory
returns its argument unchanged. So for example,
$z0 = $x0 - $birthday; # 10
is actually returning the result of $x0->interval_factory(10)
, which is 10.
Absolute time, not calendar time
DateTime::Moonpig
plus
and minus
always do real-time calculations, never civil calendar calculations. If your locality began observing daylight savings on 2007-03-11, as most of the USA did, then:
$a_day = DateTime::Moonpig->new( year => 2007,
month => 3,
day => 11,
hour => 1,
minute => 0,
second => 0,
time_zone => "America/New_York",
);
$next_day = $a_day->plus(24*3600);
At this point $next_day
is exactly 24·3600 seconds ahead of $a_day
. Because the civil calendar day for 2007-03-11 in New York was only 23 hours long, $next_day
represents represents 2007-03-12 02:00:00 instead of 2007-03-12 01:00:00. This should be what you expect; if not please correct your expectation.
NEW METHODS
new_datetime
DateTime::Moonpig->new_datetime( $dt )
takes a DateTime
object and returns an equivalent DateTime::Moonpig
object.
plus
, minus
These methods implement the overloading for the +
and -
operators as per "OVERLOADING" above. See the overload man page for fuller details.
precedes
, follows
$a->precedes($b)
$a->follows($b)
return true if time $a
is strictly earlier than time $b
, or strictly later than time $b
, respectively. If $a
and $b
represent the same time, both methods will return false. At most one will be true for a given pair of dates. They are implemented as calls to DateTime::compare
.
st
Return a string representing the target time in the format
1969-04-02 02:38:00
This is convenient and readable, but does not comply with ISO 8601. It also omits the time zone, so beware.
The name st
is short for "string".
number_of_days_in_month
This method takes no argument and returns the number of days in the month it represents. For example:
DateTime::Moonpig->new( year => 1969,
month => 4,
day => 2,
)
->number_of_days_in_month()
returns 30.
interval_factory
Used internally for manufacturing objects that represent time intervals. See the description of the -
operator under "OVERLOADING", above.
BUGS
Please submit bug reports at https://github.com/mjdominus/DateTime-Moonpig/issues.
Please *do not* submit bug reports at http://rt.cpan.org/
.
LICENSE
Copyright © 2010 IC Group, Inc.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
See the LICENSE
file for a full statement of your rights under this license.
AUTHOR
Mark Jason DOMINUS, mjd@cpan.org
Ricardo SIGNES, rjbs@cpan.org
WUT
DateTime::Moonpig
was originally part of the Moonpig project, where it was used successfully for several years before this CPAN release. For more complete details, see:
http://blog.plover.com/prog/Moonpig.html - Long blog article on the design and development of Moonpig generally.
http://perl.plover.com/yak/Moonpig/ - Slides and other materials from a one-hour talk about Moonpig.
http://www.perladvent.org/2013/2013-12-23.html - Perl 2013 Advent Calendar article introducing this module and complaining about
DateTime::Duration
.