Re: [interchange] Fix month and year adjustment wrapping issue.

Mike Heins <[email protected]>
Newsgroups gmane.comp.web.interchange.users
Message-ID <CACcURn9Pm-JaMfuafKs7cq9Qw3E5CWL+KVXAD1wizw6gweTc5g@mail.gmail.com>
Part of this was that I don't believe I ever defined "month" as one of the
items in config_to_seconds. It was never intended to be part of an
adjustment in the initial conception -- "m" stood for minutes.


On Mon, Jun 5, 2017 at 5:17 AM, Peter Ajamian <
[email protected]> wrote:

> commit fb8cd269c691a4d15f154826e4d1aa02eef0540a
> Author: Peter Ajamian <[email protected]>
> Date:   Mon Jun 5 20:53:00 2017 +1200
>
>     Fix month and year adjustment wrapping issue.
>
>     Month and year adjustments introduced in 5.7 had a bug where adjusting
> the month
>     to one where the target date doesn't exist caused the day to roll over
> into the
>     following month (ex: May 31st - 1 month became May 1st instead of
> April 30th)
>     and similarily with leapday year adjustments (Feb 29th, 2016 + 1
> year), this was
>     fixed to adjust to the last day of the correct month instead of
> rolling over
>     into the next month.
>
>  UPGRADE          |   13 +++++++++++--
>  lib/Vend/Util.pm |   49 ++++++++++++++++++++++++++++++++++++-------------
>  2 files changed, 47 insertions(+), 15 deletions(-)
> ---
> diff --git a/UPGRADE b/UPGRADE
> index c5f8cc7..2740d87 100644
> --- a/UPGRADE
> +++ b/UPGRADE
> @@ -8,8 +8,17 @@ Briefly summarized, here's what you can expect when
> upgrading from the
>  following versions:
>
>   5.10.x -- A minor bug was fixed in an edge-case usage of the [area] tag
> which
> -         could result in incompatibility if your code relies on the buggy
> -         behaviour.
> +          could result in incompatibility if your code relies on the buggy
> +          behaviour.
> +
> +       -- Month and year adjustments introduced in 5.7 had a bug where
> +          adjusting the month to one where the target date doesn't exist
> caused
> +          the day to roll over into the following month (ex: May 31st - 1
> month
> +          became May 1st instead of April 30th) and similarily with
> leapday
> +          year adjustments (Feb 29th, 2016 + 1 year), this was fixed to
> adjust
> +          to the last day of the correct month instead of rolling over
> into the
> +          next month.  If your code relies on the old behavior please
> update
> +          it.
>
>   5.6.x -- Perl 5.8.8 or newer is now generally required to run
> Interchange.
>            See "Known Issues" below.
> diff --git a/lib/Vend/Util.pm b/lib/Vend/Util.pm
> index 7610e42..866ef3b 100644
> --- a/lib/Vend/Util.pm
> +++ b/lib/Vend/Util.pm
> @@ -2490,6 +2490,27 @@ sub timecard_read {
>  # optional.
>  #
>  sub adjust_time {
> +    # We need special adjustments to take into account end of month or
> leap year
> +    # issues in adjusting the month or year.  This sub will adjust the
> time
> +    # passed in $time as well as kick back a unixtime of the adjusted
> time.
> +    my $perform_adjust = sub {
> +       my ($time, $adjust) = @_;
> +       # Do an adjustment based on year and month first to check for
> issues
> +       # with leap year and end of month variances.  We set isdst to -1 to
> +       # avoid variances due to DST time change.
> +       my @timecheck = @$time;
> +       $timecheck[5] += $adjust->[5];
> +       $timecheck[4] += $adjust->[4];
> +       $timecheck[8] = -1;
> +       my @adjusted = localtime(POSIX::mktime(@timecheck));
> +       # If the day is off we need to add an additional adjustment for it.
> +       $adjust->[3] -= $adjusted[3] if $adjusted[3] < $timecheck[3];
> +       $time->[$_] += $adjust->[$_] for (0..5);
> +       my $unixtime = POSIX::mktime(@$time);
> +       @$time = localtime($unixtime);
> +       return $unixtime;
> +    };
> +
>      my ($adjust, $time, $compensate_dst) = @_;
>      $time ||= time;
>
> @@ -2511,6 +2532,7 @@ sub adjust_time {
>      # or leave the time the same).
>
>      my @times = localtime($time);
> +    my @adjust = (0)x6;
>      my $sign = 1;
>
>      foreach my $amount ($adjust =~ /([+-]?\s*[\d\.]+\s*[a-z]*)/ig) {
> @@ -2527,12 +2549,12 @@ sub adjust_time {
>             $amount *= 7;
>         }
>
> -       if ($unit =~ /^s/) { $times[0] += $amount }
> -       elsif ($unit =~ /^mo/) { $times[4] += $amount } # has to come
> before min
> -       elsif ($unit =~ /^m/) { $times[1] += $amount }
> -       elsif ($unit =~ /^h/) { $times[2] += $amount }
> -       elsif ($unit =~ /^d/) { $times[3] += $amount }
> -       elsif ($unit =~ /^y/) { $times[5] += $amount }
> +       if ($unit =~ /^s/) { $adjust[0] += $amount }
> +       elsif ($unit =~ /^mo/) { $adjust[4] += $amount } # has to come
> before min
> +       elsif ($unit =~ /^m/) { $adjust[1] += $amount }
> +       elsif ($unit =~ /^h/) { $adjust[2] += $amount }
> +       elsif ($unit =~ /^d/) { $adjust[3] += $amount }
> +       elsif ($unit =~ /^y/) { $adjust[5] += $amount }
>
>         else {
>             ::logError("adjust_time(): bad unit: $unit");
> @@ -2546,26 +2568,27 @@ sub adjust_time {
>      my @multip = (0, 60, 60, 24, 0, 12);
>      my $monfrac = 0;
>      foreach my $i (reverse 0..5) {
> -       if ($times[$i] =~ /\./) {
> +       if ($adjust[$i] =~ /\./) {
>             if ($multip[$i]) {
> -               $times[$i-1] += ($times[$i] - int $times[$i]) *
> $multip[$i];
> +               $adjust[$i-1] += ($adjust[$i] - int $adjust[$i]) *
> $multip[$i];
>             }
>
>             elsif ($i == 4) {
>                 # Fractions of a month need some really extra special
> handling.
> -               $monfrac = $times[$i] - int $times[$i];
> +               $monfrac = $adjust[$i] - int $adjust[$i];
>             }
>
> -           $times[$i] = int $times[$i]
> +           $adjust[$i] = int $adjust[$i];
>         }
>      }
>
> -    $time = POSIX::mktime(@times);
> +    $time = $perform_adjust->(\@times, \@adjust);
>
>      # This is how we handle a fraction of a month:
>      if ($monfrac) {
> -       $times[4] += $monfrac > 0 ? 1 : -1;
> -       my $timediff = POSIX::mktime(@times);
> +       @adjust = (0)x6;
> +       $adjust[4] = $monfrac > 0 ? 1 : -1;
> +       my $timediff = $perform_adjust->(\@times, \@adjust);
>         $timediff = int(abs($timediff - $time) * $monfrac);
>         $time += $timediff;
>      }
>
> _______________________________________________
> interchange-cvs mailing list
> [email protected]
> http://www.icdevgroup.org/mailman/listinfo/interchange-cvs
>

_______________________________________________
interchange-users mailing list
[email protected]
http://www.icdevgroup.org/mailman/listinfo/interchange-users
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.