From 4949e780ca19af7748dadccc52a30122c7928a27 Mon Sep 17 00:00:00 2001 From: David Nichols Date: Fri, 11 Dec 2015 10:31:14 +0100 Subject: [PATCH] refs #243 #249 #250 fixed bugs in relative date/time arithmetic, added tests and updated docs + relnotes --- doxygen/lang/180_operators.dox.tmpl | 2 +- doxygen/lang/900_release_notes.dox.tmpl | 2 ++ examples/test/qore/operators/operators.qtest | 8 ++++++++ include/qore/intern/qore_date_private.h | 12 +++++++++--- lib/DateTime.cpp | 11 ++--------- lib/DateTimeNode.cpp | 11 ++--------- lib/Operator.cpp | 2 +- lib/qore_date_private.cpp | 9 +++++++++ 8 files changed, 34 insertions(+), 23 deletions(-) diff --git a/doxygen/lang/180_operators.dox.tmpl b/doxygen/lang/180_operators.dox.tmpl index 23d14bc4bd..86118501f7 100644 --- a/doxygen/lang/180_operators.dox.tmpl +++ b/doxygen/lang/180_operators.dox.tmpl @@ -915,7 +915,7 @@ foreach my string $key in (keys $hash) @par Synopsis With @ref float "float", @ref integer "integer", or @ref number "number" arguments, subtracts one number from another.\n\n - With @ref date "date" arguments, subtracts one date from another; if both date arguments are absolute dates, the result is a relative date (duration) giving the time between them; if the first date argument is an absolute date and the second is a relative date (duration), then the result is an absolute date. If both date arguments are relative dates, then the result is a relative date. If the first argument is a relative date and the second date is an absolute date, the result is an absolute date as if the operands were reversed.\n\n + With @ref date "date" arguments, subtracts one date from another; if both date arguments are @ref absolute_dates "absolute dates", the result is a @ref relative_dates "relative date" (duration) giving the time between them; if the first date argument is an @ref absolute_dates "absolute date" and the second is a @ref relative_dates "relative date" (duration), then the result is an @ref absolute_dates "absolute date". If both date arguments are @ref relative_dates "relative dates", then the result is a @ref relative_dates "relative date". If the first argument is a @ref relative_dates "relative date" and the second date is an @ref absolute_dates "absolute date", the @ref absolute_dates "absolute date"'s epoch offset (offset in seconds and microseconds from \c 1970-01-01Z) is used to perform the calculation, and a @ref relative_dates "relative date/time value" is produced.\n\n However, if the left-hand side is a @ref hash "hash", and the right-hand side is a string, then the hash key represented by the string will be removed from the hash. If the left-hand side is a hash and the right-hand side is a list, then each element in the list will be converted to a string and any hash key with that name will be deleted from the hash. @par Syntax diff --git a/doxygen/lang/900_release_notes.dox.tmpl b/doxygen/lang/900_release_notes.dox.tmpl index 557206f857..56b5bc31c4 100644 --- a/doxygen/lang/900_release_notes.dox.tmpl +++ b/doxygen/lang/900_release_notes.dox.tmpl @@ -369,6 +369,8 @@ - fixed a bug where imported global variables (@ref Qore::Program::importGlobalVariable()) were added to the pending global variable list and therefore were removed if a parse exception occurred, hwoever the namespace indexes remained, which could lead to unexpected problems at runtime including a crash. Additionally the pending global variable list was not checked which could lead to a memory leak if the a single global variable name is pending, imported, and then committed to the @ref Qore::Program "Program" object. - fixed memory errors managing program feature lists in the CharPtrList class by copying string memory instead of using sometimes temporary values in the list - fixed minor bugs with directive parsing, mostly related to error reporting + - fixed bugs in relative date arithmetic where operands were swapped with the @ref minus_operator "- operator" if the first operand was a @ref relative_dates "relative date/time value", additionally an operation with the @ref minus_operator "- operator" where the first operand is a @ref relative_dates "relative date" and the second operand is a @ref absolute_dates "absolute date" is now calculated using the @ref absolute_dates "absolute date"'s epoch offset (offset in seconds and microseconds from \c 1970-01-01Z), and a @ref relative_dates "relative date/time value" is produced + - fixed a bug normalizing the result of date arithmetic between hour and minute components of @ref relative_dates "relative date/time value" @section qore_0811 Qore 0.8.11 diff --git a/examples/test/qore/operators/operators.qtest b/examples/test/qore/operators/operators.qtest index 257170d783..c9f8b904ee 100755 --- a/examples/test/qore/operators/operators.qtest +++ b/examples/test/qore/operators/operators.qtest @@ -81,6 +81,14 @@ class Test inherits QUnit::Test { at -= (3h + 5m); testAssertionValue("second date += operator", at, 2004-02-29-08:55:00); + # relative date arithmetic tests + assertEq(3s, 5s - 2s); + assertEq(-1s, 2s - 3s); + # check for normalization between hours & minutes + assertEq(30m, 1h - 30m); + # rel date - abs date is performed by using the seconds + us offset from the epoch in the absolute date + assertEq(15s, 30s - 1970-01-01T00:00:15Z); + any ni += 3.2; testAssertionValue("float +=, lhs NOTHING", ni, 3.2); delete ni; diff --git a/include/qore/intern/qore_date_private.h b/include/qore/intern/qore_date_private.h index 49c1d5f119..1c5ac6e615 100644 --- a/include/qore/intern/qore_date_private.h +++ b/include/qore/intern/qore_date_private.h @@ -784,7 +784,10 @@ class qore_relative_time : public qore_simple_tm { // no longer normalize days, as with DST not all days are 24 hours // normalize hours from seconds - normalize_units(hour, second, 3600); + //normalize_units(hour, second, 3600); + + // normalize hours from minutes + normalize_units(hour, minute, 60); // normalize minutes from seconds normalize_units(minute, second, 60); @@ -953,6 +956,7 @@ class qore_relative_time : public qore_simple_tm { DLLLOCAL qore_relative_time& operator+=(const qore_relative_time& dt); DLLLOCAL qore_relative_time& operator-=(const qore_relative_time& dt); + DLLLOCAL qore_relative_time& operator-=(const qore_absolute_time& dt); DLLLOCAL void getAsString(QoreString& str) const { int f = 0; @@ -1237,8 +1241,10 @@ class qore_date_private { return; } - assert(dt.relative); - d.rel -= dt.d.rel; + if (dt.relative) + d.rel -= dt.d.rel; + else + d.rel -= dt.d.abs; } DLLLOCAL void addSecondsTo(int64 secs, int us) { diff --git a/lib/DateTime.cpp b/lib/DateTime.cpp index 99b481d7e7..e693f4410e 100644 --- a/lib/DateTime.cpp +++ b/lib/DateTime.cpp @@ -297,15 +297,8 @@ DateTime* DateTime::subtractBy(const DateTime* dt) const { } DateTime* DateTime::subtractBy(const DateTime& dt) const { - DateTime* rv; - if (isRelative()) { - rv = new DateTime(dt); - rv->priv->subtractBy(*priv); - } - else { - rv = new DateTime(*this); - rv->priv->subtractBy(*dt.priv); - } + DateTime* rv = new DateTime(*this); + rv->priv->subtractBy(*dt.priv); return rv; } diff --git a/lib/DateTimeNode.cpp b/lib/DateTimeNode.cpp index f273033005..7027e2ac71 100644 --- a/lib/DateTimeNode.cpp +++ b/lib/DateTimeNode.cpp @@ -188,15 +188,8 @@ DateTimeNode* DateTimeNode::subtractBy(const DateTime& dt) const { if (!dt.hasValue()) return refSelf(); - DateTimeNode* rv; - if (isRelative()) { - rv = new DateTimeNode(dt); - rv->priv->subtractBy(*priv); - } - else { - rv = new DateTimeNode(*this); - rv->priv->subtractBy(*dt.priv); - } + DateTimeNode* rv = new DateTimeNode(*this); + rv->priv->subtractBy(*dt.priv); return rv; } diff --git a/lib/Operator.cpp b/lib/Operator.cpp index 6fe28da9a4..686be765fa 100644 --- a/lib/Operator.cpp +++ b/lib/Operator.cpp @@ -388,7 +388,7 @@ static int64 op_multiply_bigint(int64 left, int64 right) { } static DateTimeNode* op_minus_date(const DateTimeNode* left, const DateTimeNode* right) { - return left->subtractBy(right); + return left->subtractBy(right); } static DateTimeNode* op_plus_date(const DateTimeNode* left, const DateTimeNode* right) { diff --git a/lib/qore_date_private.cpp b/lib/qore_date_private.cpp index f523041a59..77af053257 100644 --- a/lib/qore_date_private.cpp +++ b/lib/qore_date_private.cpp @@ -501,6 +501,15 @@ qore_relative_time &qore_relative_time::operator-=(const qore_relative_time &dt) return *this; } +qore_relative_time &qore_relative_time::operator-=(const qore_absolute_time &dt) { + second -= dt.epoch; + us -= dt.us; + + normalize(); + + return *this; +} + void qore_relative_time::set(const QoreValue v) { switch (v.type) { case QV_Bool: {