diff --git a/CMakeLists.txt b/CMakeLists.txt index 0664d9f4e6..a626cf13be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -376,7 +376,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 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -Wall -Wunused -Wmissing-prototypes -Wmissing-declarations -Wno-unused") - SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=deprecated-declarations -std=gnu99 -O2") + SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=deprecated-declarations -std=gnu99") ENDIF (UNIX) IF (MINGW) SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wdeclaration-after-statement -Wno-pointer-sign -Wall -Wunused -Wmissing-prototypes -Wmissing-declarations -Wno-unused -std=gnu99") diff --git a/src/backend/sql/gnc-transaction-sql.cpp b/src/backend/sql/gnc-transaction-sql.cpp index a3d93dce23..5d6f6d78e8 100644 --- a/src/backend/sql/gnc-transaction-sql.cpp +++ b/src/backend/sql/gnc-transaction-sql.cpp @@ -38,6 +38,7 @@ extern "C" #include "Account.h" #include "Transaction.h" +#include #include "gnc-lot.h" #include "engine-helpers.h" #include "gnc-commodity.h" @@ -371,6 +372,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.cpp b/src/backend/xml/io-gncxml-v2.cpp index 61de9d223d..920fe8ddfc 100644 --- a/src/backend/xml/io-gncxml-v2.cpp +++ b/src/backend/xml/io-gncxml-v2.cpp @@ -287,6 +287,7 @@ add_transaction_local (sixtp_gdv2* data, Transaction* trn) xaccTransSetCurrency); xaccTransScrubCurrency (trn); + xaccTransScrubPostedDate (trn); xaccTransCommitEdit (trn); data->counter.transactions_loaded++; diff --git a/src/business/business-ledger/gncEntryLedgerLoad.c b/src/business/business-ledger/gncEntryLedgerLoad.c index eeac11ff19..c277836b85 100644 --- a/src/business/business-ledger/gncEntryLedgerLoad.c +++ b/src/business/business-ledger/gncEntryLedgerLoad.c @@ -451,6 +451,7 @@ void gnc_entry_ledger_load (GncEntryLedger *ledger, GList *entry_list) if (ledger->is_cust_doc) { + gncEntrySetInvTaxable (blank_entry, table != NULL); gncEntrySetInvTaxTable (blank_entry, table); gncEntrySetInvTaxIncluded (blank_entry, taxincluded); gncEntrySetInvDiscount (blank_entry, discount); @@ -458,6 +459,7 @@ void gnc_entry_ledger_load (GncEntryLedger *ledger, GList *entry_list) } else { + gncEntrySetBillTaxable (blank_entry, table != NULL); gncEntrySetBillTaxTable (blank_entry, table); gncEntrySetBillTaxIncluded (blank_entry, taxincluded); gncEntrySetBillPrice (blank_entry, price); diff --git a/src/engine/Scrub.c b/src/engine/Scrub.c index ad29626e41..136cf853e6 100644 --- a/src/engine/Scrub.c +++ b/src/engine/Scrub.c @@ -1374,4 +1374,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 82d5e2d8ac..efdad1b0e7 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.cpp b/src/libqof/qof/gnc-date.cpp index 18f7405bae..dd0fa56527 100644 --- a/src/libqof/qof/gnc-date.cpp +++ b/src/libqof/qof/gnc-date.cpp @@ -226,7 +226,6 @@ gnc_timegm (struct tm* time) { return 0; } - } char* @@ -1217,6 +1216,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) { @@ -1229,6 +1229,27 @@ 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; + memset (&date, 0, sizeof(struct tm)); + date.tm_year = year - 1900; + date.tm_mon = month - 1; + date.tm_mday = day; + date.tm_hour = 11; + date.tm_min = 0; + date.tm_sec = 0; + + GncDateTime gncdt(date); + auto offset = gncdt.offset() / 3600; + if (offset < -11) + date.tm_hour = -offset; + if (offset > 13) + date.tm_hour = 24 - offset; + + return {gnc_timegm(&date), 0}; +} /********************************************************************\ \********************************************************************/ void @@ -1283,9 +1304,9 @@ GDate* gnc_g_date_new_today () Timespec gdate_to_timespec (GDate 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 6034151e14..6a54e27124 100644 --- a/src/libqof/qof/gnc-date.h +++ b/src/libqof/qof/gnc-date.h @@ -341,6 +341,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 712a8f27d1..037ade6014 100644 --- a/src/libqof/qof/test/test-gnc-date.c +++ b/src/libqof/qof/test/test-gnc-date.c @@ -122,6 +122,15 @@ setup_begin(FixtureB *f, gconstpointer pData) f->test[3] = (TimeMap){2057, 11, 20, INT64_C(2773440000)}; } +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)}; +} + static void setup_end(FixtureB *f, gconstpointer pData) { @@ -1825,6 +1834,19 @@ test_gnc_dmy2timespec_end (FixtureB *f, gconstpointer pData) } } +/*gnc_dmy2timespec_neutral*/ +static void +test_gnc_dmy2timespec_neutral (FixtureB *f, gconstpointer pData) +{ + for (int i = 0; i < sizeof(f->test)/sizeof(TimeMap); ++i) + { + Timespec r_t = gnc_dmy2timespec_neutral (f->test[i].day, f->test[i].mon, + f->test[i].yr); + + g_assert_cmpint (r_t.tv_sec, ==, f->test[i].secs); + } +} + /* gnc_timezone long int gnc_timezone (const struct tm *tm)// C: 5 in 2 Local: 2:0:0 @@ -1913,20 +1935,12 @@ test_gdate_to_timespec (FixtureB *f, gconstpointer pData) { for (int i = 0; i < sizeof(f->test)/sizeof(TimeMap); ++i) { -#ifdef HAVE_STRUCT_TM_GMTOFF - struct tm tm = {0, 0, 0, f->test[i].day, f->test[i].mon - 1, - f->test[i].yr - 1900, 0, 0, -1, 0, NULL}; -#else - struct tm tm = {0, 0, 0, f->test[i].day, f->test[i].mon - 1, - f->test[i].yr - 1900, 0, 0, -1}; -#endif GDate gd; Timespec r_t; - int offset = gnc_mktime(&tm) - gnc_timegm(&tm); g_date_clear(&gd, 1); g_date_set_dmy(&gd, f->test[i].day, f->test[i].mon, f->test[i].yr); r_t = gdate_to_timespec(gd); - g_assert_cmpint (r_t.tv_sec, ==, f->test[i].secs + offset); + g_assert_cmpint (r_t.tv_sec, ==, f->test[i].secs); } } /* gnc_tm_get_day_start @@ -2158,14 +2172,16 @@ test_suite_gnc_date (void) GNC_TEST_ADD (suitename, "gnc timespec to iso8601 buff", FixtureA, NULL, setup, test_gnc_timespec_to_iso8601_buff, NULL); GNC_TEST_ADD (suitename, "gnc timespec2dmy", FixtureA, NULL, setup, test_gnc_timespec2dmy, NULL); // GNC_TEST_ADD_FUNC (suitename, "gnc dmy2timespec internal", test_gnc_dmy2timespec_internal); + GNC_TEST_ADD (suitename, "gnc dmy2timespec", FixtureB, NULL, setup_begin, test_gnc_dmy2timespec, NULL); GNC_TEST_ADD (suitename, "gnc dmy2timespec end", FixtureB, NULL, setup_end, test_gnc_dmy2timespec_end, NULL); + GNC_TEST_ADD (suitename, "gnc dmy2timespec Neutral", FixtureB, NULL, setup_neutral, test_gnc_dmy2timespec_neutral, NULL); // 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); // GNC_TEST_ADD_FUNC (suitename, "timespecToTime t", test_timespecTotime64); GNC_TEST_ADD (suitename, "timespec to gdate", FixtureA, NULL, setup, test_timespec_to_gdate, NULL); - GNC_TEST_ADD (suitename, "gdate to timespec", FixtureB, NULL, setup_begin, test_gdate_to_timespec, NULL); + GNC_TEST_ADD (suitename, "gdate to timespec", FixtureB, NULL, setup_neutral, test_gdate_to_timespec, NULL); // GNC_TEST_ADD_FUNC (suitename, "gnc tm get day start", test_gnc_tm_get_day_start); // GNC_TEST_ADD_FUNC (suitename, "gnc tm get day end", test_gnc_tm_get_day_end); GNC_TEST_ADD (suitename, "gnc time64 get day start", FixtureA, NULL, setup, test_gnc_time64_get_day_start, NULL);