diff --git a/glib/gdatetime.c b/glib/gdatetime.c index 2640e3b24..d04b0abf1 100644 --- a/glib/gdatetime.c +++ b/glib/gdatetime.c @@ -3048,8 +3048,10 @@ g_date_time_format_utf8 (GDateTime *datetime, gunichar c; gboolean alt_digits = FALSE; gboolean pad_set = FALSE; + gboolean mod_case = FALSE; gboolean name_is_utf8; const gchar *pad = ""; + const gchar *mod = ""; const gchar *name; const gchar *tz; @@ -3071,6 +3073,7 @@ g_date_time_format_utf8 (GDateTime *datetime, colons = 0; alt_digits = FALSE; pad_set = FALSE; + mod_case = FALSE; next_mod: c = g_utf8_get_char (utf8_format); @@ -3078,7 +3081,8 @@ g_date_time_format_utf8 (GDateTime *datetime, switch (c) { case 'a': - name = WEEKDAY_ABBR (datetime); + name = mod_case ? g_utf8_strup (WEEKDAY_ABBR (datetime), -1) + : WEEKDAY_ABBR (datetime); if (g_strcmp0 (name, "") == 0) return FALSE; @@ -3089,7 +3093,8 @@ g_date_time_format_utf8 (GDateTime *datetime, break; case 'A': - name = WEEKDAY_FULL (datetime); + name = mod_case ? g_utf8_strup (WEEKDAY_FULL (datetime), -1) + : WEEKDAY_FULL (datetime); if (g_strcmp0 (name, "") == 0) return FALSE; @@ -3104,6 +3109,8 @@ g_date_time_format_utf8 (GDateTime *datetime, : MONTH_ABBR_WITH_DAY (datetime); if (g_strcmp0 (name, "") == 0) return FALSE; + if (mod_case) + name = g_utf8_strup (name, -1); name_is_utf8 = locale_is_utf8 || ((alt_digits && !MONTH_ABBR_STANDALONE_IS_LOCALE) || @@ -3118,6 +3125,8 @@ g_date_time_format_utf8 (GDateTime *datetime, : MONTH_FULL_WITH_DAY (datetime); if (g_strcmp0 (name, "") == 0) return FALSE; + if (mod_case) + name = g_utf8_strup (name, -1); name_is_utf8 = locale_is_utf8 || ((alt_digits && !MONTH_FULL_STANDALONE_IS_LOCALE) || @@ -3171,6 +3180,8 @@ g_date_time_format_utf8 (GDateTime *datetime, : MONTH_ABBR_WITH_DAY (datetime); if (g_strcmp0 (name, "") == 0) return FALSE; + if (mod_case) + name = g_utf8_strup (name, -1); name_is_utf8 = locale_is_utf8 || ((alt_digits && !MONTH_ABBR_STANDALONE_IS_LOCALE) || @@ -3215,11 +3226,15 @@ g_date_time_format_utf8 (GDateTime *datetime, alt_digits = TRUE; goto next_mod; case 'p': - if (!format_ampm (datetime, outstr, locale_is_utf8, TRUE)) + if (!format_ampm (datetime, outstr, locale_is_utf8, + mod_case && g_strcmp0 (mod, "#") == 0 ? FALSE + : TRUE)) return FALSE; break; case 'P': - if (!format_ampm (datetime, outstr, locale_is_utf8, FALSE)) + if (!format_ampm (datetime, outstr, locale_is_utf8, + mod_case && g_strcmp0 (mod, "^") == 0 ? TRUE + : FALSE)) return FALSE; break; case 'r': @@ -3299,7 +3314,8 @@ g_date_time_format_utf8 (GDateTime *datetime, } break; case 'Z': - tz = g_date_time_get_timezone_abbreviation (datetime); + tz = mod_case && g_strcmp0 (mod, "#") == 0 ? g_utf8_strdown (g_date_time_get_timezone_abbreviation (datetime), -1) + : g_date_time_get_timezone_abbreviation (datetime); g_string_append (outstr, tz); break; case '%': @@ -3323,9 +3339,17 @@ g_date_time_format_utf8 (GDateTime *datetime, return FALSE; colons++; goto next_mod; - default: - return FALSE; - } + case '^': + mod_case = TRUE; + mod = "^"; + goto next_mod; + case '#': + mod_case = TRUE; + mod = "#"; + goto next_mod; + default: + return FALSE; + } } return TRUE; @@ -3418,8 +3442,9 @@ g_date_time_format_utf8 (GDateTime *datetime, * - `%%`: a literal `%` character * * Some conversion specifications can be modified by preceding the - * conversion specifier by one or more modifier characters. The - * following modifiers are supported for many of the numeric + * conversion specifier by one or more modifier characters. + * + * The following modifiers are supported for many of the numeric * conversions: * * - `O`: Use alternative numeric symbols, if the current locale supports those. @@ -3430,6 +3455,13 @@ g_date_time_format_utf8 (GDateTime *datetime, * - `0`: Pad a numeric result with zeros. This overrides the default padding * for the specifier. * + * The following modifiers are supported for many of the alphabetic conversions: + * + * - `^`: Use upper case if possible. This is a gnulib `strftime()` extension. + * Since: 2.80 + * - `#`: Use opposite case if possible. This is a gnulib `strftime()` + * extension. Since: 2.80 + * * Additionally, when `O` is used with `B`, `b`, or `h`, it produces the alternative * form of a month name. The alternative form should be used when the month * name is used without a day number (e.g., standalone). It is required in diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c index 49390c900..1a7a1d834 100644 --- a/glib/tests/gdatetime.c +++ b/glib/tests/gdatetime.c @@ -1792,6 +1792,30 @@ test_modifiers (void) TEST_PRINTF_DATE (2009, 1, 21, "%-e", "21"); TEST_PRINTF_DATE (2009, 1, 21, "%0e", "21"); + TEST_PRINTF_DATE (2009, 1, 1, "%a", "Thu"); + TEST_PRINTF_DATE (2009, 1, 1, "%^a", "THU"); + TEST_PRINTF_DATE (2009, 1, 1, "%#a", "THU"); + + TEST_PRINTF_DATE (2009, 1, 1, "%A", "Thursday"); + TEST_PRINTF_DATE (2009, 1, 1, "%^A", "THURSDAY"); + TEST_PRINTF_DATE (2009, 1, 1, "%#A", "THURSDAY"); + + TEST_PRINTF_DATE (2009, 1, 1, "%b", "Jan"); + TEST_PRINTF_DATE (2009, 1, 1, "%^b", "JAN"); + TEST_PRINTF_DATE (2009, 1, 1, "%#b", "JAN"); + + TEST_PRINTF_DATE (2009, 1, 1, "%B", "January"); + TEST_PRINTF_DATE (2009, 1, 1, "%^B", "JANUARY"); + TEST_PRINTF_DATE (2009, 1, 1, "%#B", "JANUARY"); + + TEST_PRINTF_DATE (2009, 1, 1, "%h", "Jan"); + TEST_PRINTF_DATE (2009, 1, 1, "%^h", "JAN"); + TEST_PRINTF_DATE (2009, 1, 1, "%#h", "JAN"); + + TEST_PRINTF_DATE (2009, 1, 1, "%Z", "UTC"); + TEST_PRINTF_DATE (2009, 1, 1, "%^Z", "UTC"); + TEST_PRINTF_DATE (2009, 1, 1, "%#Z", "utc"); + TEST_PRINTF_TIME ( 1, 0, 0, "%H", "01"); TEST_PRINTF_TIME ( 1, 0, 0, "%_H", " 1"); TEST_PRINTF_TIME ( 1, 0, 0, "%-H", "1"); @@ -1824,6 +1848,14 @@ test_modifiers (void) TEST_PRINTF_TIME (23, 0, 0, "%-l", "11"); TEST_PRINTF_TIME (23, 0, 0, "%0l", "11"); + TEST_PRINTF_TIME (1, 0, 0, "%p", "AM"); + TEST_PRINTF_TIME (1, 0, 0, "%^p", "AM"); + TEST_PRINTF_TIME (1, 0, 0, "%#p", "am"); + + TEST_PRINTF_TIME (1, 0, 0, "%P", "am"); + TEST_PRINTF_TIME (1, 0, 0, "%^P", "AM"); + TEST_PRINTF_TIME (1, 0, 0, "%#P", "am"); + oldlocale = g_strdup (setlocale (LC_ALL, NULL)); setlocale (LC_ALL, "fa_IR.utf-8"); #ifdef HAVE_LANGINFO_OUTDIGIT