gnucash master: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Sun Oct 9 04:54:12 EDT 2016


Updated	 via  https://github.com/Gnucash/gnucash/commit/20c0271e (commit)
	 via  https://github.com/Gnucash/gnucash/commit/b00694fd (commit)
	from  https://github.com/Gnucash/gnucash/commit/6e132d83 (commit)



commit 20c0271e985cfe711e0edf9bd89c1e06efc6db15
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Oct 4 20:00:48 2016 +0200

    Fix CSV importer to handle GMT + 13 Timezone (New Zealand Daylight Time).
    
    Also remove special time calculations and use gnc_dmy2timespec_neutral()
    for consistency with rest of GnuCash.

diff --git a/src/import-export/csv-imp/gnc-csv-model.c b/src/import-export/csv-imp/gnc-csv-model.c
index d0c6c0e..a862f01 100644
--- a/src/import-export/csv-imp/gnc-csv-model.c
+++ b/src/import-export/csv-imp/gnc-csv-model.c
@@ -107,11 +107,9 @@ static StfParseOptions_t* default_parse_options (void)
  */
 static time64 parse_date_with_year (const char* date_str, int format)
 {
-    time64 rawtime; /* The integer time */
-    struct tm retvalue, test_retvalue; /* The time in a broken-down structure */
-
-    int i, j, mem_length, orig_year = -1, orig_month = -1, orig_day = -1;
 
+    int i, j, mem_length, year = -1, month = -1, day = -1;
+    Timespec ts;
     /* Buffer for containing individual parts (e.g. year, month, day) of a date */
     char date_segment[5];
 
@@ -164,15 +162,6 @@ static time64 parse_date_with_year (const char* date_str, int format)
         }
     }
 
-    /* Put some sane values in retvalue by using a fixed time for
-     * the non-year-month-day parts of the date. */
-    gnc_time (&rawtime);
-    gnc_localtime_r (&rawtime, &retvalue);
-    retvalue.tm_hour = 11;
-    retvalue.tm_min = 0;
-    retvalue.tm_sec = 0;
-    retvalue.tm_isdst = -1;
-
     /* j traverses pmatch (index 0 contains the entire string, so we
      * start at index 1 for the first meaningful match). */
     j = 1;
@@ -196,51 +185,32 @@ static time64 parse_date_with_year (const char* date_str, int format)
             switch (segment_type)
             {
             case 'y':
-                retvalue.tm_year = atoi (date_segment);
+                year = atoi (date_segment);
 
                 /* Handle two-digit years. */
-                if (retvalue.tm_year < 100)
+                if (year < 100)
                 {
                     /* We allow two-digit years in the range 1969 - 2068. */
-                    if (retvalue.tm_year < 69)
-                        retvalue.tm_year += 100;
+                    if (year < 69)
+                        year += 2000;
+                    else
+                        year += 1900;
                 }
-                else
-                    retvalue.tm_year -= 1900;
-                orig_year = retvalue.tm_year;
                 break;
 
             case 'm':
-                orig_month = retvalue.tm_mon = atoi (date_segment) - 1;
+                month =atoi (date_segment);
                 break;
 
             case 'd':
-                orig_day = retvalue.tm_mday = atoi (date_segment);
+                day = atoi (date_segment);
                 break;
             }
             j++;
         }
     }
-    /* Convert back to an integer. If gnc_mktime leaves retvalue unchanged,
-     * everything is okay; otherwise, an error has occurred. */
-    /* We have to use a "test" date value to account for changes in
-     * daylight savings time, which can cause a date change with gnc_mktime
-     * near midnight, causing the code to incorrectly think a date is
-     * incorrect. */
-    test_retvalue = retvalue;
-    gnc_mktime (&test_retvalue);
-    retvalue.tm_isdst = test_retvalue.tm_isdst;
-    rawtime = gnc_mktime (&retvalue);
-    if (retvalue.tm_mday == orig_day &&
-            retvalue.tm_mon == orig_month &&
-            retvalue.tm_year == orig_year)
-    {
-        return rawtime;
-    }
-    else
-    {
-        return -1;
-    }
+    ts = gnc_dmy2timespec_neutral(day, month, year);
+    return ts.tv_sec;
 }
 
 /** Parses a string into a date, given a format. The format cannot
@@ -252,10 +222,8 @@ static time64 parse_date_with_year (const char* date_str, int format)
  */
 static time64 parse_date_without_year (const char* date_str, int format)
 {
-    time64 rawtime; /* The integer time */
-    struct tm retvalue, test_retvalue; /* The time in a broken-down structure */
-
-    int i, j, mem_length, orig_year = -1, orig_month = -1, orig_day = -1;
+    Timespec ts;
+    int i, j, mem_length, year = -1, month = -1, day = -1;
 
     /* Buffer for containing individual parts (e.g. year, month, day) of a date */
     gchar* date_segment;
@@ -273,21 +241,14 @@ static time64 parse_date_without_year (const char* date_str, int format)
     regcomp (&preg, regex, REG_EXTENDED);
     regexec (&preg, date_str, 3, pmatch, 0);
     regfree (&preg);
-
+    /* Set day, month, and year to today. We'll replace day & month with the
+     * values from the string.
+     */
+    gnc_timespec2dmy(timespec_now(), &day, &month, &year);
     /* If there wasn't a match, there was an error. */
     if (pmatch[0].rm_eo == 0)
         return -1;
 
-    /* Put some sane values in retvalue by using a fixed time for
-     * the non-year-month-day parts of the date. */
-    gnc_time (&rawtime);
-    gnc_localtime_r (&rawtime, &retvalue);
-    retvalue.tm_hour = 11;
-    retvalue.tm_min = 0;
-    retvalue.tm_sec = 0;
-    retvalue.tm_isdst = -1;
-    orig_year = retvalue.tm_year;
-
     /* j traverses pmatch (index 0 contains the entire string, so we
      * start at index 1 for the first meaningful match). */
     j = 1;
@@ -312,37 +273,21 @@ static time64 parse_date_without_year (const char* date_str, int format)
             switch (segment_type)
             {
             case 'm':
-                orig_month = retvalue.tm_mon = atoi (date_segment) - 1;
+                month = atoi (date_segment);
                 break;
 
             case 'd':
-                orig_day = retvalue.tm_mday = atoi (date_segment);
+                day = atoi (date_segment);
                 break;
             }
             g_free (date_segment);
             j++;
         }
     }
-    /* Convert back to an integer. If gnc_mktime leaves retvalue unchanged,
-     * everything is okay; otherwise, an error has occurred. */
-    /* We have to use a "test" date value to account for changes in
-     * daylight savings time, which can cause a date change with gnc_mktime
-     * near midnight, causing the code to incorrectly think a date is
-     * incorrect. */
-    test_retvalue = retvalue;
-    gnc_mktime (&test_retvalue);
-    retvalue.tm_isdst = test_retvalue.tm_isdst;
-    rawtime = gnc_mktime (&retvalue);
-    if (retvalue.tm_mday == orig_day &&
-            retvalue.tm_mon == orig_month &&
-            retvalue.tm_year == orig_year)
-    {
-        return rawtime;
-    }
-    else
-    {
+    if (month > 12 || day > 31)
         return -1;
-    }
+    ts = gnc_dmy2timespec_neutral(day, month, year);
+    return ts.tv_sec;
 }
 
 /** Parses a string into a date, given a format. This function

commit b00694fde4148417813e36502ca6a68dba66454e
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Oct 4 19:59:00 2016 +0200

    Bug 772382 - Date off-by-one after DST change
    
    The time needs to be 10:59, not 11:00: 13 hours after 11:00 is 24:00,
    which is really 00:00 the next day.

diff --git a/src/libqof/qof/gnc-date.cpp b/src/libqof/qof/gnc-date.cpp
index dd0fa56..3867a61 100644
--- a/src/libqof/qof/gnc-date.cpp
+++ b/src/libqof/qof/gnc-date.cpp
@@ -1237,8 +1237,8 @@ gnc_dmy2timespec_neutral (int day, int month, int year)
     date.tm_year = year - 1900;
     date.tm_mon = month - 1;
     date.tm_mday = day;
-    date.tm_hour = 11;
-    date.tm_min = 0;
+    date.tm_hour = 10;
+    date.tm_min = 59;
     date.tm_sec = 0;
 
     GncDateTime gncdt(date);
@@ -1246,7 +1246,7 @@ gnc_dmy2timespec_neutral (int day, int month, int year)
     if (offset < -11)
         date.tm_hour = -offset;
     if (offset > 13)
-        date.tm_hour = 24 - offset;
+        date.tm_hour = 23 - offset;
 
     return {gnc_timegm(&date), 0};
 }
diff --git a/src/libqof/qof/test/test-gnc-date.c b/src/libqof/qof/test/test-gnc-date.c
index dc22b76..8bdf940 100644
--- a/src/libqof/qof/test/test-gnc-date.c
+++ b/src/libqof/qof/test/test-gnc-date.c
@@ -125,10 +125,10 @@ setup_begin(FixtureB *f, gconstpointer pData)
 static void
 setup_neutral(FixtureB *f, gconstpointer pData)
 {
-    f->test[0] = (TimeMap){1999, 7, 21, INT64_C(932554800)};
-    f->test[1] = (TimeMap){1918, 3, 31, INT64_C(-1633266000)};
-    f->test[2] = (TimeMap){1918, 4, 1, INT64_C(-1633179600)};
-    f->test[3] = (TimeMap){2057, 11, 20, INT64_C(2773479600)};
+    f->test[0] = (TimeMap){1999, 7, 21, INT64_C(932554740)};
+    f->test[1] = (TimeMap){1918, 3, 31, INT64_C(-1633266060)};
+    f->test[2] = (TimeMap){1918, 4, 1, INT64_C(-1633179660)};
+    f->test[3] = (TimeMap){2057, 11, 20, INT64_C(2773479540)};
 }
 
 static void



Summary of changes:
 src/import-export/csv-imp/gnc-csv-model.c | 101 +++++++-----------------------
 src/libqof/qof/gnc-date.cpp               |   6 +-
 src/libqof/qof/test/test-gnc-date.c       |   8 +--
 3 files changed, 30 insertions(+), 85 deletions(-)



More information about the gnucash-changes mailing list