Skip to content

Commit

Permalink
Subclasses of .Date(Time) coercion
Browse files Browse the repository at this point in the history
Calling .Date on a subclass of Date, and .DateTime on a subclass
of DateTime, returned the object itself even if it was a subclass.

This commit makes sure that if you call .Date(Time) on a subclass
of Date(Time), you will actually get the appropriate Date(Time)
object.

This should remove the need of subclasses to provide this logic,
such as e.g. in Games::TauStation::DateTime.

If accepted, this should probably also be done for all core class
coercers.
  • Loading branch information
lizmat committed May 20, 2022
1 parent 6bd19e4 commit 9a2095b
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 24 deletions.
50 changes: 27 additions & 23 deletions src/core.c/Date.pm6
Expand Up @@ -26,22 +26,22 @@ my class Date does Dateish {
unless 1 <= $day <= self!DAYS-IN-MONTH($year, $month);
}

method !SET-SELF(int $year, int $month, int $day, &formatter --> Date:D) {
nqp::bindattr_i(self,Date,'$!year',$year);
nqp::bindattr_i(self,Date,'$!month',$month);
nqp::bindattr_i(self,Date,'$!day',$day);
nqp::bindattr(self,Date,'&!formatter',&formatter);
self
}

# fast object creation with sanity check on month/day
method !SET-SELF(int $year, int $month, int $day, $formatter --> Date:D) {
nqp::if(
nqp::isge_i($month,1)
&& nqp::isle_i($month,12)
&& nqp::isge_i($day,1)
&& nqp::isle_i($day, self!DAYS-IN-MONTH($year, $month)),
nqp::stmts(
nqp::bindattr_i(self,Date,'$!year',$year),
nqp::bindattr_i(self,Date,'$!month',$month),
nqp::bindattr_i(self,Date,'$!day',$day),
nqp::bindattr(self,Date,'&!formatter',$formatter),
self
),
self!wrong-oor($year, $month, $day)
)
method !fast(int $year, int $month, int $day, &formatter --> Date:D) {
nqp::isge_i($month,1)
&& nqp::isle_i($month,12)
&& nqp::isge_i($day,1)
&& nqp::isle_i($day, self!DAYS-IN-MONTH($year, $month))
?? self!SET-SELF($year, $month, $day, &formatter)
!! self!wrong-oor($year, $month, $day)
}

# object creation for subclasses, with sanity check on month/day
Expand Down Expand Up @@ -70,7 +70,7 @@ my class Date does Dateish {
$day = self!day-not-Int($year, $month, $day)
unless nqp::istype($day,Int);
nqp::eqaddr(self.WHAT,Date)
?? nqp::create(self)!SET-SELF($year, $month, $day, &formatter)
?? nqp::create(self)!fast($year, $month, $day, &formatter)
!! self!bless($year, $month, $day, &formatter, %_)
}
multi method new(Date:
Expand All @@ -79,7 +79,7 @@ my class Date does Dateish {
$day = self!day-not-Int($year, $month, $day)
unless nqp::istype($day,Int);
nqp::eqaddr(self.WHAT,Date)
?? nqp::create(self)!SET-SELF($year, $month, $day, &formatter)
?? nqp::create(self)!fast($year, $month, $day, &formatter)
!! self!bless($year, $month, $day, &formatter, %_)
}
multi method new(Date: Str:D $Date, :&formatter --> Date:D) {
Expand All @@ -93,7 +93,7 @@ my class Date does Dateish {
&& nqp::eqat($date,'-',4)
&& nqp::eqat($date,'-',7) {
nqp::eqaddr(self.WHAT,Date)
?? nqp::create(self)!SET-SELF(
?? nqp::create(self)!fast(
nqp::substr($date,0,4).Int,
nqp::substr($date,5,2).Int,
nqp::substr($date,8,2).Int,
Expand All @@ -117,7 +117,7 @@ my class Date does Dateish {
(\d\d) # day
$/) {
nqp::eqaddr(self.WHAT,Date)
?? nqp::create(self)!SET-SELF($0.Int,$1.Int,$2.Int,&formatter)
?? nqp::create(self)!fast($0.Int,$1.Int,$2.Int,&formatter)
!! self!bless($0.Int, $1.Int, $2.Int, &formatter, %_)
}

Expand All @@ -134,7 +134,7 @@ my class Date does Dateish {
}
multi method new(Date: Dateish $d, :&formatter, *%_ --> Date:D) {
nqp::eqaddr(self.WHAT,Date)
?? nqp::create(self)!SET-SELF($d.year,$d.month,$d.day,&formatter)
?? nqp::create(self)!fast($d.year,$d.month,$d.day,&formatter)
!! self.bless(
:year($d.year),:month($d.month),:day($d.day),:&formatter, |%_
)!SET-DAYCOUNT
Expand Down Expand Up @@ -181,7 +181,7 @@ my class Date does Dateish {
method today(:&formatter --> Date:D) {
my $lt := nqp::decodelocaltime(time);
nqp::eqaddr(self.WHAT,Date)
?? nqp::create(self)!SET-SELF(
?? nqp::create(self)!fast(
nqp::atpos_i($lt,5), # year
nqp::atpos_i($lt,4), # month
nqp::atpos_i($lt,3), # day
Expand Down Expand Up @@ -359,7 +359,7 @@ my class Date does Dateish {
# A premature optimization.
method !clone-without-validating(Date:D: *%_ --> Date:D) {
my $h := nqp::getattr(%_,Map,'$!storage');
nqp::create(self)!SET-SELF(
nqp::create(self)!fast(
nqp::ifnull(nqp::atkey($h,'year'), $!year),
nqp::ifnull(nqp::atkey($h,'month'),$!month),
nqp::ifnull(nqp::atkey($h,'day'), $!day),
Expand Down Expand Up @@ -398,7 +398,11 @@ my class Date does Dateish {
DateTime.new(:$!year, :$!month, :$!day)
}
multi method DateTime(Date:U: --> DateTime:U) { DateTime }
method Date() { self }
method Date() {
nqp::eqaddr(self.WHAT,Date)
?? self
!! nqp::create(Date)!SET-SELF($!year, $!month, $!day, &!formatter)
}
}

multi sub infix:<+>(Date:D $date, Int:D $x --> Date:D) {
Expand Down
8 changes: 7 additions & 1 deletion src/core.c/DateTime.pm6
Expand Up @@ -600,7 +600,13 @@ my class DateTime does Dateish {
proto method Date() {*}
multi method Date(DateTime:D: --> Date:D) { Date.new($!year,$!month,$!day) }
multi method Date(DateTime:U: --> Date:U) { Date }
method DateTime() { self }
method DateTime() {
nqp::eqaddr(self.WHAT,DateTime)
?? self
!! nqp::create(DateTime)!SET-SELF:
$!year, $!month, $!day, $!hour, $!minute, $!second,
$!timezone, &!formatter
}

multi method raku(DateTime:D: --> Str:D) {
self.^name
Expand Down

0 comments on commit 9a2095b

Please sign in to comment.