gnucash maint: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Sat Jul 2 19:13:04 EDT 2016


Updated	 via  https://github.com/Gnucash/gnucash/commit/51e29e78 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/6a81738e (commit)
	from  https://github.com/Gnucash/gnucash/commit/704bc835 (commit)



commit 51e29e7836af814868f51161cb3263465a5e951f
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Jul 2 16:03:55 2016 -0700

    Bug 137017 - date of transaction change with time zone change
    
    First step: Change the timestamp to 11:00 UTC instead of midnight local,
    adjusting by an hour or two if the local timezone is one near the
    International Date Line to keep the date from flipping around.
    
    Scrub all old entries to make current files correct.
    
    Note: This effectively disposes of the distinction of close-book transactions
    having a noon instead of midnight timestamp as a way to distinguish them
    from regular transactions, but that distinction doesn't seem to be used;
    xaccTransIsCloseBook() is used instead.

diff --git a/src/backend/sql/gnc-transaction-sql.c b/src/backend/sql/gnc-transaction-sql.c
index 0ea2189..b228c61 100644
--- a/src/backend/sql/gnc-transaction-sql.c
+++ b/src/backend/sql/gnc-transaction-sql.c
@@ -36,6 +36,7 @@
 
 #include "Account.h"
 #include "Transaction.h"
+#include <Scrub.h>
 #include "gnc-lot.h"
 #include "engine-helpers.h"
 
@@ -376,6 +377,7 @@ query_transactions( GncSqlBackend* be, GncSqlStatement* stmt )
             if ( tx != NULL )
             {
                 tx_list = g_list_prepend( tx_list, tx );
+                xaccTransScrubPostedDate (tx);
             }
             row = gnc_sql_result_get_next_row( result );
         }
diff --git a/src/backend/xml/io-gncxml-v2.c b/src/backend/xml/io-gncxml-v2.c
index 051c94c..0531984 100644
--- a/src/backend/xml/io-gncxml-v2.c
+++ b/src/backend/xml/io-gncxml-v2.c
@@ -278,6 +278,7 @@ add_transaction_local(sixtp_gdv2 *data, Transaction *trn)
                                    xaccTransSetCurrency);
 
     xaccTransScrubCurrency (trn);
+    xaccTransScrubPostedDate (trn);
     xaccTransCommitEdit (trn);
 
     data->counter.transactions_loaded++;
diff --git a/src/engine/Scrub.c b/src/engine/Scrub.c
index dc22b20..4146f9b 100644
--- a/src/engine/Scrub.c
+++ b/src/engine/Scrub.c
@@ -1373,4 +1373,17 @@ xaccScrubUtilityGetOrMakeAccount (Account *root, gnc_commodity * currency,
     return acc;
 }
 
+void
+xaccTransScrubPostedDate (Transaction *trans)
+{
+    time64 orig = xaccTransGetDate(trans);
+    GDate date = xaccTransGetDatePostedGDate(trans);
+    Timespec ts = gdate_to_timespec(date);
+    if (orig && orig != ts.tv_sec)
+    {
+        /* xaccTransSetDatePostedTS handles committing the change. */
+        xaccTransSetDatePostedTS(trans, &ts);
+    }
+}
+
 /* ==================== END OF FILE ==================== */
diff --git a/src/engine/Scrub.h b/src/engine/Scrub.h
index 82d5e2d..efdad1b 100644
--- a/src/engine/Scrub.h
+++ b/src/engine/Scrub.h
@@ -142,8 +142,18 @@ void xaccAccountTreeScrubCommodities (Account *acc);
  */
 void xaccAccountTreeScrubQuoteSources (Account *root, gnc_commodity_table *table);
 
+/** Removes empty "notes", "placeholder", and "hbci" KVP slots from Accounts. */
 void xaccAccountScrubKvp (Account *account);
 
+/** Changes Transaction date_posted timestamps from 00:00 local to 11:00 UTC.
+ * 11:00 UTC is the same day local time in almost all timezones, the exceptions
+ * being the -12, +13, and +14 timezones along the International Date Line. If
+ * Local time is set to one of these timezones then the new date_posted time
+ * will be adjusted as needed to ensure that the date doesn't change there. This
+ * change was made for v2.6.14 to partially resolve bug 137017.
+ */
+void xaccTransScrubPostedDate (Transaction *trans);
+
 #endif /* XACC_SCRUB_H */
 /** @} */
 /** @} */
diff --git a/src/libqof/qof/gnc-date.c b/src/libqof/qof/gnc-date.c
index 50cd248..3da2eca 100644
--- a/src/libqof/qof/gnc-date.c
+++ b/src/libqof/qof/gnc-date.c
@@ -183,6 +183,7 @@ gnc_g_date_time_to_local (GDateTime* gdt)
 typedef struct
 {
     GDateTime *(*new_local)(gint, gint, gint, gint, gint, gdouble);
+    GDateTime *(*new_utc)(gint, gint, gint, gint, gint, gdouble);
     GDateTime *(*adjust_for_dst)(GDateTime *, GTimeZone *);
     GDateTime *(*new_from_unix_local)(time64);
     GDateTime *(*new_from_timeval_local)(const GTimeVal *);
@@ -195,6 +196,7 @@ void
 _gnc_date_time_init (_GncDateTime *gncdt)
 {
     gncdt->new_local = gnc_g_date_time_new_local;
+    gncdt->new_utc = g_date_time_new_utc;
     gncdt->adjust_for_dst = gnc_g_date_time_adjust_for_dst;
     gncdt->new_from_unix_local = gnc_g_date_time_new_from_unix_local;
     gncdt->new_from_timeval_local = gnc_g_date_time_new_from_timeval_local;
@@ -372,12 +374,13 @@ gnc_timegm (struct tm* time)
      gdt = g_date_time_new_utc (time->tm_year + 1900, time->tm_mon,
 				time->tm_mday, time->tm_hour, time->tm_min,
 				(gdouble)(time->tm_sec));
-     time->tm_mon = time->tm_mon > 0 ? time->tm_mon - 1 : 11;
-     // Watch out: struct tm has wday=0..6 with Sunday=0, but GDateTime has wday=1..7 with Sunday=7.
-     time->tm_wday = g_date_time_get_day_of_week (gdt) % 7;
-     time->tm_yday = g_date_time_get_day_of_year (gdt);
-     time->tm_isdst = g_date_time_is_daylight_savings (gdt);
-
+     if (gdt == NULL)
+     {
+         PERR("Failed to get valid GDateTime with struct tm: %d-%d-%d %d:%d:%d",
+              time->tm_year + 1900, time->tm_mon, time->tm_mday, time->tm_hour,
+              time->tm_min, time->tm_sec);
+         return 0;
+     }
      secs = g_date_time_to_unix (gdt);
      g_date_time_unref (gdt);
      return secs;
@@ -1551,6 +1554,7 @@ gnc_dmy2timespec_internal (int day, int month, int year, gboolean start_of_day)
     return result;
 }
 
+
 Timespec
 gnc_dmy2timespec (int day, int month, int year)
 {
@@ -1563,6 +1567,29 @@ gnc_dmy2timespec_end (int day, int month, int year)
     return gnc_dmy2timespec_internal (day, month, year, FALSE);
 }
 
+Timespec
+gnc_dmy2timespec_neutral (int day, int month, int year)
+{
+    struct tm date;
+    Timespec ts = {0, 0};
+    GTimeZone *zone = gnc_g_time_zone_new_local();
+    GDateTime *gdt = gnc_g_date_time_new_local (year, month, day, 12, 0, 0.0);
+    int interval = g_time_zone_find_interval (zone, G_TIME_TYPE_STANDARD,
+                                              g_date_time_to_unix(gdt));
+    int offset = g_time_zone_get_offset(gnc_g_time_zone_new_local(),
+                                        interval) / 3600;
+    g_date_time_unref (gdt);
+    memset (&date, 0, sizeof(struct tm));
+    date.tm_year = year - 1900;
+    date.tm_mon = month - 1;
+    date.tm_mday = day;
+    date.tm_hour = offset < -11 ? -offset : offset > 13 ? 24 - offset : 11;
+    date.tm_min = 0;
+    date.tm_sec = 0;
+
+    ts.tv_sec = gnc_timegm(&date);
+    return ts;
+}
 /********************************************************************\
 \********************************************************************/
 
@@ -1648,9 +1675,9 @@ GDate* gnc_g_date_new_today ()
 Timespec gdate_to_timespec (GDate d)
 {
     gnc_gdate_range_check (&d);
-    return gnc_dmy2timespec(g_date_get_day(&d),
-                            g_date_get_month(&d),
-                            g_date_get_year(&d));
+    return gnc_dmy2timespec_neutral (g_date_get_day(&d),
+                                     g_date_get_month(&d),
+                                     g_date_get_year(&d));
 }
 
 static void
diff --git a/src/libqof/qof/gnc-date.h b/src/libqof/qof/gnc-date.h
index 56fed84..51fa353 100644
--- a/src/libqof/qof/gnc-date.h
+++ b/src/libqof/qof/gnc-date.h
@@ -351,6 +351,15 @@ Timespec gnc_dmy2timespec (gint day, gint month, gint year);
 /** Same as gnc_dmy2timespec, but last second of the day */
 Timespec gnc_dmy2timespec_end (gint day, gint month, gint year);
 
+/** Converts a day, month, and year to a Timespec representing 11:00:00 UTC
+ *  11:00:00 UTC falls on the same time in almost all timezones, the exceptions
+ *  being the +13, +14, and -12 timezones used by countries along the
+ *  International Date Line. Since users in those timezones would see dates
+ *  immediately change by one day, the function checks the current timezone for
+ *  those changes and adjusts the UTC time so that the date will be consistent.
+ */
+Timespec gnc_dmy2timespec_neutral (gint day, gint month, gint year);
+
 /** The gnc_iso8601_to_timespec_gmt() routine converts an ISO-8601 style
  *    date/time string to Timespec.  Please note that ISO-8601 strings
  *    are a representation of Universal Time (UTC), and as such, they
diff --git a/src/libqof/qof/test/test-gnc-date.c b/src/libqof/qof/test/test-gnc-date.c
index a610beb..4210177 100644
--- a/src/libqof/qof/test/test-gnc-date.c
+++ b/src/libqof/qof/test/test-gnc-date.c
@@ -47,6 +47,7 @@ void test_suite_gnc_date ( void );
 typedef struct
 {
     GDateTime *(*new_local)(gint, gint, gint, gint, gint, gdouble);
+    GDateTime *(*new_utc)(gint, gint, gint, gint, gint, gdouble);
     GDateTime *(*adjust_for_dst)(GDateTime *, GTimeZone *);
     GDateTime *(*new_from_unix_local)(time64);
     GDateTime *(*new_from_timeval_local)(GTimeVal *);
@@ -1967,6 +1968,48 @@ test_gnc_dmy2timespec_end (void)
     g_date_time_unref (gdt3);
     g_date_time_unref (gdt4);
 }
+
+/*gnc_dmy2timespec_neutral*/
+static void
+test_gnc_dmy2timespec_neutral (void)
+{
+    GDateTime *gdt1 = gncdt.new_utc (1999, 7, 21, 11, 0, 0);
+    GDateTime *gdt2 = gncdt.new_utc (1918, 3, 31, 11, 0, 0);
+    GDateTime *gdt3 = gncdt.new_utc (1918, 4, 1, 11, 0, 0);
+    GDateTime *gdt4 = gncdt.new_utc (2057, 11, 20, 11, 0, 0);
+
+    gint day, mon, yr;
+    Timespec t, r_t;
+
+    t = g_date_time_to_timespec (gdt1);
+    g_date_time_get_ymd (gdt1, &yr, &mon, &day);
+    r_t = gnc_dmy2timespec_neutral (day, mon, yr);
+    g_assert_cmpint (r_t.tv_sec, ==, t.tv_sec);
+    g_assert_cmpint (r_t.tv_nsec, ==, t.tv_nsec);
+
+    t = g_date_time_to_timespec (gdt2);
+    g_date_time_get_ymd (gdt2, &yr, &mon, &day);
+    r_t = gnc_dmy2timespec_neutral (day, mon, yr);
+    g_assert_cmpint (r_t.tv_sec, ==, t.tv_sec);
+    g_assert_cmpint (r_t.tv_nsec, ==, t.tv_nsec);
+
+    t = g_date_time_to_timespec (gdt3);
+    g_date_time_get_ymd (gdt3, &yr, &mon, &day);
+    r_t = gnc_dmy2timespec_neutral (day, mon, yr);
+    g_assert_cmpint (r_t.tv_sec, ==, t.tv_sec);
+    g_assert_cmpint (r_t.tv_nsec, ==, t.tv_nsec);
+
+    t = g_date_time_to_timespec (gdt4);
+    g_date_time_get_ymd (gdt4, &yr, &mon, &day);
+    r_t = gnc_dmy2timespec_neutral (day, mon, yr);
+    g_assert_cmpint (r_t.tv_sec, ==, t.tv_sec);
+    g_assert_cmpint (r_t.tv_nsec, ==, t.tv_nsec);
+
+    g_date_time_unref (gdt1);
+    g_date_time_unref (gdt2);
+    g_date_time_unref (gdt3);
+    g_date_time_unref (gdt4);
+}
 /* gnc_timezone
 long int
 gnc_timezone (const struct tm *tm)// C: 5 in 2  Local: 2:0:0
@@ -2086,10 +2129,10 @@ Timespec gdate_to_timespec (GDate d)// C: 7 in 6  Local: 0:0:0
 static void
 test_gdate_to_timespec (void)
 {
-    GDateTime *gdt1 = gncdt.new_local (1999, 7, 21, 0, 0, 0);
-    GDateTime *gdt2 = gncdt.new_local (1918, 3, 31, 0, 0, 0);
-    GDateTime *gdt3 = gncdt.new_local (1918, 4, 1, 0, 0, 0);
-    GDateTime *gdt4 = gncdt.new_local (2057, 11, 20, 0, 0, 0);
+    GDateTime *gdt1 = gncdt.new_utc (1999, 7, 21, 11, 0, 0);
+    GDateTime *gdt2 = gncdt.new_utc (1918, 3, 31, 11, 0, 0);
+    GDateTime *gdt3 = gncdt.new_utc (1918, 4, 1, 11, 0, 0);
+    GDateTime *gdt4 = gncdt.new_utc (2057, 11, 20, 11, 0, 0);
 
     gint day, mon, yr;
     Timespec t, r_t;
@@ -2411,6 +2454,7 @@ test_suite_gnc_date (void)
 // GNC_TEST_ADD_FUNC (suitename, "gnc dmy2timespec internal", test_gnc_dmy2timespec_internal);
     GNC_TEST_ADD_FUNC (suitename, "gnc dmy2timespec", test_gnc_dmy2timespec);
     GNC_TEST_ADD_FUNC (suitename, "gnc dmy2timespec end", test_gnc_dmy2timespec_end);
+    GNC_TEST_ADD_FUNC (suitename, "gnc dmy2timespec Neutral", test_gnc_dmy2timespec_neutral);
 // GNC_TEST_ADD_FUNC (suitename, "gnc timezone", test_gnc_timezone);
 // GNC_TEST_ADD_FUNC (suitename, "timespecFromTime t", test_timespecFromtime64);
 // GNC_TEST_ADD_FUNC (suitename, "timespec now", test_timespec_now);

commit 6a81738e969cd56556f3dbaf1ee08521ee86a855
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Jul 2 14:08:14 2016 -0700

    Don't override optimization flags in CMakeLists.txt.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0cb86eb..913834e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -348,7 +348,7 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")  # FIXME: should be -std=
 
 
 IF (UNIX)
-  SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wdeclaration-after-statement -Wno-pointer-sign -D_FORTIFY_SOURCE=2 -Wall -Wunused -Wmissing-prototypes -Wmissing-declarations -O2 -Wno-unused -std=gnu99")
+  SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wdeclaration-after-statement -Wno-pointer-sign -D_FORTIFY_SOURCE=2 -Wall -Wunused -Wmissing-prototypes -Wmissing-declarations -Wno-unused -std=gnu99")
   SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=deprecated-declarations")
 ENDIF (UNIX)
 IF (MINGW)



Summary of changes:
 CMakeLists.txt                        |  2 +-
 src/backend/sql/gnc-transaction-sql.c |  2 ++
 src/backend/xml/io-gncxml-v2.c        |  1 +
 src/engine/Scrub.c                    | 13 +++++++++
 src/engine/Scrub.h                    | 10 +++++++
 src/libqof/qof/gnc-date.c             | 45 ++++++++++++++++++++++++------
 src/libqof/qof/gnc-date.h             |  9 ++++++
 src/libqof/qof/test/test-gnc-date.c   | 52 ++++++++++++++++++++++++++++++++---
 8 files changed, 120 insertions(+), 14 deletions(-)



More information about the gnucash-changes mailing list