diff --git a/libgnucash/backend/sql/gnc-sql-column-table-entry.cpp b/libgnucash/backend/sql/gnc-sql-column-table-entry.cpp index e48c1657a3..1c300066aa 100644 --- a/libgnucash/backend/sql/gnc-sql-column-table-entry.cpp +++ b/libgnucash/backend/sql/gnc-sql-column-table-entry.cpp @@ -448,8 +448,9 @@ GncSqlColumnTableEntryImpl::add_to_query(QofIdTypeConst obj_name, if (t64 > MINTIME && t64 < MAXTIME) { GncDateTime time(t64); - vec.emplace_back (std::make_pair (std::string{m_col_name}, - time.format_zulu ("'%Y-%m-%d %H:%M:%S'"))); + std::string timestr("'"); + timestr += time.format_iso8601() + "'"; + vec.emplace_back (std::make_pair (std::string{m_col_name}, timestr)); } else { diff --git a/libgnucash/backend/sql/gnc-transaction-sql.cpp b/libgnucash/backend/sql/gnc-transaction-sql.cpp index 9867577f97..fce7f6c5c1 100644 --- a/libgnucash/backend/sql/gnc-transaction-sql.cpp +++ b/libgnucash/backend/sql/gnc-transaction-sql.cpp @@ -853,7 +853,7 @@ convert_query_term_to_sql (const GncSqlBackend* sql_be, const gchar* fieldName, query_date_t date_data = (query_date_t)pPredData; GncDateTime time(date_data->date); - sql << time.format_zulu ("%Y-%m-%d %H:%M:%S"); + sql << time.format_iso8601(); } else if (strcmp (pPredData->type_name, QOF_TYPE_INT32) == 0) { diff --git a/libgnucash/backend/xml/sixtp-dom-generators.cpp b/libgnucash/backend/xml/sixtp-dom-generators.cpp index 6cdf40526a..4ddd0bf4c9 100644 --- a/libgnucash/backend/xml/sixtp-dom-generators.cpp +++ b/libgnucash/backend/xml/sixtp-dom-generators.cpp @@ -35,6 +35,7 @@ extern "C" #include "sixtp-utils.h" #include +#include static QofLogModule log_module = GNC_MOD_IO; @@ -136,13 +137,12 @@ time64_to_dom_tree (const char* tag, const time64 time) { xmlNodePtr ret; g_return_val_if_fail (time != INT64_MAX, NULL); - auto date_str = gnc_print_time64 (time, "%Y-%m-%d %H:%M:%S %q"); - if (!date_str) + auto date_str = GncDateTime(time).format_iso8601(); + if (date_str.empty()) return NULL; ret = xmlNewNode (NULL, BAD_CAST tag); xmlNewTextChild (ret, NULL, BAD_CAST "ts:date", - checked_char_cast (date_str)); - g_free (date_str); + checked_char_cast (const_cast(date_str.c_str()))); return ret; } diff --git a/libgnucash/engine/gnc-date.cpp b/libgnucash/engine/gnc-date.cpp index 756d12c3af..cacc35f8e8 100644 --- a/libgnucash/engine/gnc-date.cpp +++ b/libgnucash/engine/gnc-date.cpp @@ -1115,13 +1115,12 @@ char * gnc_time64_to_iso8601_buff (time64 time, char * buff) { constexpr size_t max_iso_date_length = 32; - const char* format = "%Y-%m-%d %H:%M:%S %q"; if (! buff) return NULL; try { GncDateTime gncdt(time); - auto sstr = gncdt.format(format); + auto sstr = gncdt.format_iso8601(); memset(buff, 0, sstr.length() + 1); strncpy(buff, sstr.c_str(), sstr.length()); diff --git a/libgnucash/engine/gnc-datetime.cpp b/libgnucash/engine/gnc-datetime.cpp index 238be2db61..70d927537c 100644 --- a/libgnucash/engine/gnc-datetime.cpp +++ b/libgnucash/engine/gnc-datetime.cpp @@ -235,6 +235,7 @@ public: std::unique_ptr date() const; std::string format(const char* format) const; std::string format_zulu(const char* format) const; + std::string format_iso8601() const; private: LDT m_time; static const TD time_of_day[3]; @@ -457,6 +458,14 @@ GncDateTimeImpl::format_zulu(const char* format) const return ss.str(); } +std::string +GncDateTimeImpl::format_iso8601() const +{ + auto str = boost::posix_time::to_iso_extended_string(m_time.utc_time()); + str[10] = ' '; + return str.substr(0, 19); +} + /* Member function definitions for GncDateImpl. */ GncDateImpl::GncDateImpl(const std::string str, const std::string fmt) : @@ -585,6 +594,12 @@ GncDateTime::format_zulu(const char* format) const return m_impl->format_zulu(format); } +std::string +GncDateTime::format_iso8601() const +{ + return m_impl->format_iso8601(); +} + /* GncDate */ GncDate::GncDate() : m_impl{new GncDateImpl} {} GncDate::GncDate(int year, int month, int day) : diff --git a/libgnucash/engine/gnc-datetime.hpp b/libgnucash/engine/gnc-datetime.hpp index 27b7e83b07..8f714f598b 100644 --- a/libgnucash/engine/gnc-datetime.hpp +++ b/libgnucash/engine/gnc-datetime.hpp @@ -148,6 +148,10 @@ public: * GMT (timezone Z) according to the format. */ std::string format_zulu(const char* format) const; +/** Format the GncDateTime into a gnucash-style iso8601 string in UTC. + * @return a std::string in the format YYYY-MM-DD HH:MM:SS. + */ + std::string format_iso8601() const; private: std::unique_ptr m_impl; diff --git a/libgnucash/engine/test/test-gnc-date.c b/libgnucash/engine/test/test-gnc-date.c index 2c385654e7..a1f1e9cb10 100644 --- a/libgnucash/engine/test/test-gnc-date.c +++ b/libgnucash/engine/test/test-gnc-date.c @@ -1407,20 +1407,15 @@ static gchar* format_timestring (time64 t, TZOffset tz) { static const unsigned tzlen = MAX_DATE_LENGTH - 26; - char *fmt = "%Y-%m-%d %H:%M:%S %z"; - struct tm tm; + char *fmt = "%Y-%m-%d %H:%M:%S"; + struct tm *tm; char buf[MAX_DATE_LENGTH + 1]; char tzbuf[tzlen]; memset(tzbuf, 0, sizeof(tzbuf)); - gnc_localtime_r(&t, &tm); -#if PLATFORM(WINDOWS) - strftime(tzbuf, sizeof(tzbuf), "%Z", &tm); -#else - strftime(tzbuf, sizeof(tzbuf), "%z", &tm); -#endif + tm = gnc_gmtime(&t); memset (buf, 0, sizeof(buf)); - strftime(buf, sizeof(buf), fmt, &tm); - + strftime(buf, sizeof(buf), fmt, tm); + free(tm); return g_strdup(buf); }