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:
Dan Winship 2012-01-19 10:39:57 -05:00
parent 9fa374ccf7
commit b6a8dec558
3 changed files with 413 additions and 250 deletions

View File

@ -1305,24 +1305,24 @@ if test x$glib_cv_langinfo_time = xyes; then
AC_DEFINE(HAVE_LANGINFO_TIME,1,[Have nl_langinfo (PM_STR)]) AC_DEFINE(HAVE_LANGINFO_TIME,1,[Have nl_langinfo (PM_STR)])
fi fi
dnl Check for nl_langinfo and _NL_CTYPE_OUTDIGITn_WC dnl Check for nl_langinfo and _NL_CTYPE_OUTDIGITn_MB
AC_CACHE_CHECK([for nl_langinfo (_NL_CTYPE_OUTDIGITn_WC)], glib_cv_langinfo_outdigit,[ AC_CACHE_CHECK([for nl_langinfo (_NL_CTYPE_OUTDIGITn_MB)], glib_cv_langinfo_outdigit,[
AC_TRY_COMPILE([#include <langinfo.h>], AC_TRY_COMPILE([#include <langinfo.h>],
[char *str; [char *str;
str = nl_langinfo (_NL_CTYPE_OUTDIGIT0_WC); str = nl_langinfo (_NL_CTYPE_OUTDIGIT0_MB);
str = nl_langinfo (_NL_CTYPE_OUTDIGIT1_WC); str = nl_langinfo (_NL_CTYPE_OUTDIGIT1_MB);
str = nl_langinfo (_NL_CTYPE_OUTDIGIT2_WC); str = nl_langinfo (_NL_CTYPE_OUTDIGIT2_MB);
str = nl_langinfo (_NL_CTYPE_OUTDIGIT3_WC); str = nl_langinfo (_NL_CTYPE_OUTDIGIT3_MB);
str = nl_langinfo (_NL_CTYPE_OUTDIGIT4_WC); str = nl_langinfo (_NL_CTYPE_OUTDIGIT4_MB);
str = nl_langinfo (_NL_CTYPE_OUTDIGIT5_WC); str = nl_langinfo (_NL_CTYPE_OUTDIGIT5_MB);
str = nl_langinfo (_NL_CTYPE_OUTDIGIT6_WC); str = nl_langinfo (_NL_CTYPE_OUTDIGIT6_MB);
str = nl_langinfo (_NL_CTYPE_OUTDIGIT7_WC); str = nl_langinfo (_NL_CTYPE_OUTDIGIT7_MB);
str = nl_langinfo (_NL_CTYPE_OUTDIGIT8_WC); str = nl_langinfo (_NL_CTYPE_OUTDIGIT8_MB);
str = nl_langinfo (_NL_CTYPE_OUTDIGIT9_WC);], str = nl_langinfo (_NL_CTYPE_OUTDIGIT9_MB);],
[glib_cv_langinfo_outdigit=yes], [glib_cv_langinfo_outdigit=yes],
[glib_cv_langinfo_outdigit=no])]) [glib_cv_langinfo_outdigit=no])])
if test x$glib_cv_langinfo_outdigit = xyes; then 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 fi
dnl **************************************** dnl ****************************************

View File

@ -62,6 +62,8 @@
#include "gslice.h" #include "gslice.h"
#include "gatomic.h" #include "gatomic.h"
#include "gcharset.h"
#include "gconvert.h"
#include "gfileutils.h" #include "gfileutils.h"
#include "ghash.h" #include "ghash.h"
#include "gmain.h" #include "gmain.h"
@ -2083,15 +2085,15 @@ g_date_time_to_utc (GDateTime *datetime)
static void static void
format_number (GString *str, format_number (GString *str,
gboolean use_alt_digits, gboolean use_alt_digits,
gchar pad, gchar *pad,
gint width, gint width,
guint32 number) guint32 number)
{ {
const gunichar ascii_digits[10] = { const gchar *ascii_digits[10] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9' "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
}; };
const gunichar *digits = ascii_digits; const gchar **digits = ascii_digits;
gunichar tmp[10]; const gchar *tmp[10];
gint i = 0; gint i = 0;
g_return_if_fail (width <= 10); g_return_if_fail (width <= 10);
@ -2099,18 +2101,14 @@ format_number (GString *str,
#ifdef HAVE_LANGINFO_OUTDIGIT #ifdef HAVE_LANGINFO_OUTDIGIT
if (use_alt_digits) if (use_alt_digits)
{ {
static gunichar alt_digits[10]; static const gchar *alt_digits[10];
static gsize initialised; static gsize initialised;
/* 2^32 has 10 digits */ /* 2^32 has 10 digits */
if G_UNLIKELY (g_once_init_enter (&initialised)) if G_UNLIKELY (g_once_init_enter (&initialised))
{ {
#define DO_DIGIT(n) \ #define DO_DIGIT(n) \
{ \ alt_digits[n] = nl_langinfo (_NL_CTYPE_OUTDIGIT## n ##_MB)
union { guint integer; char *pointer; } val; \
val.pointer = nl_langinfo (_NL_CTYPE_OUTDIGIT## n ##_WC); \
alt_digits[n] = val.integer; \
}
DO_DIGIT(0); DO_DIGIT(1); DO_DIGIT(2); DO_DIGIT(3); DO_DIGIT(4); 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); DO_DIGIT(5); DO_DIGIT(6); DO_DIGIT(7); DO_DIGIT(8); DO_DIGIT(9);
#undef DO_DIGIT #undef DO_DIGIT
@ -2129,13 +2127,330 @@ format_number (GString *str,
while (number); while (number);
while (pad && i < width) while (pad && i < width)
tmp[i++] = pad == '0' ? digits[0] : pad; tmp[i++] = *pad == '0' ? digits[0] : pad;
/* should really be impossible */ /* should really be impossible */
g_assert (i <= 10); g_assert (i <= 10);
while (i) 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) const gchar *format)
{ {
GString *outstr; GString *outstr;
gchar *tmp; gchar *utf8;
gunichar c; gboolean locale_is_utf8 = g_get_charset (NULL);
gboolean in_mod = FALSE;
gboolean alt_digits = FALSE;
gboolean pad_set = FALSE;
gchar pad = '\0';
gchar *ampm;
g_return_val_if_fail (datetime != NULL, NULL); g_return_val_if_fail (datetime != NULL, NULL);
g_return_val_if_fail (format != NULL, NULL); g_return_val_if_fail (format != NULL, NULL);
g_return_val_if_fail (g_utf8_validate (format, -1, NULL), NULL); g_return_val_if_fail (g_utf8_validate (format, -1, NULL), NULL);
outstr = g_string_sized_new (strlen (format) * 2); 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); g_string_free (outstr, TRUE);
return NULL;
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: ;
} }
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); g_string_free (outstr, TRUE);
return NULL; return utf8;
} }

View File

@ -871,6 +871,68 @@ GDateTime *__dt = g_date_time_new_local (2009, 10, 24, 0, 0, 0);\
TEST_PRINTF ("%Z", dst); 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 static void
test_modifiers (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/new_full", test_GDateTime_new_full);
g_test_add_func ("/GDateTime/now", test_GDateTime_now); g_test_add_func ("/GDateTime/now", test_GDateTime_now);
g_test_add_func ("/GDateTime/printf", test_GDateTime_printf); 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/strftime", test_strftime);
g_test_add_func ("/GDateTime/modifiers", test_modifiers); g_test_add_func ("/GDateTime/modifiers", test_modifiers);
g_test_add_func ("/GDateTime/to_local", test_GDateTime_to_local); g_test_add_func ("/GDateTime/to_local", test_GDateTime_to_local);