Blame lib/Date/Manip/Calc.pod

Packit 95306a
# Copyright (c) 1995-2017 Sullivan Beck. All rights reserved.
Packit 95306a
# This program is free software; you can redistribute it and/or modify it
Packit 95306a
# under the same terms as Perl itself.
Packit 95306a
Packit 95306a
=pod
Packit 95306a
Packit 95306a
=head1 NAME
Packit 95306a
Packit 95306a
Date::Manip::Calc - describes date calculations
Packit 95306a
Packit 95306a
=head1 SYNOPSIS
Packit 95306a
Packit 95306a
Two objects (both of which are either L<Date::Manip::Date> or
Packit 95306a
L<Date::Manip::Delta> objects) may be used to creates a third object
Packit 95306a
based on those two.
Packit 95306a
Packit 95306a
   $delta  = $date->calc($date2 [,$subtract] [,$mode]);
Packit 95306a
Packit 95306a
   $date2  = $date->calc($delta [,$subtract]);
Packit 95306a
   $date2  = $delta->calc($date1 [,$subtract]);
Packit 95306a
Packit 95306a
   $delta3 = $delta1->calc($delta2 [,$subtract] [,$no_normalize]);
Packit 95306a
Packit 95306a
=head1 DESCRIPTION
Packit 95306a
Packit 95306a
This document describes the different types of calculations that can be
Packit 95306a
done using dates and deltas.  Date calculations are much more complicated
Packit 95306a
than they initially appear, so this document is fairly large.
Packit 95306a
Packit 95306a
The complication in date calculations is due to the fact that it is
Packit 95306a
impossible to express some parts of a delta as an exact length.  Some
Packit 95306a
examples will illustrate this:
Packit 95306a
Packit 95306a
As an example, let's take two dates and determine how much time elapsed
Packit 95306a
between them:
Packit 95306a
Packit 95306a
   Nov 3 2016 11:00:00
Packit 95306a
   Dec 5 2016 12:00:00
Packit 95306a
Packit 95306a
   Elapsed time: 770 hours
Packit 95306a
Packit 95306a
There are several ways to describe the time that elapsed.  The first way
Packit 95306a
is to give the difference exactly.  This is the exact delta.
Packit 95306a
Packit 95306a
An exact delta is always described in terms of hours, minutes, and seconds.
Packit 95306a
Packit 95306a
The problem with this is that we don't think in terms of exact deltas.
Packit 95306a
We think in terms which cannot be expressed exactly.
Packit 95306a
Packit 95306a
For example, most people would look at those two dates and think:
Packit 95306a
Packit 95306a
   Percieved: 1 month, 2 days, 1 hour
Packit 95306a
Packit 95306a
But the two dates:
Packit 95306a
Packit 95306a
   Feb 3 2016 11:00:00
Packit 95306a
   Mar 5 2016 12:00:00
Packit 95306a
Packit 95306a
   Elapsed time: 745 hours
Packit 95306a
   Perceived: 1 month, 2 days, 1 hour
Packit 95306a
Packit 95306a
Some fields in a delta do not have an exact length.  A year is usually
Packit 95306a
365 days long, but sometimes it is 366.  A month might be 28, 29, 30,
Packit 95306a
or 31 days long.
Packit 95306a
Packit 95306a
Perhaps the most unexpected difficulty is that days are not of
Packit 95306a
constant length.  Most people would define a day as 24 hours, but when
Packit 95306a
you take daylight saving time into account that definition produces
Packit 95306a
unexpected results.  The following calculation illustrates this:
Packit 95306a
Packit 95306a
   Nov 5, 2011 02:30 EDT
Packit 95306a
   + 24 hour
Packit 95306a
Packit 95306a
   Result: Nov 6, 2011 01:30 EST
Packit 95306a
Packit 95306a
This immediately causes most people to redefine a day as the amount of time
Packit 95306a
between the same wallclock time.  For example, the amount of time between noon
Packit 95306a
one day and noon the next (regardless of daylight saving time changes).
Packit 95306a
Packit 95306a
This definition doesn't work either.  For example:
Packit 95306a
Packit 95306a
   Mar 12, 2011 02:30 EST
Packit 95306a
   + 1 day (same time next day)
Packit 95306a
Packit 95306a
   Result: Mar 13 02:30 EST
Packit 95306a
Packit 95306a
But that date does not exist!  Neither does:
Packit 95306a
Packit 95306a
   Result: Mar 13 02:30 EDT
Packit 95306a
Packit 95306a
An alternate calculation could be:
Packit 95306a
Packit 95306a
   Nov 5, 2011 01:30 EDT
Packit 95306a
   + 1 day (same time next day)
Packit 95306a
Packit 95306a
   Result: Nov 6, 01:30 EDT
Packit 95306a
   Result: Nov 6, 01:30 EST
Packit 95306a
Packit 95306a
Both of those results exist.  Which result did you mean?  The first
Packit 95306a
one is probably correct (since it is 24 hours later), but an hour
Packit 95306a
later, you will have the same clock time again.
Packit 95306a
Packit 95306a
So, the same time next day definition doesn't work at all for some
Packit 95306a
dates (during a 'spring forward' type daylight saving time transition)
Packit 95306a
and is ambiguous for others (during a 'fall back' type daylight saving
Packit 95306a
time transition).
Packit 95306a
Packit 95306a
Calculations involving exact deltas are unambiguous in all cases.
Packit 95306a
Packit 95306a
A second class of delta is called a semi-exact delta, and these add
Packit 95306a
days (and weeks) to the delta, and treats days as a "same time next day"
Packit 95306a
at all times except the two cases where the resulting date falls in the
Packit 95306a
period where a daylight saving time transition is occuring.  Then it
Packit 95306a
falls back to the 24 hour definition.
Packit 95306a
Packit 95306a
A final class of delta is an approximate delta which includes all of
Packit 95306a
the fields (years and months).  This allows Date::Manip to handle
Packit 95306a
deltas in a way that is consistent with how most people perceive the
Packit 95306a
elapsed time.  It should be noted that there is some uncertaintly
Packit 95306a
there as not everyone's definition of how a delta is perceived is the
Packit 95306a
same, but in general, they should be closer to what most people think
Packit 95306a
of.
Packit 95306a
Packit 95306a
=head1 TYPES OF CALCULATIONS
Packit 95306a
Packit 95306a
This document describes the different types of calculations.
Packit 95306a
Calculations involve two types of Date::Manip objects: dates and
Packit 95306a
deltas. These are described in the L<Date::Manip::Date> and
Packit 95306a
L<Date::Manip::Delta> manuals respectively.
Packit 95306a
Packit 95306a
Two objects (two dates, two deltas, or one of each) are used.  In all
Packit 95306a
cases, if a second object is not passed in, undef is returned.
Packit 95306a
Packit 95306a
There are 3 types of calculations:
Packit 95306a
Packit 95306a
=over 4
Packit 95306a
Packit 95306a
=item B<Date/Date calculations>
Packit 95306a
Packit 95306a
A calculation involving 2 dates is used to determine the amount of time (the
Packit 95306a
delta) between them.
Packit 95306a
Packit 95306a
   $delta  = $date1->calc($date2 [,$subtract] [,$mode]);
Packit 95306a
Packit 95306a
Two dates can be worked with and a delta will be produced which is
Packit 95306a
the amount of time between the two dates.
Packit 95306a
Packit 95306a
C<$date1> and C<$date2> are L<Date::Manip::Date> objects with valid dates.
Packit 95306a
The L<Date::Manip::Delta> object returned is the amount of time between
Packit 95306a
them. If C<$subtract> is not passed in (or is 0), the delta produced
Packit 95306a
is:
Packit 95306a
Packit 95306a
   DELTA = DATE2 - DATE1
Packit 95306a
Packit 95306a
If C<$subtract> is non-zero, the delta produced is:
Packit 95306a
Packit 95306a
   DELTA = DATE1 - DATE2
Packit 95306a
Packit 95306a
The C<$subtract> argument has special importance when doing approximate
Packit 95306a
calculations, and this is described below.
Packit 95306a
Packit 95306a
If either date is invalid, a delta object will be returned which
Packit 95306a
has an error associated with it.
Packit 95306a
Packit 95306a
The C<$mode> argument describes the type of delta that is produced and
Packit 95306a
is described below in L</"MODE">.
Packit 95306a
Packit 95306a
=item B<Date/Delta calculations>
Packit 95306a
Packit 95306a
Date/delta calculations can be performed using either a L<Date::Manip::Date>
Packit 95306a
or L<Date::Manip::Delta> object as the primary object:
Packit 95306a
Packit 95306a
   $date2  = $date1->calc($delta [,$subtract]);
Packit 95306a
   $date2  = $delta->calc($date1 [,$subtract]);
Packit 95306a
Packit 95306a
A date and delta can be combined to yield a date that is the
Packit 95306a
given amount of time before or after it.
Packit 95306a
Packit 95306a
C<$date1> and C<$delta> are L<Date::Manip::Date> and L<Date::Manip::Delta>
Packit 95306a
objects respectively. A new L<Date::Manip::Date> object is produced.
Packit 95306a
If either C<$date1> or C<$delta> are invalid, the new date object will have
Packit 95306a
an error associated with it.
Packit 95306a
Packit 95306a
Both of the calls above perform the same function and produce exactly the
Packit 95306a
same results.
Packit 95306a
Packit 95306a
If C<$subtract> is not passed in, or is 0, the resulting date is
Packit 95306a
formed as:
Packit 95306a
Packit 95306a
   DATE2 = DATE1 + DELTA
Packit 95306a
Packit 95306a
If C<$subtract> is non-zero, the resulting date is:
Packit 95306a
Packit 95306a
   DATE2 = DATE1 - DELTA
Packit 95306a
Packit 95306a
The C<$subtract> argument has special importance when doing approximate
Packit 95306a
calculations, and this is described below in L</"SUBTRACTION">.
Packit 95306a
Packit 95306a
=item B<Delta/Delta calculations>
Packit 95306a
Packit 95306a
Delta/delta calculations can be performed to add two amounts of time
Packit 95306a
together, or subtract them.
Packit 95306a
Packit 95306a
   $delta3 = $delta1->calc($delta2 [,$subtract] [,$no_normalize]);
Packit 95306a
Packit 95306a
If C<$subtract> is not passed in, or is 0, the resulting delta formed
Packit 95306a
is:
Packit 95306a
Packit 95306a
   DELTA3 = DELTA1 + DELTA2
Packit 95306a
Packit 95306a
If C<$subtract> is non-zero, then the resulting delta is:
Packit 95306a
Packit 95306a
   DELTA3 = DELTA1 - DELTA2
Packit 95306a
Packit 95306a
C<$delta1> and C<$delta2> are valid L<Date::Manip::Delta> objects, and a new
Packit 95306a
L<Date::Manip::Delta> object is produced.
Packit 95306a
Packit 95306a
C<$no_normalize> can be the string 'nonormalize' or a non-zero value (in
Packit 95306a
which case $subtract MUST be entered, even if it is 0).
Packit 95306a
Packit 95306a
=back
Packit 95306a
Packit 95306a
=head1 MODE
Packit 95306a
Packit 95306a
Date::Manip calculations can be divided into two different categories:
Packit 95306a
business and non-business; and within those are three sub-categories:
Packit 95306a
exact, semi-exact, and approximate.
Packit 95306a
Packit 95306a
=over 4
Packit 95306a
Packit 95306a
=item B<Business and non-business calculations>
Packit 95306a
Packit 95306a
A business calculation is one where the length of the day is
Packit 95306a
determined by the length of the work day, and only business days
Packit 95306a
(i.e. days in which business is conducted) count. Holidays and
Packit 95306a
weekends are omitted (though there is some flexibility in defining
Packit 95306a
what exactly constitutes the work week as described in the
Packit 95306a
L<Date::Manip::Config> manual). This is described in more detail below
Packit 95306a
in L</"BUSINESS MODE CONSIDERATIONS">.
Packit 95306a
Packit 95306a
A non-business mode calculation is the normal type of calculation
Packit 95306a
where no days are ignored, and all days are full length.
Packit 95306a
Packit 95306a
=item B<Exact, semi-exact, and approximate calculations>
Packit 95306a
Packit 95306a
An exact calculation is one in which the delta used (or produced) is
Packit 95306a
an exact delta.  An exact delta is described in more detail in the
Packit 95306a
L<Date::Manip::Delta> manual, but the short explanation is that it is
Packit 95306a
a delta which only involves fields of an exactly known length (hours,
Packit 95306a
minutes, and seconds).  Business deltas also include days in the exact
Packit 95306a
part.  The value of all other fields in the delta will be zero.
Packit 95306a
Packit 95306a
A semi-exact calculation is one in which the deltas used (or produced)
Packit 95306a
is a semi-exact delta.  This is also described in the
Packit 95306a
L<Date::Manip::Delta> manual, but the short explanation is that it
Packit 95306a
includes days and weeks (for standard calculations) or weeks (for
Packit 95306a
business calculations) in addition to the exact fields.  A semi-exact
Packit 95306a
day is defined as the same clock time on two successive days.  So noon
Packit 95306a
to noon is 1 day (even though it may not be exactly 24 hours due to a
Packit 95306a
daylight saving time transition).  A week is defined as 7 days. This
Packit 95306a
is described in more detail below.
Packit 95306a
Packit 95306a
An approximate calculation is one in which the deltas used (or
Packit 95306a
produced) are approximate, and may include any of the fields.
Packit 95306a
Packit 95306a
=back
Packit 95306a
Packit 95306a
In date-delta and delta-delta calculations, the mode of the
Packit 95306a
calculation will be determined automatically by the delta. In the case
Packit 95306a
of date-date calculations, the mode is supplied as an argument.
Packit 95306a
Packit 95306a
=over 4
Packit 95306a
Packit 95306a
=item B<Mode in date-date calculations>
Packit 95306a
Packit 95306a
When doing a date-date calculation, the following call is used:
Packit 95306a
Packit 95306a
   $delta = $date1->calc($date2 [,$subtract] [,$mode]);
Packit 95306a
Packit 95306a
C<$mode> defaults to "exact". The delta produced will be be either a
Packit 95306a
business or non-business delta; exact, semi-exact, or approximate, as
Packit 95306a
specified by C<$mode>.
Packit 95306a
Packit 95306a
Currently, the possible values that $mode can have are:
Packit 95306a
Packit 95306a
   exact    : an exact, non-business calculation
Packit 95306a
   semi     : a semi-exact, non-business calculation
Packit 95306a
   approx   : an approximate, non-business calculation
Packit 95306a
Packit 95306a
   business : an exact, business calculation
Packit 95306a
   bsemi    : a semi-exact, business calculation
Packit 95306a
   bapprox  : an approximate, business calculation
Packit 95306a
Packit 95306a
=item B<Mode in date-delta calculations>
Packit 95306a
Packit 95306a
When doing calculations of a date and a delta:
Packit 95306a
Packit 95306a
   $date2 = $date1->calc($delta [,$subtract]);
Packit 95306a
   $date2 = $delta->calc($date1 [,$subtract]);
Packit 95306a
Packit 95306a
the mode is not passed in. It is determined exclusively by the
Packit 95306a
delta. If C<$delta> is a business delta, A business calculation is
Packit 95306a
done. If C<$delta> is a non-business delta, a non-business calculation
Packit 95306a
will be done.
Packit 95306a
Packit 95306a
The C<$delta> will also be classified as exact, semi-exact, or approximate
Packit 95306a
based on which fields are non-zero.
Packit 95306a
Packit 95306a
=item B<Mode in delta-delta calculations>
Packit 95306a
Packit 95306a
When doing calculations with two deltas:
Packit 95306a
Packit 95306a
   $delta3 = $delta1->calc($delta2 [,$subtract]);
Packit 95306a
Packit 95306a
the mode is not passed in. It is determined by the two deltas.
Packit 95306a
Packit 95306a
If both deltas are business mode, or both are non-business mode, a
Packit 95306a
new delta will be produced of the same type.
Packit 95306a
Packit 95306a
It one of the deltas is a business mode and the other is not, the
Packit 95306a
resulting delta will have an error condition since there is no
Packit 95306a
direct correlation between the two types of deltas. Even though
Packit 95306a
it would be easy to add the two together, it would be impossible
Packit 95306a
to come up with a result that is meaningful.
Packit 95306a
Packit 95306a
If both deltas are exact, semi-exact, or approximate, the resulting
Packit 95306a
delta is the same. If one delta is approximate and one is not, then
Packit 95306a
the resulting delta is approximate.  It is NOT treated as an error.
Packit 95306a
Likewise, if one is semi-exact and the other exact, a semi-exact delta
Packit 95306a
is produced.
Packit 95306a
Packit 95306a
=back
Packit 95306a
Packit 95306a
=head1 TIMEZONE CONSIDERATIONS
Packit 95306a
Packit 95306a
=over 4
Packit 95306a
Packit 95306a
=item B<date-date calculations>
Packit 95306a
Packit 95306a
When doing a business calculation, both dates must be in the same time
Packit 95306a
zone or an error is produced.
Packit 95306a
Packit 95306a
For non-business calculations, when calculating the difference between
Packit 95306a
two dates in different time zones, C<$date2> will be converted to the
Packit 95306a
same timezone as C<$date1> and the returned date will be in this
Packit 95306a
timezone.
Packit 95306a
Packit 95306a
=item B<date-delta calculations>
Packit 95306a
Packit 95306a
When adding a delta to a date, the resulting date will be in the same
Packit 95306a
time zone as the original date.
Packit 95306a
Packit 95306a
=item B<delta-delta calculations>
Packit 95306a
Packit 95306a
No timezone information applies.
Packit 95306a
Packit 95306a
=back
Packit 95306a
Packit 95306a
It should also be noted that daylight saving time considerations are
Packit 95306a
currently ignored when doing business calculations.  In common usage,
Packit 95306a
daylight saving time changes occurs outside of the business day, so
Packit 95306a
the business day length is constant.  As a result, daylight saving
Packit 95306a
time is ignored.
Packit 95306a
Packit 95306a
=head1 BUSINESS MODE CONSIDERATIONS
Packit 95306a
Packit 95306a
In order to correctly do business mode calculations, a config file
Packit 95306a
should exist which contains the section defining holidays (otherwise,
Packit 95306a
weekends will be ignored, but all other days will be counted as
Packit 95306a
business days). This is documented below, and in the
Packit 95306a
L<Date::Manip::Config> section of the documentation.  Some config
Packit 95306a
variables (namely WorkWeekBeg, WorkWeekEnd, WorkDayBeg, WorkDayEnd,
Packit 95306a
and WorkDay24Hr) defined the length of the work week and work day.
Packit 95306a
Packit 95306a
If the workday is defined as 08:00 to 18:00, a work week consisting of
Packit 95306a
Mon-Sat, and the standard (American) holidays, then from Tuesday at
Packit 95306a
12:00 to the following Monday at 14:00 is 5 days and 2 hours.  If the
Packit 95306a
"end" of the day is reached in a calculation, it automatically
Packit 95306a
switches to the next day.  So, Tuesday at 12:00 plus 6 hours is
Packit 95306a
Wednesday at 08:00 (provided Wed is not a holiday).  Also, a date that
Packit 95306a
is not during a workday automatically becomes the start of the next
Packit 95306a
workday.  So, Sunday 12:00 and Monday at 03:00 both automatically
Packit 95306a
becomes Monday at 08:00 (provided Monday is not a holiday).
Packit 95306a
Packit 95306a
Note that a business week is treated the same as an exact week
Packit 95306a
(i.e. from Tuesday to Tuesday, regardless of holidays).  Because this
Packit 95306a
means that the relationship between days and weeks is NOT unambiguous,
Packit 95306a
when a semi-exact delta is produced from two dates, it will be in
Packit 95306a
terms of d/h/mn/s (i.e. no week field).
Packit 95306a
Packit 95306a
Anyone using business mode is going to notice a few quirks about it
Packit 95306a
which should be explained.  When I designed business mode, I had in
Packit 95306a
mind what a business which promises 1 business day turnaround really
Packit 95306a
means.
Packit 95306a
Packit 95306a
If you do a business calculation (with the workday set to 9:00-17:00),
Packit 95306a
you will get the following:
Packit 95306a
Packit 95306a
   Saturday at noon + 1 business day = Tuesday at 9:00
Packit 95306a
   Saturday at noon - 1 business day = Friday at 9:00
Packit 95306a
Packit 95306a
What does this mean?
Packit 95306a
Packit 95306a
As an example, say I use a business that works 9-5 and they have a
Packit 95306a
drop box so I can drop things off over the weekend and they promise 1
Packit 95306a
business day turnaround.  If I drop something off Friday night,
Packit 95306a
Saturday, or Sunday, it doesn't matter.  They're going to get started
Packit 95306a
on it Monday morning.  It'll be 1 business day to finish the job, so
Packit 95306a
the earliest I can expect it to be done is around 17:00 Monday or 9:00
Packit 95306a
Tuesday morning.  Unfortunately, there is some ambiguity as to what
Packit 95306a
day 17:00 really falls on, similar to the ambiguity that occurs when
Packit 95306a
you ask what day midnight falls on.  Although it's not the only
Packit 95306a
answer, Date::Manip treats midnight as the beginning of a day rather
Packit 95306a
than the end of one.  In the same way, 17:00 is equivalent to 9:00 the
Packit 95306a
next day and any time the date calculations encounter 17:00, it
Packit 95306a
automatically switch to 9:00 the next day.  Although this introduces
Packit 95306a
some quirks, I think this is justified.  I also think that it is the
Packit 95306a
way most people think of it. If I drop something off first thing
Packit 95306a
Monday morning, I would expect to pick it up first thing Tuesday if
Packit 95306a
there is 1 business day turnaround.
Packit 95306a
Packit 95306a
Equivalently, if I want a job to be finished on Saturday (despite the fact
Packit 95306a
that I cannot pick it up since the business is closed), I have to drop it
Packit 95306a
off no later than Friday at 9:00.  That gives them a full business day to
Packit 95306a
finish it off.  Of course, I could just as easily drop it off at 17:00
Packit 95306a
Thursday, or any time between then and 9:00 Friday.  Again, it's a matter
Packit 95306a
of treating 17:00 as ambiguous.
Packit 95306a
Packit 95306a
So Saturday + 1 business day = Tuesday at 9:00 (which means anything
Packit 95306a
from Monday 17:00 to Tuesday 9:00), but Monday at 9:01 + 1 business
Packit 95306a
day = Tuesday at 9:01 which is unambiguous.
Packit 95306a
Packit 95306a
It should be noted that when adding years, months, and weeks,
Packit 95306a
the business day is ignored.  Once they've been added, the resulting
Packit 95306a
date is forced to be a business time (i.e. it moves to the start of
Packit 95306a
the next business day if it wasn't one already) before proceeding with
Packit 95306a
the days, hours, minutes, and seconds part.
Packit 95306a
Packit 95306a
=head1 EXACT, SEMI-EXACT, AND APPROXIMATE DATE/DELTA CALCULATIONS
Packit 95306a
Packit 95306a
This section contains more details about exactly how exact, semi-exact,
Packit 95306a
and approximate calculations are performed for date/delta calculations.
Packit 95306a
Packit 95306a
All calculations make use of some exact quantities, including:
Packit 95306a
Packit 95306a
  1 year   = 12 months
Packit 95306a
  1 week   = 7 days
Packit 95306a
  1 hour   = 60 minutes
Packit 95306a
  1 minute = 60 seconds
Packit 95306a
Packit 95306a
This leaves two relationships which are not exact:
Packit 95306a
Packit 95306a
  1 month  = ? days
Packit 95306a
  1 day    = ? hours
Packit 95306a
Packit 95306a
For non-business calculations, a day is usually 24 hours long. Due to
Packit 95306a
daylight saving time transitions which might make a day be 23 or 25 hours
Packit 95306a
long (or in some cases, some other length), the relation is not exact.
Packit 95306a
Whenever possible, a day is actually measured as the same time on
Packit 95306a
two days (i.e. Tuesday at noon to Wednesday at noon) even if that
Packit 95306a
period is not precisely 24 hours.  For business calculations, a days
Packit 95306a
length is determined by the length of the work day and is known
Packit 95306a
exactly.
Packit 95306a
Packit 95306a
Exact calculations involve ONLY quantities of time with a known length,
Packit 95306a
so there is no ambiguity in them.
Packit 95306a
Packit 95306a
Approximate and semi-exact calculations involve variable length fields,
Packit 95306a
and so they must be treated specially.
Packit 95306a
Packit 95306a
In order to do an approximate or semi-exact calculation, the delta is
Packit 95306a
added to a date in pieces, where the fields in each piece have an
Packit 95306a
exact and known relationship.
Packit 95306a
Packit 95306a
For a non-business calculation, a calculation occurs in the following
Packit 95306a
steps:
Packit 95306a
Packit 95306a
  year/month fields added
Packit 95306a
  week/day fields added
Packit 95306a
  hour/minute/second fields added
Packit 95306a
Packit 95306a
For a business calculation, the steps are:
Packit 95306a
Packit 95306a
  year/month fields added
Packit 95306a
  week field added
Packit 95306a
  day field added
Packit 95306a
  hour/minute/second fields added
Packit 95306a
Packit 95306a
After each step, a valid date must be present, or it will be adjusted
Packit 95306a
before proceeding to the next step.  Note however that for business
Packit 95306a
calculations, the first step must produce a valid date, but not
Packit 95306a
necessarily a business date.  The second step will produce a valid
Packit 95306a
business date.
Packit 95306a
Packit 95306a
A series of examples will illustrate this.
Packit 95306a
Packit 95306a
=over 4
Packit 95306a
Packit 95306a
=item B
Packit 95306a
Packit 95306a
   date  = Mar 31 2001 at 12:00:00
Packit 95306a
   delta = 1 year, 1 month, 1 day, 1 hour
Packit 95306a
Packit 95306a
First, the year/month fields are added without modifying any other field.
Packit 95306a
This would produce:
Packit 95306a
Packit 95306a
   Apr 31, 2002 at 12:00
Packit 95306a
Packit 95306a
which is not valid.  Any time the year/month fields produce a day past
Packit 95306a
the end of the month, the result is 'truncated' to the last day of the
Packit 95306a
month, so this produces:
Packit 95306a
Packit 95306a
   Apr 30, 2002 at 12:00
Packit 95306a
Packit 95306a
Next the week/day fields are added producing:
Packit 95306a
Packit 95306a
   May 1, 2002 at 12:00
Packit 95306a
Packit 95306a
and finally, the exact fields (hour/minute/second) are added to produce:
Packit 95306a
Packit 95306a
   May 1, 2002 at 13:00
Packit 95306a
Packit 95306a
=item B
Packit 95306a
Packit 95306a
Assuming a normal Monday-Friday work week from 8:00 - 17:00:
Packit 95306a
Packit 95306a
   date  = Wed, Nov 23, 2011 at 12:00
Packit 95306a
   delta = 1 week, 1 day, 1 hour
Packit 95306a
Packit 95306a
First, the week field is added:
Packit 95306a
Packit 95306a
   Wed, Nov 30, 2011 at 12:00
Packit 95306a
Packit 95306a
Then the day field is added:
Packit 95306a
Packit 95306a
   Thu, Dec 1, 2011 at 12:00
Packit 95306a
Packit 95306a
Then the exact fields are added:
Packit 95306a
Packit 95306a
   Thu, Dec 1, 2011 at 13:00
Packit 95306a
Packit 95306a
=item B
Packit 95306a
Packit 95306a
In America, Jul 4 is a holiday, so Mon, Jul 4, 2011 is not a work day.
Packit 95306a
Packit 95306a
   date  = Mon, Jun 27, 2011 at 12:00
Packit 95306a
   delta = 1 week, 1 day, 1 hour
Packit 95306a
Packit 95306a
First, the week field is added:
Packit 95306a
Packit 95306a
   Mon, Jul 4, 2011 at 12:00
Packit 95306a
Packit 95306a
Since that is not a work day, it immediately becomes:
Packit 95306a
Packit 95306a
   Tue, Jul 5, 2011 at 8:00
Packit 95306a
Packit 95306a
Then the day field is added:
Packit 95306a
Packit 95306a
   Wed, Jul 6, 2011 at 8:00
Packit 95306a
Packit 95306a
and finally the remaining fields:
Packit 95306a
Packit 95306a
   Wed, Jul 6, 2011 at 9:00
Packit 95306a
Packit 95306a
=item B<Calculation where daylight savings time impacts it (fall example)>
Packit 95306a
Packit 95306a
In the America/New_York timezone (Eastern time), on November 6, 2011,
Packit 95306a
the following time change occurred:
Packit 95306a
Packit 95306a
   2011-11-06 02:00  EDT  => 2011-11-06 01:00  EST
Packit 95306a
Packit 95306a
Three simple calculations illustrate how this is handled:
Packit 95306a
Packit 95306a
   date  = 2011-11-05 02:30 EDT
Packit 95306a
   delta = 1 day
Packit 95306a
Packit 95306a
Adding the day produces:
Packit 95306a
Packit 95306a
   2011-11-06 02:30  EDT
Packit 95306a
Packit 95306a
which is valid, so that is the result.
Packit 95306a
Packit 95306a
Similarly:
Packit 95306a
Packit 95306a
   date  = 2011-11-07 02:30 EST
Packit 95306a
   delta = -1 day
Packit 95306a
Packit 95306a
produces:
Packit 95306a
Packit 95306a
   2011-11-06 02:30 EST
Packit 95306a
Packit 95306a
which is valid.
Packit 95306a
Packit 95306a
Finally:
Packit 95306a
Packit 95306a
   date  = 2011-11-05 02:30 EDT
Packit 95306a
   delta = 2 days
Packit 95306a
Packit 95306a
produces:
Packit 95306a
Packit 95306a
   2011-11-07 02:30  EST
Packit 95306a
Packit 95306a
The calculation will preserve the savings time where possible so the
Packit 95306a
resulting day will have the same offset from UTC.  If that is not
Packit 95306a
possible, but the resulting day is valid in the other offset, that
Packit 95306a
will be used instead.
Packit 95306a
Packit 95306a
=item B<Calculation where daylight savings time impacts it (spring example)>
Packit 95306a
Packit 95306a
In the America/New_York timezone (Eastern time), on March 13,
Packit 95306a
the following time change occurred:
Packit 95306a
Packit 95306a
   2011-03-13 02:00  EST  => 2011-03-13 03:00  EDT
Packit 95306a
Packit 95306a
In this case, a calculation may produce an invalid date.
Packit 95306a
Packit 95306a
   date  = 2011-03-12 02:30 EST
Packit 95306a
   delta = 1 day
Packit 95306a
Packit 95306a
produces:
Packit 95306a
Packit 95306a
   2011-03-13 02:30 EST
Packit 95306a
Packit 95306a
This is not valid.  Neither is:
Packit 95306a
Packit 95306a
   2011-03-13 02:30 EDT
Packit 95306a
Packit 95306a
In this case, the calculation will be redone converting days to 24-hour
Packit 95306a
periods, so the calculation becomes:
Packit 95306a
Packit 95306a
   date  = 2011-03-12 02:30 EST
Packit 95306a
   delta = 24 hours
Packit 95306a
Packit 95306a
which will produce a valid date:
Packit 95306a
Packit 95306a
   2011-03-13 03:30 EDT
Packit 95306a
Packit 95306a
=back
Packit 95306a
Packit 95306a
=head1 EXACT, SEMI-EXACT, AND APPROXIMATE DATE/DATE CALCULATIONS
Packit 95306a
Packit 95306a
This section contains more details about exactly how exact, semi-exact,
Packit 95306a
and approximate calculations are performed for date/date calculations.
Packit 95306a
Packit 95306a
When calculating the delta between two dates, the delta may take
Packit 95306a
different forms depending on the mode passed in. An exact calculation
Packit 95306a
will produce a delta which included only exact fields.  A semi-exact calculation
Packit 95306a
may produce a semi-exact delta, and an approximate calculation may produce
Packit 95306a
an approximate delta.  Note that if the two dates are close enough together,
Packit 95306a
an exact delta will be produced (even if the mode is semi-exact or approximate),
Packit 95306a
or it may produce a semi-exact delta in approximate mode.
Packit 95306a
Packit 95306a
For example, the two dates "Mar 12 1995 12:00" and "Apr 13 1995 12:00"
Packit 95306a
would have an exact delta of "744 hours", and a semi-exact delta of
Packit 95306a
"31 days".  It would have an approximate delta of "1 month 1 day".
Packit 95306a
Packit 95306a
Two dates, "Mar 31 12:00" and "Apr 30 12:00" would have deltas "720
Packit 95306a
hours" (exact), "30 days" (semi-exact) or "1 month" (approximate).
Packit 95306a
Packit 95306a
Approximate mode is a more human way of looking at things (you'd say 1
Packit 95306a
month and 2 days more often then 33 days), but it is less meaningful
Packit 95306a
in terms of absolute time.
Packit 95306a
Packit 95306a
One thing to remember is that an exact delta is exactly the amount of
Packit 95306a
time that has passed, including all effects of daylight saving
Packit 95306a
time. Semi-exact and approximate deltas usually ignore the affects of
Packit 95306a
daylight saving time.
Packit 95306a
Packit 95306a
=head1 SUBTRACTION
Packit 95306a
Packit 95306a
In exact and semi-exact calculations, and in delta-delta calculations,
Packit 95306a
the the C<$subtract> argument is easy to understand.  When working
Packit 95306a
with an approximate delta however (either when adding an approximate
Packit 95306a
delta to a date, or when taking two dates to get an approximate
Packit 95306a
delta), there is a degree of uncertainty in how the calculation is
Packit 95306a
done, and the $subtract argument is used to specify exactly how the
Packit 95306a
approximate delta is to be use. An example illustrates this quite
Packit 95306a
well.
Packit 95306a
Packit 95306a
If you take the date Jan 4, 2000 and subtract a delta of "1 month 1
Packit 95306a
week" from it, you end up with Nov 27, 1999 (Jan 4, 2000 minus 1 month
Packit 95306a
is Dec 4, 1999; minus 1 week is Nov 27, 1999). But Nov 27, 1999 plus a
Packit 95306a
delta of "1 month 1 week" is Jan 3, 2000 (Nov 27, 1999 plus 1 month is
Packit 95306a
Dec 27, 1999; plus 1 week is Jan 3, 2000).
Packit 95306a
Packit 95306a
In other words the approximate delta (but NOT the exact or semi-exact
Packit 95306a
delta) is different depending on whether you move from earlier date to
Packit 95306a
the later date, or vice versa. And depending on what you are
Packit 95306a
calculating, both are useful.
Packit 95306a
Packit 95306a
In order to resolve this, the C<$subtract> argument can take on the values
Packit 95306a
0, 1, or 2, and have different meanings.
Packit 95306a
Packit 95306a
=over 4
Packit 95306a
Packit 95306a
=item B<$subtract in approximate date-date calculations>
Packit 95306a
Packit 95306a
In the call:
Packit 95306a
Packit 95306a
   $delta = $date1->calc($date2,$subtract,"approx");
Packit 95306a
Packit 95306a
if C<$subtract> is 0, the resulting delta can be added to C<$date1> to get
Packit 95306a
C<$date2>. Obviously C<$delta> may still be negative (if C<$date2> comes before
Packit 95306a
C<$date1>).
Packit 95306a
Packit 95306a
If C<$subtract> is 1, the resulting delta can be subtracted from C<$date1>
Packit 95306a
to get C<$date2> (the deltas from these two are identical except for having
Packit 95306a
an opposite sign).
Packit 95306a
Packit 95306a
If C<$subtract> is 2, the resulting delta can be added to C<$date2> to get
Packit 95306a
C<$date1>. In other words, the following are identical:
Packit 95306a
Packit 95306a
   $delta = $date1->calc($date2,2,"approx");
Packit 95306a
   $delta = $date2->calc($date1,"approx");
Packit 95306a
Packit 95306a
=item B<$subtract in approximate date-delta calculations>
Packit 95306a
Packit 95306a
In the call:
Packit 95306a
Packit 95306a
   $date2 = $date1->calc($delta,$subtract);
Packit 95306a
Packit 95306a
If C<$subtract> is 0, the resulting date is determined by adding C<$delta> to
Packit 95306a
C<$date1>.
Packit 95306a
Packit 95306a
If C<$subtract> is 1, the resulting date is determined by subtracting C<$delta>
Packit 95306a
from C<$date1>.
Packit 95306a
Packit 95306a
If C<$subtract> is 2, the resulting date is the date which C<$delta>
Packit 95306a
can be added to to get C<$date1>.
Packit 95306a
Packit 95306a
For business mode calculations, C<$date1> will first be adjusted to be a valid
Packit 95306a
work day (if it isn't already), so this may lead to non-intuitive results.
Packit 95306a
Packit 95306a
In some cases, it is impossible to do a calculation with C<$subtract> = 2.
Packit 95306a
As an example, if the date is "Dec 31" and the delta is "1 month", there
Packit 95306a
is no date which you can add "1 month" to to get "Dec 31".  When this occurs,
Packit 95306a
the date returned has an error flag.
Packit 95306a
Packit 95306a
=back
Packit 95306a
Packit 95306a
=head1 APPROXIMATE DATE/DATE CALCULATION
Packit 95306a
Packit 95306a
There are two different ways to look at the approximate delta between
Packit 95306a
two dates.
Packit 95306a
Packit 95306a
In Date::Manip 5.xx, the approximate delta between the two dates:
Packit 95306a
Packit 95306a
   Jan 10 1996 noon
Packit 95306a
   Jan  7 1998 noon
Packit 95306a
Packit 95306a
was 1:11:4:0:0:0:0 (or 1 year, 11 months, 4 weeks).  In calculating
Packit 95306a
this, the first date was adjusted as far as it could go towards the
Packit 95306a
second date without going past it with each unit starting with the
Packit 95306a
years and ending with the seconds.
Packit 95306a
Packit 95306a
This gave a strictly positive or negative delta, but it isn't
Packit 95306a
actually how most people would think of the delta.
Packit 95306a
Packit 95306a
As of Date::Manip 6.0, the delta is 2:0:0:-3:0:0:0 (or 2 years minus
Packit 95306a
3 days). Although this leads to mixed-sign deltas, it is actually how
Packit 95306a
more people would think about the delta. It has the additional
Packit 95306a
advantage of being easier to calculate.
Packit 95306a
Packit 95306a
For non-business mode calculations, the year/month part of the
Packit 95306a
approximate delta will move a date from the year/month of the first
Packit 95306a
date into the year/month of the second date. The remainder of the
Packit 95306a
delta will adjust the days/hours/minutes/seconds as appropriate.
Packit 95306a
Packit 95306a
For approximate business mode calculations, the year, date, and week
Packit 95306a
parts will be done approximately, and the remainder will be done
Packit 95306a
exactly.
Packit 95306a
Packit 95306a
=head1 KNOWN BUGS
Packit 95306a
Packit 95306a
None known.
Packit 95306a
Packit 95306a
=head1 BUGS AND QUESTIONS
Packit 95306a
Packit 95306a
Please refer to the L<Date::Manip::Problems> documentation for
Packit 95306a
information on submitting bug reports or questions to the author.
Packit 95306a
Packit 95306a
=head1 SEE ALSO
Packit 95306a
Packit 95306a
L<Date::Manip>        - main module documentation
Packit 95306a
Packit 95306a
=head1 LICENSE
Packit 95306a
Packit 95306a
This script is free software; you can redistribute it and/or
Packit 95306a
modify it under the same terms as Perl itself.
Packit 95306a
Packit 95306a
=head1 AUTHOR
Packit 95306a
Packit 95306a
Sullivan Beck (sbeck@cpan.org)
Packit 95306a
Packit 95306a
=cut