mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-23 22:16:16 +01:00
g_date_time_format: fix output in non-UTF-8 locales
In non-UTF-8 locales, the translations and nl_langinfo() return values must be converted to UTF-8 before being returned to the caller. Likewise, when making a recursive call to expand a format like '%x', the format string must first be converted to UTF-8. https://bugzilla.gnome.org/show_bug.cgi?id=668250
This commit is contained in:
parent
9fa374ccf7
commit
b6a8dec558
26
configure.ac
26
configure.ac
@ -1305,24 +1305,24 @@ if test x$glib_cv_langinfo_time = xyes; then
|
||||
AC_DEFINE(HAVE_LANGINFO_TIME,1,[Have nl_langinfo (PM_STR)])
|
||||
fi
|
||||
|
||||
dnl Check for nl_langinfo and _NL_CTYPE_OUTDIGITn_WC
|
||||
AC_CACHE_CHECK([for nl_langinfo (_NL_CTYPE_OUTDIGITn_WC)], glib_cv_langinfo_outdigit,[
|
||||
dnl Check for nl_langinfo and _NL_CTYPE_OUTDIGITn_MB
|
||||
AC_CACHE_CHECK([for nl_langinfo (_NL_CTYPE_OUTDIGITn_MB)], glib_cv_langinfo_outdigit,[
|
||||
AC_TRY_COMPILE([#include <langinfo.h>],
|
||||
[char *str;
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT0_WC);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT1_WC);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT2_WC);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT3_WC);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT4_WC);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT5_WC);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT6_WC);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT7_WC);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT8_WC);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT9_WC);],
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT0_MB);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT1_MB);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT2_MB);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT3_MB);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT4_MB);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT5_MB);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT6_MB);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT7_MB);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT8_MB);
|
||||
str = nl_langinfo (_NL_CTYPE_OUTDIGIT9_MB);],
|
||||
[glib_cv_langinfo_outdigit=yes],
|
||||
[glib_cv_langinfo_outdigit=no])])
|
||||
if test x$glib_cv_langinfo_outdigit = xyes; then
|
||||
AC_DEFINE(HAVE_LANGINFO_OUTDIGIT,1,[Have nl_langinfo (_NL_CTYPE_OUTDIGITn_WC)])
|
||||
AC_DEFINE(HAVE_LANGINFO_OUTDIGIT,1,[Have nl_langinfo (_NL_CTYPE_OUTDIGITn_MB)])
|
||||
fi
|
||||
|
||||
dnl ****************************************
|
||||
|
574
glib/gdatetime.c
574
glib/gdatetime.c
@ -62,6 +62,8 @@
|
||||
|
||||
#include "gslice.h"
|
||||
#include "gatomic.h"
|
||||
#include "gcharset.h"
|
||||
#include "gconvert.h"
|
||||
#include "gfileutils.h"
|
||||
#include "ghash.h"
|
||||
#include "gmain.h"
|
||||
@ -2083,15 +2085,15 @@ g_date_time_to_utc (GDateTime *datetime)
|
||||
static void
|
||||
format_number (GString *str,
|
||||
gboolean use_alt_digits,
|
||||
gchar pad,
|
||||
gchar *pad,
|
||||
gint width,
|
||||
guint32 number)
|
||||
{
|
||||
const gunichar ascii_digits[10] = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
|
||||
const gchar *ascii_digits[10] = {
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
|
||||
};
|
||||
const gunichar *digits = ascii_digits;
|
||||
gunichar tmp[10];
|
||||
const gchar **digits = ascii_digits;
|
||||
const gchar *tmp[10];
|
||||
gint i = 0;
|
||||
|
||||
g_return_if_fail (width <= 10);
|
||||
@ -2099,18 +2101,14 @@ format_number (GString *str,
|
||||
#ifdef HAVE_LANGINFO_OUTDIGIT
|
||||
if (use_alt_digits)
|
||||
{
|
||||
static gunichar alt_digits[10];
|
||||
static const gchar *alt_digits[10];
|
||||
static gsize initialised;
|
||||
/* 2^32 has 10 digits */
|
||||
|
||||
if G_UNLIKELY (g_once_init_enter (&initialised))
|
||||
{
|
||||
#define DO_DIGIT(n) \
|
||||
{ \
|
||||
union { guint integer; char *pointer; } val; \
|
||||
val.pointer = nl_langinfo (_NL_CTYPE_OUTDIGIT## n ##_WC); \
|
||||
alt_digits[n] = val.integer; \
|
||||
}
|
||||
alt_digits[n] = nl_langinfo (_NL_CTYPE_OUTDIGIT## n ##_MB)
|
||||
DO_DIGIT(0); DO_DIGIT(1); DO_DIGIT(2); DO_DIGIT(3); DO_DIGIT(4);
|
||||
DO_DIGIT(5); DO_DIGIT(6); DO_DIGIT(7); DO_DIGIT(8); DO_DIGIT(9);
|
||||
#undef DO_DIGIT
|
||||
@ -2129,13 +2127,330 @@ format_number (GString *str,
|
||||
while (number);
|
||||
|
||||
while (pad && i < width)
|
||||
tmp[i++] = pad == '0' ? digits[0] : pad;
|
||||
tmp[i++] = *pad == '0' ? digits[0] : pad;
|
||||
|
||||
/* should really be impossible */
|
||||
g_assert (i <= 10);
|
||||
|
||||
while (i)
|
||||
g_string_append_unichar (str, tmp[--i]);
|
||||
g_string_append (str, tmp[--i]);
|
||||
}
|
||||
|
||||
static gboolean g_date_time_format_locale (GDateTime *datetime,
|
||||
const gchar *format,
|
||||
GString *outstr,
|
||||
gboolean locale_is_utf8);
|
||||
|
||||
/* g_date_time_format() subroutine that takes a locale-encoded format
|
||||
* string and produces a locale-encoded date/time string.
|
||||
*/
|
||||
static gboolean
|
||||
g_date_time_locale_format_locale (GDateTime *datetime,
|
||||
const gchar *format,
|
||||
GString *outstr,
|
||||
gboolean locale_is_utf8)
|
||||
{
|
||||
gchar *utf8_format;
|
||||
gboolean success;
|
||||
|
||||
if (locale_is_utf8)
|
||||
return g_date_time_format_locale (datetime, format, outstr,
|
||||
locale_is_utf8);
|
||||
|
||||
utf8_format = g_locale_to_utf8 (format, -1, NULL, NULL, NULL);
|
||||
if (!utf8_format)
|
||||
return FALSE;
|
||||
|
||||
success = g_date_time_format_locale (datetime, utf8_format, outstr,
|
||||
locale_is_utf8);
|
||||
g_free (utf8_format);
|
||||
return success;
|
||||
}
|
||||
|
||||
/* g_date_time_format() subroutine that takes a UTF-8 format
|
||||
* string and produces a locale-encoded date/time string.
|
||||
*/
|
||||
static gboolean
|
||||
g_date_time_format_locale (GDateTime *datetime,
|
||||
const gchar *format,
|
||||
GString *outstr,
|
||||
gboolean locale_is_utf8)
|
||||
{
|
||||
guint len;
|
||||
gchar *tmp;
|
||||
gunichar c;
|
||||
gboolean alt_digits = FALSE;
|
||||
gboolean pad_set = FALSE;
|
||||
gchar *pad = "";
|
||||
gchar *ampm;
|
||||
const gchar *tz;
|
||||
|
||||
while (*format)
|
||||
{
|
||||
len = strcspn (format, "%");
|
||||
if (len)
|
||||
{
|
||||
if (locale_is_utf8)
|
||||
g_string_append_len (outstr, format, len);
|
||||
else
|
||||
{
|
||||
tmp = g_locale_from_utf8 (format, len, NULL, NULL, NULL);
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
g_string_append (outstr, tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
}
|
||||
|
||||
format += len;
|
||||
if (!*format)
|
||||
break;
|
||||
|
||||
g_assert (*format == '%');
|
||||
format++;
|
||||
if (!*format)
|
||||
break;
|
||||
|
||||
alt_digits = FALSE;
|
||||
pad_set = FALSE;
|
||||
|
||||
next_mod:
|
||||
c = g_utf8_get_char (format);
|
||||
format = g_utf8_next_char (format);
|
||||
switch (c)
|
||||
{
|
||||
case 'a':
|
||||
g_string_append (outstr, WEEKDAY_ABBR (datetime));
|
||||
break;
|
||||
case 'A':
|
||||
g_string_append (outstr, WEEKDAY_FULL (datetime));
|
||||
break;
|
||||
case 'b':
|
||||
g_string_append (outstr, MONTH_ABBR (datetime));
|
||||
break;
|
||||
case 'B':
|
||||
g_string_append (outstr, MONTH_FULL (datetime));
|
||||
break;
|
||||
case 'c':
|
||||
{
|
||||
if (!g_date_time_locale_format_locale (datetime, PREFERRED_DATE_TIME_FMT,
|
||||
outstr, locale_is_utf8))
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
|
||||
g_date_time_get_year (datetime) / 100);
|
||||
break;
|
||||
case 'd':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
|
||||
g_date_time_get_day_of_month (datetime));
|
||||
break;
|
||||
case 'e':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : " ", 2,
|
||||
g_date_time_get_day_of_month (datetime));
|
||||
break;
|
||||
case 'F':
|
||||
g_string_append_printf (outstr, "%d-%02d-%02d",
|
||||
g_date_time_get_year (datetime),
|
||||
g_date_time_get_month (datetime),
|
||||
g_date_time_get_day_of_month (datetime));
|
||||
break;
|
||||
case 'g':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
|
||||
g_date_time_get_week_numbering_year (datetime) % 100);
|
||||
break;
|
||||
case 'G':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : 0, 0,
|
||||
g_date_time_get_week_numbering_year (datetime));
|
||||
break;
|
||||
case 'h':
|
||||
g_string_append (outstr, MONTH_ABBR (datetime));
|
||||
break;
|
||||
case 'H':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
|
||||
g_date_time_get_hour (datetime));
|
||||
break;
|
||||
case 'I':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
|
||||
(g_date_time_get_hour (datetime) + 11) % 12 + 1);
|
||||
break;
|
||||
case 'j':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : "0", 3,
|
||||
g_date_time_get_day_of_year (datetime));
|
||||
break;
|
||||
case 'k':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : " ", 2,
|
||||
g_date_time_get_hour (datetime));
|
||||
break;
|
||||
case 'l':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : " ", 2,
|
||||
(g_date_time_get_hour (datetime) + 11) % 12 + 1);
|
||||
break;
|
||||
case 'n':
|
||||
g_string_append_c (outstr, '\n');
|
||||
break;
|
||||
case 'm':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
|
||||
g_date_time_get_month (datetime));
|
||||
break;
|
||||
case 'M':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
|
||||
g_date_time_get_minute (datetime));
|
||||
break;
|
||||
case 'O':
|
||||
alt_digits = TRUE;
|
||||
goto next_mod;
|
||||
case 'p':
|
||||
ampm = GET_AMPM (datetime);
|
||||
if (!locale_is_utf8)
|
||||
{
|
||||
ampm = tmp = g_locale_to_utf8 (ampm, -1, NULL, NULL, NULL);
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
}
|
||||
ampm = g_utf8_strup (ampm, -1);
|
||||
if (!locale_is_utf8)
|
||||
{
|
||||
g_free (tmp);
|
||||
tmp = g_locale_from_utf8 (ampm, -1, NULL, NULL, NULL);
|
||||
g_free (ampm);
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
ampm = tmp;
|
||||
}
|
||||
g_string_append (outstr, ampm);
|
||||
g_free (ampm);
|
||||
break;
|
||||
case 'P':
|
||||
ampm = GET_AMPM (datetime);
|
||||
if (!locale_is_utf8)
|
||||
{
|
||||
ampm = tmp = g_locale_to_utf8 (ampm, -1, NULL, NULL, NULL);
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
}
|
||||
ampm = g_utf8_strdown (ampm, -1);
|
||||
if (!locale_is_utf8)
|
||||
{
|
||||
g_free (tmp);
|
||||
tmp = g_locale_from_utf8 (ampm, -1, NULL, NULL, NULL);
|
||||
g_free (ampm);
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
ampm = tmp;
|
||||
}
|
||||
g_string_append (outstr, ampm);
|
||||
g_free (ampm);
|
||||
break;
|
||||
case 'r':
|
||||
{
|
||||
if (!g_date_time_locale_format_locale (datetime, PREFERRED_12HR_TIME_FMT,
|
||||
outstr, locale_is_utf8))
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
g_string_append_printf (outstr, "%02d:%02d",
|
||||
g_date_time_get_hour (datetime),
|
||||
g_date_time_get_minute (datetime));
|
||||
break;
|
||||
case 's':
|
||||
g_string_append_printf (outstr, "%" G_GINT64_FORMAT, g_date_time_to_unix (datetime));
|
||||
break;
|
||||
case 'S':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
|
||||
g_date_time_get_second (datetime));
|
||||
break;
|
||||
case 't':
|
||||
g_string_append_c (outstr, '\t');
|
||||
break;
|
||||
case 'T':
|
||||
g_string_append_printf (outstr, "%02d:%02d:%02d",
|
||||
g_date_time_get_hour (datetime),
|
||||
g_date_time_get_minute (datetime),
|
||||
g_date_time_get_second (datetime));
|
||||
break;
|
||||
case 'u':
|
||||
format_number (outstr, alt_digits, 0, 0,
|
||||
g_date_time_get_day_of_week (datetime));
|
||||
break;
|
||||
case 'V':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
|
||||
g_date_time_get_week_of_year (datetime));
|
||||
break;
|
||||
case 'w':
|
||||
format_number (outstr, alt_digits, 0, 0,
|
||||
g_date_time_get_day_of_week (datetime) % 7);
|
||||
break;
|
||||
case 'x':
|
||||
{
|
||||
if (!g_date_time_locale_format_locale (datetime, PREFERRED_DATE_FMT,
|
||||
outstr, locale_is_utf8))
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case 'X':
|
||||
{
|
||||
if (!g_date_time_locale_format_locale (datetime, PREFERRED_TIME_FMT,
|
||||
outstr, locale_is_utf8))
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case 'y':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
|
||||
g_date_time_get_year (datetime) % 100);
|
||||
break;
|
||||
case 'Y':
|
||||
format_number (outstr, alt_digits, 0, 0,
|
||||
g_date_time_get_year (datetime));
|
||||
break;
|
||||
case 'z':
|
||||
if (datetime->tz != NULL)
|
||||
{
|
||||
gint64 offset = g_date_time_get_utc_offset (datetime)
|
||||
/ USEC_PER_SECOND;
|
||||
|
||||
g_string_append_printf (outstr, "%+03d%02d",
|
||||
(int) offset / 3600,
|
||||
(int) abs(offset) / 60 % 60);
|
||||
}
|
||||
else
|
||||
g_string_append (outstr, "+0000");
|
||||
break;
|
||||
case 'Z':
|
||||
tz = g_date_time_get_timezone_abbreviation (datetime);
|
||||
if (!locale_is_utf8)
|
||||
{
|
||||
tz = tmp = g_locale_from_utf8 (tz, -1, NULL, NULL, NULL);
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
}
|
||||
g_string_append (outstr, tz);
|
||||
if (!locale_is_utf8)
|
||||
g_free (tmp);
|
||||
break;
|
||||
case '%':
|
||||
g_string_append_c (outstr, '%');
|
||||
break;
|
||||
case '-':
|
||||
pad_set = TRUE;
|
||||
pad = "";
|
||||
goto next_mod;
|
||||
case '_':
|
||||
pad_set = TRUE;
|
||||
pad = " ";
|
||||
goto next_mod;
|
||||
case '0':
|
||||
pad_set = TRUE;
|
||||
pad = "0";
|
||||
goto next_mod;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2411,242 +2726,27 @@ g_date_time_format (GDateTime *datetime,
|
||||
const gchar *format)
|
||||
{
|
||||
GString *outstr;
|
||||
gchar *tmp;
|
||||
gunichar c;
|
||||
gboolean in_mod = FALSE;
|
||||
gboolean alt_digits = FALSE;
|
||||
gboolean pad_set = FALSE;
|
||||
gchar pad = '\0';
|
||||
gchar *ampm;
|
||||
gchar *utf8;
|
||||
gboolean locale_is_utf8 = g_get_charset (NULL);
|
||||
|
||||
g_return_val_if_fail (datetime != NULL, NULL);
|
||||
g_return_val_if_fail (format != NULL, NULL);
|
||||
g_return_val_if_fail (g_utf8_validate (format, -1, NULL), NULL);
|
||||
|
||||
outstr = g_string_sized_new (strlen (format) * 2);
|
||||
in_mod = FALSE;
|
||||
|
||||
for (; *format; format = g_utf8_next_char (format))
|
||||
if (!g_date_time_format_locale (datetime, format, outstr, locale_is_utf8))
|
||||
{
|
||||
c = g_utf8_get_char (format);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '%':
|
||||
if (!in_mod)
|
||||
{
|
||||
in_mod = TRUE;
|
||||
alt_digits = FALSE;
|
||||
pad_set = FALSE;
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
if (in_mod)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'a':
|
||||
g_string_append (outstr, WEEKDAY_ABBR (datetime));
|
||||
break;
|
||||
case 'A':
|
||||
g_string_append (outstr, WEEKDAY_FULL (datetime));
|
||||
break;
|
||||
case 'b':
|
||||
g_string_append (outstr, MONTH_ABBR (datetime));
|
||||
break;
|
||||
case 'B':
|
||||
g_string_append (outstr, MONTH_FULL (datetime));
|
||||
break;
|
||||
case 'c':
|
||||
{
|
||||
tmp = g_date_time_format (datetime, PREFERRED_DATE_TIME_FMT);
|
||||
g_string_append (outstr, tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
|
||||
g_date_time_get_year (datetime) / 100);
|
||||
break;
|
||||
case 'd':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
|
||||
g_date_time_get_day_of_month (datetime));
|
||||
break;
|
||||
case 'e':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : ' ', 2,
|
||||
g_date_time_get_day_of_month (datetime));
|
||||
break;
|
||||
case 'F':
|
||||
g_string_append_printf (outstr, "%d-%02d-%02d",
|
||||
g_date_time_get_year (datetime),
|
||||
g_date_time_get_month (datetime),
|
||||
g_date_time_get_day_of_month (datetime));
|
||||
break;
|
||||
case 'g':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
|
||||
g_date_time_get_week_numbering_year (datetime) % 100);
|
||||
break;
|
||||
case 'G':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : 0, 0,
|
||||
g_date_time_get_week_numbering_year (datetime));
|
||||
break;
|
||||
case 'h':
|
||||
g_string_append (outstr, MONTH_ABBR (datetime));
|
||||
break;
|
||||
case 'H':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
|
||||
g_date_time_get_hour (datetime));
|
||||
break;
|
||||
case 'I':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
|
||||
(g_date_time_get_hour (datetime) + 11) % 12 + 1);
|
||||
break;
|
||||
case 'j':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : '0', 3,
|
||||
g_date_time_get_day_of_year (datetime));
|
||||
break;
|
||||
case 'k':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : ' ', 2,
|
||||
g_date_time_get_hour (datetime));
|
||||
break;
|
||||
case 'l':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : ' ', 2,
|
||||
(g_date_time_get_hour (datetime) + 11) % 12 + 1);
|
||||
break;
|
||||
case 'n':
|
||||
g_string_append_c (outstr, '\n');
|
||||
break;
|
||||
case 'm':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
|
||||
g_date_time_get_month (datetime));
|
||||
break;
|
||||
case 'M':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
|
||||
g_date_time_get_minute (datetime));
|
||||
break;
|
||||
case 'O':
|
||||
alt_digits = TRUE;
|
||||
goto next_mod;
|
||||
case 'p':
|
||||
ampm = g_utf8_strup (GET_AMPM (datetime), -1);
|
||||
g_string_append (outstr, ampm);
|
||||
g_free (ampm);
|
||||
break;
|
||||
case 'P':
|
||||
ampm = g_utf8_strdown (GET_AMPM (datetime), -1);
|
||||
g_string_append (outstr, ampm);
|
||||
g_free (ampm);
|
||||
break;
|
||||
case 'r':
|
||||
{
|
||||
tmp = g_date_time_format (datetime, PREFERRED_12HR_TIME_FMT);
|
||||
g_string_append (outstr, tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
g_string_append_printf (outstr, "%02d:%02d",
|
||||
g_date_time_get_hour (datetime),
|
||||
g_date_time_get_minute (datetime));
|
||||
break;
|
||||
case 's':
|
||||
g_string_append_printf (outstr, "%" G_GINT64_FORMAT, g_date_time_to_unix (datetime));
|
||||
break;
|
||||
case 'S':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
|
||||
g_date_time_get_second (datetime));
|
||||
break;
|
||||
case 't':
|
||||
g_string_append_c (outstr, '\t');
|
||||
break;
|
||||
case 'T':
|
||||
g_string_append_printf (outstr, "%02d:%02d:%02d",
|
||||
g_date_time_get_hour (datetime),
|
||||
g_date_time_get_minute (datetime),
|
||||
g_date_time_get_second (datetime));
|
||||
break;
|
||||
case 'u':
|
||||
format_number (outstr, alt_digits, 0, 0,
|
||||
g_date_time_get_day_of_week (datetime));
|
||||
break;
|
||||
case 'V':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
|
||||
g_date_time_get_week_of_year (datetime));
|
||||
break;
|
||||
case 'w':
|
||||
format_number (outstr, alt_digits, 0, 0,
|
||||
g_date_time_get_day_of_week (datetime) % 7);
|
||||
break;
|
||||
case 'x':
|
||||
{
|
||||
tmp = g_date_time_format (datetime, PREFERRED_DATE_FMT);
|
||||
g_string_append (outstr, tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
break;
|
||||
case 'X':
|
||||
{
|
||||
tmp = g_date_time_format (datetime, PREFERRED_TIME_FMT);
|
||||
g_string_append (outstr, tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
break;
|
||||
case 'y':
|
||||
format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
|
||||
g_date_time_get_year (datetime) % 100);
|
||||
break;
|
||||
case 'Y':
|
||||
format_number (outstr, alt_digits, 0, 0,
|
||||
g_date_time_get_year (datetime));
|
||||
break;
|
||||
case 'z':
|
||||
if (datetime->tz != NULL)
|
||||
{
|
||||
gint64 offset = g_date_time_get_utc_offset (datetime)
|
||||
/ USEC_PER_SECOND;
|
||||
|
||||
g_string_append_printf (outstr, "%+03d%02d",
|
||||
(int) offset / 3600,
|
||||
(int) abs(offset) / 60 % 60);
|
||||
}
|
||||
else
|
||||
g_string_append (outstr, "+0000");
|
||||
break;
|
||||
case 'Z':
|
||||
g_string_append (outstr, g_date_time_get_timezone_abbreviation (datetime));
|
||||
break;
|
||||
case '%':
|
||||
g_string_append_c (outstr, '%');
|
||||
break;
|
||||
case '-':
|
||||
pad_set = TRUE;
|
||||
pad = 0;
|
||||
goto next_mod;
|
||||
case '_':
|
||||
pad_set = TRUE;
|
||||
pad = ' ';
|
||||
goto next_mod;
|
||||
case '0':
|
||||
pad_set = TRUE;
|
||||
pad = '0';
|
||||
goto next_mod;
|
||||
default:
|
||||
goto bad_format;
|
||||
}
|
||||
in_mod = FALSE;
|
||||
}
|
||||
else
|
||||
g_string_append_unichar (outstr, c);
|
||||
}
|
||||
next_mod: ;
|
||||
g_string_free (outstr, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_string_free (outstr, FALSE);
|
||||
if (locale_is_utf8)
|
||||
return g_string_free (outstr, FALSE);
|
||||
|
||||
bad_format:
|
||||
utf8 = g_locale_to_utf8 (outstr->str, outstr->len, NULL, NULL, NULL);
|
||||
g_string_free (outstr, TRUE);
|
||||
return NULL;
|
||||
return utf8;
|
||||
}
|
||||
|
||||
|
||||
|
@ -871,6 +871,68 @@ GDateTime *__dt = g_date_time_new_local (2009, 10, 24, 0, 0, 0);\
|
||||
TEST_PRINTF ("%Z", dst);
|
||||
}
|
||||
|
||||
static void
|
||||
test_non_utf8_printf (void)
|
||||
{
|
||||
gchar *oldlocale;
|
||||
|
||||
oldlocale = g_strdup (setlocale (LC_ALL, NULL));
|
||||
setlocale (LC_ALL, "ja_JP.eucjp");
|
||||
if (strstr (setlocale (LC_ALL, NULL), "ja_JP") == NULL)
|
||||
{
|
||||
g_test_message ("locale ja_JP.eucjp not available, skipping non-UTF8 tests");
|
||||
return;
|
||||
}
|
||||
|
||||
/* These are the outputs that ja_JP.UTF-8 generates; if everything
|
||||
* is working then ja_JP.eucjp should generate the same.
|
||||
*/
|
||||
TEST_PRINTF ("%a", "\345\234\237");
|
||||
TEST_PRINTF ("%A", "\345\234\237\346\233\234\346\227\245");
|
||||
TEST_PRINTF ("%b", "10\346\234\210");
|
||||
TEST_PRINTF ("%B", "10\346\234\210");
|
||||
TEST_PRINTF ("%d", "24");
|
||||
TEST_PRINTF_DATE (2009, 1, 1, "%d", "01");
|
||||
TEST_PRINTF ("%e", "24"); // fixme
|
||||
TEST_PRINTF ("%h", "10\346\234\210");
|
||||
TEST_PRINTF ("%H", "00");
|
||||
TEST_PRINTF_TIME (15, 0, 0, "%H", "15");
|
||||
TEST_PRINTF ("%I", "12");
|
||||
TEST_PRINTF_TIME (12, 0, 0, "%I", "12");
|
||||
TEST_PRINTF_TIME (15, 0, 0, "%I", "03");
|
||||
TEST_PRINTF ("%j", "297");
|
||||
TEST_PRINTF ("%k", " 0");
|
||||
TEST_PRINTF_TIME (13, 13, 13, "%k", "13");
|
||||
TEST_PRINTF ("%l", "12");
|
||||
TEST_PRINTF_TIME (12, 0, 0, "%I", "12");
|
||||
TEST_PRINTF_TIME (13, 13, 13, "%l", " 1");
|
||||
TEST_PRINTF_TIME (10, 13, 13, "%l", "10");
|
||||
TEST_PRINTF ("%m", "10");
|
||||
TEST_PRINTF ("%M", "00");
|
||||
TEST_PRINTF ("%p", "\345\215\210\345\211\215");
|
||||
TEST_PRINTF_TIME (13, 13, 13, "%p", "\345\215\210\345\276\214");
|
||||
TEST_PRINTF ("%P", "\345\215\210\345\211\215");
|
||||
TEST_PRINTF_TIME (13, 13, 13, "%P", "\345\215\210\345\276\214");
|
||||
TEST_PRINTF ("%r", "\345\215\210\345\211\21512\346\231\20200\345\210\20600\347\247\222");
|
||||
TEST_PRINTF_TIME (13, 13, 13, "%r", "\345\215\210\345\276\21401\346\231\20213\345\210\20613\347\247\222");
|
||||
TEST_PRINTF ("%R", "00:00");
|
||||
TEST_PRINTF_TIME (13, 13, 31, "%R", "13:13");
|
||||
TEST_PRINTF ("%S", "00");
|
||||
TEST_PRINTF ("%t", " ");
|
||||
TEST_PRINTF ("%u", "6");
|
||||
TEST_PRINTF ("%x", "2009\345\271\26410\346\234\21024\346\227\245");
|
||||
TEST_PRINTF ("%X", "00\346\231\20200\345\210\20600\347\247\222");
|
||||
TEST_PRINTF_TIME (13, 14, 15, "%X", "13\346\231\20214\345\210\20615\347\247\222");
|
||||
TEST_PRINTF ("%y", "09");
|
||||
TEST_PRINTF ("%Y", "2009");
|
||||
TEST_PRINTF ("%%", "%");
|
||||
TEST_PRINTF ("%", "");
|
||||
TEST_PRINTF ("%9", NULL);
|
||||
|
||||
setlocale (LC_ALL, oldlocale);
|
||||
g_free (oldlocale);
|
||||
}
|
||||
|
||||
static void
|
||||
test_modifiers (void)
|
||||
{
|
||||
@ -1196,6 +1258,7 @@ main (gint argc,
|
||||
g_test_add_func ("/GDateTime/new_full", test_GDateTime_new_full);
|
||||
g_test_add_func ("/GDateTime/now", test_GDateTime_now);
|
||||
g_test_add_func ("/GDateTime/printf", test_GDateTime_printf);
|
||||
g_test_add_func ("/GDateTime/non_utf8_printf", test_non_utf8_printf);
|
||||
g_test_add_func ("/GDateTime/strftime", test_strftime);
|
||||
g_test_add_func ("/GDateTime/modifiers", test_modifiers);
|
||||
g_test_add_func ("/GDateTime/to_local", test_GDateTime_to_local);
|
||||
|
Loading…
Reference in New Issue
Block a user