aboutsummaryrefslogtreecommitdiff
path: root/time
diff options
context:
space:
mode:
Diffstat (limited to 'time')
-rw-r--r--time/Makefile3
-rw-r--r--time/strftime_l.c11
-rw-r--r--time/strptime_l.c32
-rw-r--r--time/tst-strptime.c12
4 files changed, 51 insertions, 7 deletions
diff --git a/time/Makefile b/time/Makefile
index 264eed9..2deb025 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -48,7 +48,8 @@ tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
include ../Rules
ifeq ($(run-built-tests),yes)
-LOCALES := de_DE.ISO-8859-1 en_US.ISO-8859-1 ja_JP.EUC-JP
+LOCALES := de_DE.ISO-8859-1 en_US.ISO-8859-1 ja_JP.EUC-JP fr_FR.UTF-8 \
+ pl_PL.UTF-8
include ../gen-locales.mk
$(objpfx)tst-ftime_l.out: $(gen-locales)
diff --git a/time/strftime_l.c b/time/strftime_l.c
index 18651ff..ac5d28f 100644
--- a/time/strftime_l.c
+++ b/time/strftime_l.c
@@ -492,6 +492,9 @@ __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format,
# define f_month \
((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
+# define f_altmonth \
+ ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(ALTMON_1) + tp->tm_mon)))
# define ampm \
((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
? NLW(PM_STR) : NLW(AM_STR)))
@@ -507,6 +510,7 @@ __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format,
? "?" : month_name[tp->tm_mon])
# define a_wkday f_wkday
# define a_month f_month
+# define f_altmonth f_month
# define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
size_t aw_len = 3;
@@ -785,7 +789,7 @@ __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format,
#endif
case L_('B'):
- if (modifier != 0)
+ if (modifier == L_('E'))
goto bad_format;
if (change_case)
{
@@ -793,7 +797,10 @@ __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format,
to_lowcase = 0;
}
#if defined _NL_CURRENT || !HAVE_STRFTIME
- cpy (STRLEN (f_month), f_month);
+ if (modifier == L_('O'))
+ cpy (STRLEN (f_altmonth), f_altmonth);
+ else
+ cpy (STRLEN (f_month), f_month);
break;
#else
goto underlying_strftime;
diff --git a/time/strptime_l.c b/time/strptime_l.c
index 7d4758e..39cf38d 100644
--- a/time/strptime_l.c
+++ b/time/strptime_l.c
@@ -124,6 +124,8 @@ extern const struct __locale_data _nl_C_LC_TIME attribute_hidden;
(&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
# define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
# define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
+# define alt_month_name \
+ (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ALTMON_1)].string)
# define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
# define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
# define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
@@ -319,10 +321,9 @@ __strptime_internal (const char *rp, const char *fmt, struct tm *tmp,
while (*fmt >= '0' && *fmt <= '9')
++fmt;
-#ifndef _NL_CURRENT
- /* We need this for handling the `E' modifier. */
+ /* In some cases, modifiers are handled by adjusting state and
+ then restarting the switch statement below. */
start_over:
-#endif
/* Make back up of current processing pointer. */
rp_backup = rp;
@@ -423,13 +424,32 @@ __strptime_internal (const char *rp, const char *fmt, struct tm *tmp,
ab_month_name[cnt]))
decided_longest = loc;
}
+#ifdef _LIBC
+ /* Now check the alt month. */
+ trp = rp;
+ if (match_string (_NL_CURRENT (LC_TIME, ALTMON_1 + cnt), trp)
+ && trp > rp_longest)
+ {
+ rp_longest = trp;
+ cnt_longest = cnt;
+ if (s.decided == not
+ && strcmp (_NL_CURRENT (LC_TIME, ALTMON_1 + cnt),
+ alt_month_name[cnt]))
+ decided_longest = loc;
+ }
+#endif
}
#endif
if (s.decided != loc
&& (((trp = rp, match_string (month_name[cnt], trp))
&& trp > rp_longest)
|| ((trp = rp, match_string (ab_month_name[cnt], trp))
- && trp > rp_longest)))
+ && trp > rp_longest)
+#ifdef _LIBC
+ || ((trp = rp, match_string (alt_month_name[cnt], trp))
+ && trp > rp_longest)
+#endif
+ ))
{
rp_longest = trp;
cnt_longest = cnt;
@@ -1015,6 +1035,10 @@ __strptime_internal (const char *rp, const char *fmt, struct tm *tmp,
case 'O':
switch (*fmt++)
{
+ case 'B':
+ /* Match month name. Reprocess as plain 'B'. */
+ fmt--;
+ goto start_over;
case 'd':
case 'e':
/* Match day of month using alternate numeric symbols. */
diff --git a/time/tst-strptime.c b/time/tst-strptime.c
index 34ad797..62ecb7c 100644
--- a/time/tst-strptime.c
+++ b/time/tst-strptime.c
@@ -51,6 +51,18 @@ static const struct
6, 0, 0, 1 },
{ "ja_JP.EUC-JP", "2001 20 \xb7\xee", "%Y %U %a", 1, 140, 4, 21 },
{ "ja_JP.EUC-JP", "2001 21 \xb7\xee", "%Y %W %a", 1, 140, 4, 21 },
+ /* Most of the languages do not need the declension of the month names
+ and do not distinguish between %B and %OB. */
+ { "en_US.ISO-8859-1", "November 17, 2017", "%B %e, %Y", 5, 320, 10, 17 },
+ { "de_DE.ISO-8859-1", "18. Nov 2017", "%d. %b %Y", 6, 321, 10, 18 },
+ { "fr_FR.UTF-8", "19 novembre 2017", "%d %OB %Y", 0, 322, 10, 19 },
+ /* Some languages do need the declension of the month names. */
+ { "pl_PL.UTF-8", "21 lis 2017", "%d %b %Y", 2, 324, 10, 21 },
+ { "pl_PL.UTF-8", "22 LIS 2017", "%d %B %Y", 3, 325, 10, 22 },
+ /* TODO: Use the genitive case here as soon as it is added to localedata. */
+ { "pl_PL.UTF-8", "23 listopad 2017", "%d %B %Y", 4, 326, 10, 23 },
+ /* The nominative case is incorrect here but it is parseable. */
+ { "pl_PL.UTF-8", "24 listopad 2017", "%d %OB %Y", 5, 327, 10, 24 },
};