Implement datediff(a, b)
Parsed its arguments correctly but had an empty body (a literal
"// TODO: Implement DATEDIFF." comment), never setting a result - isNumber
was left uninitialized on this path.
Matches MySQL's own DATEDIFF(expr1, expr2): expr1 - expr2 expressed as a
whole number of days, ignoring time-of-day. Dates parse as YYYY-MM-DD via
strptime (a longer "YYYY-MM-DD HH:MM:SS" value parses fine too, since
strptime only consumes what the format string asks for) and are
interpreted as UTC via timegm() rather than mktime(), so the result
doesn't shift with the server's own timezone. An unparseable date throws
a clear, specific error instead of producing garbage.
Verified via real jet-2.0 runs: datediff('2026-08-26','2026-08-20') -> 6,
the reverse -> -6, same date -> 0, a full non-leap year -> 365, and an
invalid date string throws cleanly rather than crashing or silently
returning nonsense. Full 9-script regression suite still passes.
This commit is contained in:
1 parent
5c703f5620
commit
8b2391b289
1 file changed
+21
-4
+21
-4
@@ -404,11 +404,28 @@ namespace jet {
|
|||||||
throw coreutils::Exception("Expecting , in DATEDIFF expression.");
|
throw coreutils::Exception("Expecting , in DATEDIFF expression.");
|
||||||
Operand parm2(in, tag);
|
Operand parm2(in, tag);
|
||||||
if(in.ifNext(")")) {
|
if(in.ifNext(")")) {
|
||||||
|
// Matches MySQL's DATEDIFF(expr1, expr2): expr1 - expr2 expressed
|
||||||
// TODO: Implement DATEDIFF.
|
// as a whole number of days, ignoring any time-of-day component.
|
||||||
|
// Dates are parsed as YYYY-MM-DD (a leading date portion of a
|
||||||
|
// longer "YYYY-MM-DD HH:MM:SS" value parses fine too, since
|
||||||
|
// strptime only consumes what the format string asks for) and
|
||||||
|
// interpreted as UTC via timegm() (not mktime(), which is
|
||||||
|
// local-timezone-dependent) so the result doesn't shift with the
|
||||||
|
// server's own timezone setting.
|
||||||
|
struct tm tm1 = {};
|
||||||
|
struct tm tm2 = {};
|
||||||
|
if(!strptime(parm1.string.c_str(), "%Y-%m-%d", &tm1))
|
||||||
|
throw coreutils::Exception("DATEDIFF: first argument is not a valid date (expected YYYY-MM-DD).");
|
||||||
|
if(!strptime(parm2.string.c_str(), "%Y-%m-%d", &tm2))
|
||||||
|
throw coreutils::Exception("DATEDIFF: second argument is not a valid date (expected YYYY-MM-DD).");
|
||||||
|
time_t t1 = timegm(&tm1);
|
||||||
|
time_t t2 = timegm(&tm2);
|
||||||
|
doubleValue = difftime(t1, t2) / 86400.0;
|
||||||
|
isNumber = true;
|
||||||
|
string = std::format("{:.12f}", doubleValue);
|
||||||
|
string.removeTrailingZeros();
|
||||||
} else
|
} else
|
||||||
throw coreutils::Exception("Expecting ) at end of DATEDIFF expression.");
|
throw coreutils::Exception("Expecting ) at end of DATEDIFF expression.");
|
||||||
} else if(in.ifNextIgnoreCase("true")) {
|
} else if(in.ifNextIgnoreCase("true")) {
|
||||||
boolean = true;
|
boolean = true;
|
||||||
string = "true";
|
string = "true";
|
||||||
|
|||||||
Reference in new issue
Block a user