Skip to content
Permalink
Browse files

Streamline creation of Date/DateTime

- bind attributes to objects, as they are immutable
- saves 3 Scalars per Date / 5 Scalars per DateTime
- makes Date.new(y,m,d) about 60% faster
- makes DateTime.new(y,m,d,h,m,s) about 15% faster
  • Loading branch information...
lizmat committed Jan 4, 2019
1 parent f2ed3db commit 9f28a4235734af626b555a4c64a63388f6ca70a2
Showing with 45 additions and 24 deletions.
  1. +9 −3 src/core/Date.pm6
  2. +21 −11 src/core/DateTime.pm6
  3. +15 −10 src/core/Dateish.pm6
@@ -21,9 +21,15 @@ my class Date does Dateish {
!! X::DateTime::InvalidDeltaUnit.new(:$unit).throw
}

method !SET-SELF(
$!year,$!month,$!day,&!formatter,$!daycount = Int
--> Date:D) { self }
method !SET-SELF(\year,\month,\day,\formatter,$daycount? --> Date:D) {
nqp::bind($!year, year); # R#2581
nqp::bind($!month, month);
nqp::bind($!day, day);
nqp::bind(&!formatter, formatter);
nqp::bind($!daycount,
nqp::isconcrete($daycount) ?? $daycount !! nqp::null);
self
}

proto method new(|) {*}
multi method new(Date:
@@ -1,8 +1,8 @@
my class DateTime does Dateish {
has int $.hour;
has int $.minute;
has Int $.hour;
has Int $.minute;
has $.second;
has int $.timezone; # UTC
has Int $.timezone; # UTC
# Not an optimization but a necessity to ensure that
# $dt.utc.local.utc is equivalent to $dt.utc. Otherwise,
# DST-induced ambiguity could ruin our day.
@@ -48,17 +48,27 @@ my class DateTime does Dateish {
}

method !SET-SELF(
$!year,
$!month,
$!day,
$!hour,
$!minute,
$!second,
$!timezone,
&!formatter,
Int:D \year,
Int:D \month,
Int:D \day,
Int:D \hour,
Int:D \minute,
\second,
Int:D \timezone,
&formatter
--> DateTime:D) {
nqp::bind($!year, year); # R#2581
nqp::bind($!month, month);
nqp::bind($!day, day);
nqp::bind(&!formatter, &formatter);
nqp::bind($!daycount, nqp::null);
$!hour := hour;
$!minute := minute;
$!second := second;
$!timezone := timezone;
self
}

method !new-from-positional(DateTime:
Int() $year,
Int() $month,
@@ -1,7 +1,7 @@
my role Dateish {
has Int $.year;
has Int $.month; # should be int
has Int $.day; # should be int
has Int $.month;
has Int $.day;
has Int $.daycount;
has &.formatter;

@@ -44,14 +44,19 @@ my role Dateish {
multi method gist(Dateish:D: --> Str:D) { self.Str }

method daycount(--> Int:D) {
$!daycount //= do {
# taken from <http://www.merlyn.demon.co.uk/daycount.htm>
my int $m = $!month < 3 ?? $!month + 12 !! $!month;
my int $y = $!year - ($!month < 3);
-678973 + $!day + (153 * $m - 2) div 5
+ 365 * $y + $y div 4
- $y div 100 + $y div 400;
}
nqp::ifnull(

This comment has been minimized.

Copy link
@usev6

usev6 Feb 10, 2019

Contributor

This check doesn't seem to work for the jvm backend. One example for the failure mode (taken from a spectest) is

$ ./perl6-j -e 'say Date.new("2000-02-28").day-of-week'
Type check failed for return value; expected Int:D but got Int (Int)
  in block <unit> at -e line 1

Testing for nqp::isconcrete would help:

diff --git a/src/core/Dateish.pm6 b/src/core/Dateish.pm6
index b3ced5fad..0a40dc378 100644
--- a/src/core/Dateish.pm6
+++ b/src/core/Dateish.pm6
@@ -50,7 +50,8 @@ my role Dateish {
     multi method gist(Dateish:D: --> Str:D) { self.Str }
 
     method daycount(--> Int:D) {
-        nqp::ifnull(
+        nqp::if(
+          nqp::isconcrete($!daycount),
           $!daycount,
           $!daycount := self!calculate-daycount
         )

@lizmat Do you think that change would be ok-ish? (It's spectest clean for moar.)

$!daycount,
$!daycount := self!calculate-daycount
)
}
method !calculate-daycount(--> Int:D) {
# taken from <http://www.merlyn.demon.co.uk/daycount.htm>
my int $d = $!day;
my int $m = $!month < 3 ?? $!month + 12 !! $!month;
my int $y = $!year - ($!month < 3);
-678973 + $d + (153 * $m - 2) div 5
+ 365 * $y + $y div 4
- $y div 100 + $y div 400
}

method !ymd-from-daycount($daycount,\year,\month,\day --> Nil) {

0 comments on commit 9f28a42

Please sign in to comment.
You can’t perform that action at this time.