use
5.010;
use
Mo
qw(build default)
;
our
$AUTHORITY
=
'cpan:PERLANCAR'
;
our
$DATE
=
'2024-02-16'
;
our
$DIST
=
'Data-Sah'
;
our
$VERSION
=
'0.917'
;
sub
handle_type {
my
(
$self
,
$cd
) =
@_
;
my
$c
=
$self
->compiler;
my
$dt
=
$cd
->{data_term};
$cd
->{coerce_to} =
$cd
->{nschema}[1]{
"x.perl.coerce_to"
} //
'float(epoch)'
;
my
$coerce_to
=
$cd
->{coerce_to};
if
(
$coerce_to
eq
'float(epoch)'
) {
$cd
->{_ccl_check_type} =
"!ref($dt) && $dt =~ /\\A[0-9]+\\z/"
;
}
elsif
(
$coerce_to
eq
'DateTime'
) {
$c
->add_runtime_module(
$cd
,
'Scalar::Util'
);
$cd
->{_ccl_check_type} =
"Scalar::Util::blessed($dt) && $dt\->isa('DateTime')"
;
}
elsif
(
$coerce_to
eq
'Time::Moment'
) {
$c
->add_runtime_module(
$cd
,
'Scalar::Util'
);
$cd
->{_ccl_check_type} =
"Scalar::Util::blessed($dt) && $dt\->isa('Time::Moment')"
;
}
else
{
die
"BUG: Unknown coerce_to value '$coerce_to', use either "
.
"float(epoch), DateTime, or Time::Moment"
;
}
}
sub
superclause_comparable {
my
(
$self
,
$which
,
$cd
) =
@_
;
my
$c
=
$self
->compiler;
my
$cv
=
$cd
->{cl_value};
my
$ct
=
$cd
->{cl_term};
my
$dt
=
$cd
->{data_term};
if
(
$cd
->{cl_is_expr}) {
$c
->_die(
$cd
,
"date's comparison with expression not yet supported"
);
}
my
$coerce_to
=
$cd
->{coerce_to};
if
(
$coerce_to
eq
'float(epoch)'
) {
if
(
$which
eq
'is'
) {
$c
->add_ccl(
$cd
,
"$dt == $ct"
);
}
elsif
(
$which
eq
'in'
) {
$c
->add_runtime_module(
$cd
,
'List::Util'
);
$c
->add_ccl(
$cd
,
"List::Util::first(sub{$dt == \$_}, $ct)"
);
}
}
elsif
(
$coerce_to
eq
'DateTime'
) {
my
$ect
=
"DateTime->from_epoch(epoch=>"
.
$cv
->epoch.
")"
;
if
(
$which
eq
'is'
) {
$c
->add_ccl(
$cd
,
"DateTime->compare($dt, $ect)==0"
);
}
elsif
(
$which
eq
'in'
) {
$c
->add_runtime_module(
$cd
,
'List::Util'
);
$c
->add_ccl(
$cd
,
"List::Util::first(sub{DateTime->compare($dt, \$_)==0}, $ect)"
);
}
}
elsif
(
$coerce_to
eq
'Time::Moment'
) {
my
$ect
=
"Time::Moment->from_epoch("
.
$cv
->epoch.
")"
;
if
(
$which
eq
'is'
) {
$c
->add_ccl(
$cd
,
"$dt\->compare($ect)==0"
);
}
elsif
(
$which
eq
'in'
) {
$c
->add_runtime_module(
$cd
,
'List::Util'
);
$c
->add_ccl(
$cd
,
"List::Util::first(sub{$dt\->compare(\$_)==0}, $ect)"
);
}
}
}
sub
superclause_sortable {
my
(
$self
,
$which
,
$cd
) =
@_
;
my
$c
=
$self
->compiler;
my
$cv
=
$cd
->{cl_value};
my
$ct
=
$cd
->{cl_term};
my
$dt
=
$cd
->{data_term};
if
(
$cd
->{cl_is_expr}) {
$c
->_die(
$cd
,
"date's comparison with expression not yet supported"
);
}
my
$coerce_to
=
$cd
->{coerce_to};
if
(
$coerce_to
eq
'float(epoch)'
) {
if
(
$which
eq
'min'
) {
$c
->add_ccl(
$cd
,
"$dt >= $cv"
);
}
elsif
(
$which
eq
'xmin'
) {
$c
->add_ccl(
$cd
,
"$dt > $cv"
);
}
elsif
(
$which
eq
'max'
) {
$c
->add_ccl(
$cd
,
"$dt <= $cv"
);
}
elsif
(
$which
eq
'xmax'
) {
$c
->add_ccl(
$cd
,
"$dt < $cv"
);
}
elsif
(
$which
eq
'between'
) {
$c
->add_ccl(
$cd
,
"$dt >= $cv->[0] && $dt <= $cv->[1]"
);
}
elsif
(
$which
eq
'xbetween'
) {
$c
->add_ccl(
$cd
,
"$dt > $cv->[0] && $dt < $cv->[1]"
);
}
}
elsif
(
$coerce_to
eq
'DateTime'
) {
my
(
$ect
,
$ect0
,
$ect1
);
if
(
ref
(
$cv
) eq
'ARRAY'
) {
$ect0
=
"DateTime->from_epoch(epoch=>"
.
$cv
->[0]->epoch.
")"
;
$ect1
=
"DateTime->from_epoch(epoch=>"
.
$cv
->[1]->epoch.
")"
;
}
else
{
$ect
=
"DateTime->from_epoch(epoch=>"
.
$cv
->epoch.
")"
;
}
if
(
$which
eq
'min'
) {
$c
->add_ccl(
$cd
,
"DateTime->compare($dt, $ect) >= 0"
);
}
elsif
(
$which
eq
'xmin'
) {
$c
->add_ccl(
$cd
,
"DateTime->compare($dt, $ect) > 0"
);
}
elsif
(
$which
eq
'max'
) {
$c
->add_ccl(
$cd
,
"DateTime->compare($dt, $ect) <= 0"
);
}
elsif
(
$which
eq
'xmax'
) {
$c
->add_ccl(
$cd
,
"DateTime->compare($dt, $ect) < 0"
);
}
elsif
(
$which
eq
'between'
) {
$c
->add_ccl(
$cd
,
"DateTime->compare($dt, $ect0) >= 0 && DateTime->compare($dt, $ect1) <= 0"
);
}
elsif
(
$which
eq
'xbetween'
) {
$c
->add_ccl(
$cd
,
"DateTime->compare($dt, $ect0) > 0 && DateTime->compare($dt, $ect1) < 0"
);
}
}
elsif
(
$coerce_to
eq
'Time::Moment'
) {
my
(
$ect
,
$ect0
,
$ect1
);
if
(
ref
(
$cv
) eq
'ARRAY'
) {
$ect0
=
"Time::Moment->from_epoch("
.
$cv
->[0]->epoch.
")"
;
$ect1
=
"Time::Moment->from_epoch("
.
$cv
->[1]->epoch.
")"
;
}
else
{
$ect
=
"Time::Moment->from_epoch("
.
$cv
->epoch.
")"
;
}
if
(
$which
eq
'min'
) {
$c
->add_ccl(
$cd
,
"$dt\->compare($ect) >= 0"
);
}
elsif
(
$which
eq
'xmin'
) {
$c
->add_ccl(
$cd
,
"$dt\->compare($ect) > 0"
);
}
elsif
(
$which
eq
'max'
) {
$c
->add_ccl(
$cd
,
"$dt\->compare($ect) <= 0"
);
}
elsif
(
$which
eq
'xmax'
) {
$c
->add_ccl(
$cd
,
"$dt\->compare($ect) < 0"
);
}
elsif
(
$which
eq
'between'
) {
$c
->add_ccl(
$cd
,
"$dt\->compare($ect0) >= 0 && $dt\->compare($ect1) <= 0"
);
}
elsif
(
$which
eq
'xbetween'
) {
$c
->add_ccl(
$cd
,
"$dt\->compare($ect0) > 0 && $dt\->compare($ect1) < 0"
);
}
}
}
1;