mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Merge Bill Nottingham's 'bad-dates' into maint
This commit is contained in:
commit
174752e28c
@ -728,6 +728,32 @@ floordiv(int a, int b)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Normalize the localized date format to avoid date scanning issues.
|
||||||
|
*
|
||||||
|
* The 'O' and 'E' format modifiers are for localized input/output
|
||||||
|
* characters. Remove them as we are always using Arabic numbers.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
normalize_format (const char *format)
|
||||||
|
{
|
||||||
|
gint counter = 0, n_counter = 0;
|
||||||
|
gchar *normalized;
|
||||||
|
|
||||||
|
normalized = g_strdup(format);
|
||||||
|
while (format[counter] != '\0')
|
||||||
|
{
|
||||||
|
normalized[n_counter] = format[counter];
|
||||||
|
if ((format[counter] == '%') && \
|
||||||
|
(format[counter+1] == 'E' || format[counter+1] == 'O'))
|
||||||
|
counter++; // skip format modifier
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
n_counter++;
|
||||||
|
}
|
||||||
|
normalized[n_counter] = '\0';
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert a string into day, month and year integers
|
/* Convert a string into day, month and year integers
|
||||||
|
|
||||||
Convert a string into day / month / year integers according to
|
Convert a string into day / month / year integers according to
|
||||||
@ -820,30 +846,12 @@ qof_scan_date_internal (const char *buff, int *day, int *month, int *year,
|
|||||||
if (buff[0] != '\0')
|
if (buff[0] != '\0')
|
||||||
{
|
{
|
||||||
struct tm thetime;
|
struct tm thetime;
|
||||||
gchar *format = g_strdup (GNC_D_FMT);
|
gchar *normalized_format = normalize_format(GNC_D_FMT);
|
||||||
gchar *stripped_format = g_strdup (GNC_D_FMT);
|
|
||||||
gint counter = 0, stripped_counter = 0;
|
|
||||||
|
|
||||||
/* strptime can't handle the - format modifier
|
|
||||||
* let's strip it out of the format before using it
|
|
||||||
*/
|
|
||||||
while (format[counter] != '\0')
|
|
||||||
{
|
|
||||||
stripped_format[stripped_counter] = format[counter];
|
|
||||||
if ((format[counter] == '%') && (format[counter+1] == '-'))
|
|
||||||
counter++; // skip - format modifier
|
|
||||||
|
|
||||||
counter++;
|
|
||||||
stripped_counter++;
|
|
||||||
}
|
|
||||||
stripped_format[stripped_counter] = '\0';
|
|
||||||
g_free (format);
|
|
||||||
|
|
||||||
|
|
||||||
/* Parse time string. */
|
/* Parse time string. */
|
||||||
memset(&thetime, -1, sizeof(struct tm));
|
memset(&thetime, -1, sizeof(struct tm));
|
||||||
strptime (buff, stripped_format, &thetime);
|
strptime (buff, normalized_format, &thetime);
|
||||||
g_free (stripped_format);
|
g_free (normalized_format);
|
||||||
|
|
||||||
if (third_field)
|
if (third_field)
|
||||||
{
|
{
|
||||||
@ -1037,10 +1045,13 @@ char dateSeparator (void)
|
|||||||
struct tm tm;
|
struct tm tm;
|
||||||
time64 secs;
|
time64 secs;
|
||||||
gchar *s;
|
gchar *s;
|
||||||
|
gchar *normalized_fmt;
|
||||||
|
|
||||||
secs = gnc_time (NULL);
|
secs = gnc_time (NULL);
|
||||||
gnc_localtime_r(&secs, &tm);
|
gnc_localtime_r(&secs, &tm);
|
||||||
qof_strftime(string, sizeof(string), GNC_D_FMT, &tm);
|
normalized_fmt = normalize_format(qof_date_format_get_string(dateFormat));
|
||||||
|
qof_strftime(string, sizeof(string), normalized_fmt, &tm);
|
||||||
|
g_free(normalized_fmt);
|
||||||
|
|
||||||
for (s = string; *s != '\0'; s++)
|
for (s = string; *s != '\0'; s++)
|
||||||
if (!isdigit(*s))
|
if (!isdigit(*s))
|
||||||
|
@ -293,6 +293,30 @@ tz_from_string(std::string str)
|
|||||||
return TZ_Ptr(new PTZ(tzstr));
|
return TZ_Ptr(new PTZ(tzstr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The 'O', 'E', and '-' format modifiers are not supported by
|
||||||
|
* boost's output facets. Remove them.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
normalize_format (const char *format)
|
||||||
|
{
|
||||||
|
int counter = 0, n_counter = 0;
|
||||||
|
char *normalized;
|
||||||
|
|
||||||
|
normalized = strdup(format);
|
||||||
|
while (format[counter] != '\0')
|
||||||
|
{
|
||||||
|
normalized[n_counter] = format[counter];
|
||||||
|
if ((format[counter] == '%') && \
|
||||||
|
(format[counter+1] == '-' || format[counter+1] == 'E' || format[counter+1] == 'O'))
|
||||||
|
counter++; // skip format modifier
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
n_counter++;
|
||||||
|
}
|
||||||
|
normalized[n_counter] = '\0';
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
GncDateTimeImpl::GncDateTimeImpl(std::string str) :
|
GncDateTimeImpl::GncDateTimeImpl(std::string str) :
|
||||||
m_time(unix_epoch, utc_zone)
|
m_time(unix_epoch, utc_zone)
|
||||||
{
|
{
|
||||||
@ -375,9 +399,11 @@ GncDateTimeImpl::format(const char* format) const
|
|||||||
{
|
{
|
||||||
using Facet = boost::local_time::local_time_facet;
|
using Facet = boost::local_time::local_time_facet;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
char *normalized_format = normalize_format(format);
|
||||||
//The stream destructor frees the facet, so it must be heap-allocated.
|
//The stream destructor frees the facet, so it must be heap-allocated.
|
||||||
auto output_facet(new Facet(format));
|
auto output_facet(new Facet(normalized_format));
|
||||||
ss.imbue(std::locale(std::locale(), output_facet));
|
ss.imbue(std::locale(std::locale(), output_facet));
|
||||||
|
free(normalized_format);
|
||||||
ss << m_time;
|
ss << m_time;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
@ -387,9 +413,11 @@ GncDateTimeImpl::format_zulu(const char* format) const
|
|||||||
{
|
{
|
||||||
using Facet = boost::posix_time::time_facet;
|
using Facet = boost::posix_time::time_facet;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
char *normalized_format = normalize_format(format);
|
||||||
//The stream destructor frees the facet, so it must be heap-allocated.
|
//The stream destructor frees the facet, so it must be heap-allocated.
|
||||||
auto output_facet(new Facet(format));
|
auto output_facet(new Facet(normalized_format));
|
||||||
ss.imbue(std::locale(std::locale(), output_facet));
|
ss.imbue(std::locale(std::locale(), output_facet));
|
||||||
|
free(normalized_format);
|
||||||
ss << m_time.utc_time();
|
ss << m_time.utc_time();
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
@ -446,9 +474,11 @@ GncDateImpl::format(const char* format) const
|
|||||||
{
|
{
|
||||||
using Facet = boost::gregorian::date_facet;
|
using Facet = boost::gregorian::date_facet;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
char *normalized_format = normalize_format(format);
|
||||||
//The stream destructor frees the facet, so it must be heap-allocated.
|
//The stream destructor frees the facet, so it must be heap-allocated.
|
||||||
auto output_facet(new Facet(format));
|
auto output_facet(new Facet(normalized_format));
|
||||||
ss.imbue(std::locale(std::locale(), output_facet));
|
ss.imbue(std::locale(std::locale(), output_facet));
|
||||||
|
free(normalized_format);
|
||||||
ss << m_greg;
|
ss << m_greg;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user