Skip to content

Commit

Permalink
Do not .Int second units in DateTime.later/.earlier
Browse files Browse the repository at this point in the history
Fixes R#1760 #1760
Fixes R#1762 #1762

Unlike other units, there's no ambiguity in fractional seconds,
so don't .Int them to allow user to .later/.earlier a date by
sub-seconds.
  • Loading branch information
zoffixznet committed Apr 22, 2018
1 parent df0b95d commit 656ff77
Showing 1 changed file with 46 additions and 44 deletions.
90 changes: 46 additions & 44 deletions src/core/DateTime.pm6
Expand Up @@ -283,57 +283,59 @@ my class DateTime does Dateish {
die "No time unit supplied" unless @pairs;

my $unit = self!VALID-UNIT(@pairs.AT-POS(0).key);
my $amount = @pairs.AT-POS(0).value.Int;
my $amount = @pairs.AT-POS(0).value;
$amount = -$amount if $earlier;

# work on instant (tai)
if $unit.starts-with('second') {
self.new(self.Instant + $amount, :$!timezone, :&!formatter)
}

# on a leap second and not moving by second
elsif $!second >= 60 {
my $dt := self!clone-without-validating(
:second($!second-1)).later(|($unit => $amount));
$dt.hour == 23 && $dt.minute == 59 && $dt.second >= 59
&& Rakudo::Internals.is-leap-second-date($dt.yyyy-mm-dd)
?? $dt!clone-without-validating(:$!second)
!! $dt
}

# month,year
elsif nqp::atkey($valid-units,$unit) {
my $date :=
Date.new($!year,$!month,$!day).later(|($unit => $amount));
nqp::create(self)!SET-SELF(
nqp::getattr($date,Date,'$!year'),
nqp::getattr($date,Date,'$!month'),
nqp::getattr($date,Date,'$!day'),
$!hour, $!minute, $!second, $!timezone, &!formatter
)
}
# minute,hour,day,week
else {
my int $minute = $!minute;
my int $hour = $!hour;

$minute += $amount if $unit.starts-with('minute');
$hour += floor($minute / 60);
$minute %= 60;
$hour += $amount if $unit.starts-with('hour');

my $day-delta = floor($hour / 24);
$hour %= 24;

$day-delta = $amount if $unit.starts-with('day');
$day-delta = 7 * $amount if $unit.starts-with('week');

my $date := Date.new-from-daycount(self.daycount + $day-delta);
nqp::create(self)!SET-SELF(
nqp::getattr($date,Date,'$!year'),
nqp::getattr($date,Date,'$!month'),
nqp::getattr($date,Date,'$!day'),
$hour, $minute, $!second, $!timezone, &!formatter)
$amount .= Int;
# on a leap second and not moving by second
if $!second >= 60 {
my $dt := self!clone-without-validating(
:second($!second-1)).later(|($unit => $amount));
$dt.hour == 23 && $dt.minute == 59 && $dt.second >= 59
&& Rakudo::Internals.is-leap-second-date($dt.yyyy-mm-dd)
?? $dt!clone-without-validating(:$!second)
!! $dt
}

# month,year
elsif nqp::atkey($valid-units,$unit) {
my $date :=
Date.new($!year,$!month,$!day).later(|($unit => $amount));
nqp::create(self)!SET-SELF(
nqp::getattr($date,Date,'$!year'),
nqp::getattr($date,Date,'$!month'),
nqp::getattr($date,Date,'$!day'),
$!hour, $!minute, $!second, $!timezone, &!formatter
)
}
# minute,hour,day,week
else {
my int $minute = $!minute;
my int $hour = $!hour;

$minute += $amount if $unit.starts-with('minute');
$hour += floor($minute / 60);
$minute %= 60;
$hour += $amount if $unit.starts-with('hour');

my $day-delta = floor($hour / 24);
$hour %= 24;

$day-delta = $amount if $unit.starts-with('day');
$day-delta = 7 * $amount if $unit.starts-with('week');

my $date := Date.new-from-daycount(self.daycount + $day-delta);
nqp::create(self)!SET-SELF(
nqp::getattr($date,Date,'$!year'),
nqp::getattr($date,Date,'$!month'),
nqp::getattr($date,Date,'$!day'),
$hour, $minute, $!second, $!timezone, &!formatter)
}
}
}

Expand Down

0 comments on commit 656ff77

Please sign in to comment.