Last active
December 11, 2015 15:38
-
-
Save masak/4621729 to your computer and use it in GitHub Desktop.
DateTime.delta implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use MONKEY_TYPING; | |
enum TimeUnit < | |
second seconds minute minutes hour hours | |
day days week weeks month months year years | |
>; | |
augment class DateTime { | |
method delta($amount, TimeUnit $unit) { | |
my ($hour, $minute) = $!hour, $!minute; | |
my $date; | |
given $unit { | |
when second | seconds { | |
return DateTime.new(self.Instant + $amount); | |
} | |
when minute | minutes { $minute += $amount; proceed } | |
$hour += floor($minute / 60); | |
$minute %= 60; | |
when hour | hours { $hour += $amount; proceed } | |
my $day-delta += floor($hour / 24); | |
$hour %= 24; | |
when day | days { $day-delta += $amount; proceed } | |
when week | weeks { $day-delta += 7 * $amount; proceed } | |
when month | months { | |
my ($month, $year) = $!month, $!year; | |
$month += $amount; | |
$year += floor(($month - 1) / 12); | |
$month = ($month - 1) % 12 + 1; | |
$date = Date.new(:$year, :$month, :$!day); | |
succeed; | |
} | |
when year | years { | |
my $year = $!year + $amount; | |
$date = Date.new(:$year, :$!month, :$!day); | |
succeed; | |
} | |
my $daycount = Date.new(self).daycount; | |
$daycount += $day-delta; | |
$date = Date.new-from-daycount($daycount); | |
} | |
my $second = $!second; | |
if $second > 59 && $date ne any(tai-utc::leap-second-dates) { | |
$second -= 60; | |
$minute++; | |
if $minute > 59 { | |
$minute -= 60; | |
$hour++; | |
if $hour > 23 { | |
$hour -= 24; | |
$date++; | |
} | |
} | |
} | |
self.new(:$date, :$hour, :$minute, :$second); | |
} | |
} | |
use Test; | |
is DateTime.new('2013-12-23T12:34:36Z').delta(1, second), | |
DateTime.new('2013-12-23T12:34:37Z'), | |
'adding 1 second'; | |
is DateTime.new('2013-12-23T12:34:36Z').delta(10, seconds), | |
DateTime.new('2013-12-23T12:34:46Z'), | |
'adding 10 seconds'; | |
is DateTime.new('2013-12-23T12:34:56Z').delta(14, seconds), | |
DateTime.new('2013-12-23T12:35:10Z'), | |
'adding 14 seconds, overflowing to minutes'; | |
is DateTime.new('2013-12-23T12:59:56Z').delta(74, seconds), | |
DateTime.new('2013-12-23T13:01:10Z'), | |
'adding 74 seconds, overflowing to hours'; | |
is DateTime.new('2013-12-23T23:59:59Z').delta(1, second), | |
DateTime.new('2013-12-24T00:00:00Z'), | |
'adding 1 second, overflowing to days'; | |
is DateTime.new('2013-12-31T23:59:59Z').delta(1, second), | |
DateTime.new('2014-01-01T00:00:00Z'), | |
'adding 1 second, overflowing to years'; | |
is DateTime.new('2012-06-30T23:59:59Z').delta(1, second), | |
DateTime.new('2012-06-30T23:59:60Z'), | |
'delting to a leap second'; | |
is DateTime.new('2008-12-31T23:59:60Z').delta(1, second), | |
DateTime.new('2009-01-01T00:00:00Z'), | |
'delting from a leap second'; | |
is DateTime.new('2013-12-23T12:34:36Z').delta(1, minute), | |
DateTime.new('2013-12-23T12:35:36Z'), | |
'adding 1 minute'; | |
is DateTime.new('2013-12-23T12:34:36Z').delta(10, minutes), | |
DateTime.new('2013-12-23T12:44:36Z'), | |
'adding 10 minutes'; | |
is DateTime.new('2013-12-23T12:56:34Z').delta(14, minutes), | |
DateTime.new('2013-12-23T13:10:34Z'), | |
'adding 14 minutes, overflowing to hours'; | |
is DateTime.new('2013-12-23T12:34:36Z').delta(1, hour), | |
DateTime.new('2013-12-23T13:34:36Z'), | |
'adding 1 hour'; | |
is DateTime.new('2013-12-23T12:34:36Z').delta(10, hours), | |
DateTime.new('2013-12-23T22:34:36Z'), | |
'adding 10 hours'; | |
is DateTime.new('2013-12-23T12:56:34Z').delta(14, hours), | |
DateTime.new('2013-12-24T02:56:34Z'), | |
'adding 14 horus, overflowing to days'; | |
is DateTime.new('2013-12-23T12:34:36Z').delta(1, day), | |
DateTime.new('2013-12-24T12:34:36Z'), | |
'adding 1 day'; | |
is DateTime.new('2014-01-31T12:34:36Z').delta(1, day), | |
DateTime.new('2014-02-01T12:34:36Z'), | |
'adding 1 day, overflowing to February'; | |
is DateTime.new('2014-02-28T12:56:34Z').delta(2, days), | |
DateTime.new('2014-03-02T12:56:34Z'), | |
'adding 2 days, overflowing to March'; | |
is DateTime.new('2008-12-31T23:59:60Z').delta(1, day), | |
DateTime.new('2009-01-02T00:00:00Z'), | |
'adding a day to a leap second'; | |
is DateTime.new('1972-12-31T23:59:60Z').delta(1, year), | |
DateTime.new('1973-12-31T23:59:60Z'), | |
'adding a year to a leap second, landing on another leap second'; | |
is DateTime.new('2013-12-23T12:34:36Z').delta(1, week), | |
DateTime.new('2013-12-30T12:34:36Z'), | |
'adding 1 week'; | |
is DateTime.new('2014-01-31T12:34:36Z').delta(1, week), | |
DateTime.new('2014-02-07T12:34:36Z'), | |
'adding 1 week, overflowing to February'; | |
is DateTime.new('2014-02-28T12:56:34Z').delta(2, weeks), | |
DateTime.new('2014-03-14T12:56:34Z'), | |
'adding 2 weeks, overflowing to March'; | |
is DateTime.new('2014-12-30T12:56:34Z').delta(3, weeks), | |
DateTime.new('2015-01-20T12:56:34Z'), | |
'adding 3 weeks, overflowing to years'; | |
is DateTime.new('2013-12-23T12:34:37Z').delta(-1, second), | |
DateTime.new('2013-12-23T12:34:36Z'), | |
'subtracting 1 second'; | |
is DateTime.new('2013-12-23T12:34:46Z').delta(-10, seconds), | |
DateTime.new('2013-12-23T12:34:36Z'), | |
'subtracting 10 seconds'; | |
is DateTime.new('2013-12-23T12:35:10Z').delta(-14, seconds), | |
DateTime.new('2013-12-23T12:34:56Z'), | |
'subtracting 14 seconds, overflowing to minutes'; | |
is DateTime.new('2013-12-23T13:01:10Z').delta(-74, seconds), | |
DateTime.new('2013-12-23T12:59:56Z'), | |
'subtracting 74 seconds, overflowing to hours'; | |
is DateTime.new('2013-12-24T00:00:00Z').delta(-1, second), | |
DateTime.new('2013-12-23T23:59:59Z'), | |
'subtracting 1 second, overflowing to days'; | |
is DateTime.new('2014-01-01T00:00:00Z').delta(-1, second), | |
DateTime.new('2013-12-31T23:59:59Z'), | |
'subtracting 1 second, overflowing to years'; | |
is DateTime.new('2013-12-23T12:35:36Z').delta(-1, minute), | |
DateTime.new('2013-12-23T12:34:36Z'), | |
'subtracting 1 minute'; | |
is DateTime.new('2013-12-23T12:44:36Z').delta(-10, minutes), | |
DateTime.new('2013-12-23T12:34:36Z'), | |
'subtracting 10 minutes'; | |
is DateTime.new('2013-12-23T13:10:34Z').delta(-14, minutes), | |
DateTime.new('2013-12-23T12:56:34Z'), | |
'subtracting 14 minutes, overflowing to hours'; | |
is DateTime.new('2013-12-23T13:34:36Z').delta(-1, hour), | |
DateTime.new('2013-12-23T12:34:36Z'), | |
'subtracting 1 hour'; | |
is DateTime.new('2013-12-23T22:34:36Z').delta(-10, hours), | |
DateTime.new('2013-12-23T12:34:36Z'), | |
'subtracting 10 hours'; | |
is DateTime.new('2013-12-24T02:56:34Z').delta(-14, hours), | |
DateTime.new('2013-12-23T12:56:34Z'), | |
'subtracting 14 horus, overflowing to days'; | |
is DateTime.new('2013-12-24T12:34:36Z').delta(-1, day), | |
DateTime.new('2013-12-23T12:34:36Z'), | |
'subtracting 1 day'; | |
is DateTime.new('2014-02-01T12:34:36Z').delta(-1, day), | |
DateTime.new('2014-01-31T12:34:36Z'), | |
'subtracting 1 day, overflowing to February'; | |
is DateTime.new('2014-03-02T12:56:34Z').delta(-2, days), | |
DateTime.new('2014-02-28T12:56:34Z'), | |
'subtracting 2 days, overflowing to March'; | |
is DateTime.new('2013-12-30T12:34:36Z').delta(-1, week), | |
DateTime.new('2013-12-23T12:34:36Z'), | |
'subtracting 1 week'; | |
is DateTime.new('2014-02-07T12:34:36Z').delta(-1, week), | |
DateTime.new('2014-01-31T12:34:36Z'), | |
'subtracting 1 week, overflowing to February'; | |
is DateTime.new('2014-03-14T12:56:34Z').delta(-2, weeks), | |
DateTime.new('2014-02-28T12:56:34Z'), | |
'subtracting 2 weeks, overflowing to March'; | |
is DateTime.new('2015-01-20T12:56:34Z').delta(-3, weeks), | |
DateTime.new('2014-12-30T12:56:34Z'), | |
'subtracting 3 weeks, overflowing to years'; | |
done; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment