diff --git a/Operand.cpp b/Operand.cpp index ca4c94f..db245c2 100644 --- a/Operand.cpp +++ b/Operand.cpp @@ -404,11 +404,28 @@ namespace jet { throw coreutils::Exception("Expecting , in DATEDIFF expression."); Operand parm2(in, tag); if(in.ifNext(")")) { - - // TODO: Implement DATEDIFF. - + // Matches MySQL's DATEDIFF(expr1, expr2): expr1 - expr2 expressed + // 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 - throw coreutils::Exception("Expecting ) at end of DATEDIFF expression."); + throw coreutils::Exception("Expecting ) at end of DATEDIFF expression."); } else if(in.ifNextIgnoreCase("true")) { boolean = true; string = "true";