diff --git a/time/Makefile b/time/Makefile
index 5c6304ece1..2ca206309d 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -43,7 +43,7 @@ tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \
tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 \
tst-strptime3 bug-getdate1 tst-strptime-whitespace tst-ftime \
- tst-tzname tst-y2039 bug-mktime4 tst-strftime2
+ tst-tzname tst-y2039 bug-mktime4 tst-strftime2 tst-strftime3
include ../Rules
diff --git a/time/strptime_l.c b/time/strptime_l.c
index e19b9a15dd..fb90bd2773 100644
--- a/time/strptime_l.c
+++ b/time/strptime_l.c
@@ -909,7 +909,8 @@ __strptime_internal (const char *rp, const char *fmt, struct tm *tmp,
* era->absolute_direction);
match = (delta >= 0
&& delta < (((int64_t) era->stop_date[0]
- - (int64_t) era->start_date[0])
+ - (int64_t) era->start_date[0]
+ + 1)
* era->absolute_direction));
}
if (! match)
diff --git a/time/tst-strftime3.c b/time/tst-strftime3.c
new file mode 100644
index 0000000000..0b5ccaed9b
--- /dev/null
+++ b/time/tst-strftime3.c
@@ -0,0 +1,204 @@
+/* Test for strftime, esp Japenese era name changes.
+ Copyright (C) 2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ . */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* These exist for the convenience of writing the test data, because
+ zero-based vs one-based. */
+typedef enum {
+ Sun, Mon, Tue, Wed, Thu, Fri, Sat
+} WeekDay;
+
+typedef enum {
+ Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
+} Month;
+
+typedef struct Data {
+ /* A descriptive name of the test. */
+ const char *name;
+
+ /* The specific date and time to be tested. */
+ int y, m, d;
+ WeekDay w;
+ int hh, mm, ss;
+
+ /* The locale under which the conversion is done. */
+ const char *locale;
+
+ /* Format passed to strftime. */
+ const char *format;
+
+ /* Expected data, NUL terminated. */
+ const char *printed;
+
+ int test_strptime_too;
+
+} Data;
+
+/* Notes: years are full 4-digit years, the code compensates. */
+const Data data[] = {
+ { "Baseline test",
+ 2019, Mar, 27, Wed, 14, 3, 22, "en_US.ISO-8859-1",
+ "%Y-%m-%d %T", "2019-03-27 14:03:22", 1 },
+
+
+ { "Japanese era change, 1926, before first transition's year",
+ 1925, Dec, 31, Thu, 12, 00, 00, "ja_JP.UTF-8", "%EY",
+ "\345\244\247\346\255\24314\345\271\264", 1 },
+ { "Japanese era change, 1926, start of first transition's year",
+ 1926, Jan, 1, Fri, 12, 00, 00, "ja_JP.UTF-8", "%EY",
+ "\345\244\247\346\255\24315\345\271\264", 1 },
+
+ { "Japanese era change, 1926, before first transition",
+ 1926, Dec, 24, Fri, 12, 00, 00, "ja_JP.UTF-8", "%EY",
+ "\345\244\247\346\255\24315\345\271\264", 1 },
+ { "Japanese era change, 1926, after first transition",
+ 1926, Dec, 25, Sat, 12, 00, 00, "ja_JP.UTF-8", "%EY",
+ "\346\230\255\345\222\214\345\205\203\345\271\264", 1 },
+
+ { "Japanese era change, 1926, before end transition year",
+ 1926, Dec, 31, Fri, 12, 00, 00, "ja_JP.UTF-8", "%EY",
+ "\346\230\255\345\222\214\345\205\203\345\271\264", 1 },
+ { "Japanese era change, 1926, after transition year",
+ 1927, Jan, 1, Sat, 12, 00, 00, "ja_JP.UTF-8", "%EY",
+ "\346\230\255\345\222\21402\345\271\264", 1 },
+
+
+ { "Japanese era change, 1989, before first transition's year",
+ 1988, Dec, 31, Sat, 12, 00, 00, "ja_JP.UTF-8", "%EY",
+ "\346\230\255\345\222\21463\345\271\264", 1 },
+ { "Japanese era change, 1989, start of first transition's year",
+ 1989, Jan, 1, Sun, 12, 00, 00, "ja_JP.UTF-8", "%EY",
+ "\346\230\255\345\222\21464\345\271\264", 1 },
+
+ { "Japanese era change, 1989, before first transition",
+ 1989, Jan, 7, Sat, 12, 00, 00, "ja_JP.UTF-8", "%EY",
+ "\346\230\255\345\222\21464\345\271\264", 0 },
+ { "Japanese era change, 1989, after first transition",
+ 1989, Jan, 8, Sun, 12, 00, 00, "ja_JP.UTF-8", "%EY",
+ "\345\271\263\346\210\220\345\205\203\345\271\264", 1 },
+ { "Japanese era change, 1989, end transition year",
+ 1989, Dec, 31, Sun, 12, 00, 00, "ja_JP.UTF-8", "%EY",
+ "\345\271\263\346\210\220\345\205\203\345\271\264", 1 },
+ { "Japanese era change, 1989, after transition year",
+ 1990, Jan, 1, Mon, 12, 00, 00, "ja_JP.UTF-8", "%EY",
+ "\345\271\263\346\210\22002\345\271\264", 1 },
+
+ { "Japanese era change, 1989, before first transition",
+ 1989, Jan, 7, Sat, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
+ "\276\274\317\30264\307\257", 0 },
+ { "Japanese era change, 1989, after first transition",
+ 1989, Jan, 8, Sun, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
+ "\312\277\300\256\270\265\307\257", 1 },
+ { "Japanese era change, 1989, end transition year",
+ 1989, Dec, 31, Sun, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
+ "\312\277\300\256\270\265\307\257", 1 },
+ { "Japanese era change, 1989, after transition year",
+ 1990, Jan, 1, Mon, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
+ "\312\277\300\25602\307\257", 1 },
+};
+
+#define NDATA array_length(data)
+
+/* Size of buffer passed to strftime. */
+#define STRBUFLEN 1000
+/* Size of buffer passed to tm_to_printed. */
+#define TMBUFLEN 50
+
+/* Helper function to create a printable version of struct tm. */
+static void
+tm_to_printed (struct tm *tm, char *buffer)
+{
+ snprintf (buffer, TMBUFLEN, "%04d/%02d/%02d-%02d:%02d:%02d-%d",
+ tm->tm_year,
+ tm->tm_mon,
+ tm->tm_mday,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec,
+ tm->tm_wday);
+}
+
+static int
+do_test (void)
+{
+ int i;
+ char buffer[STRBUFLEN];
+ char buf1[TMBUFLEN];
+ char buf2[TMBUFLEN];
+
+ for (i = 0; i < NDATA; i ++)
+ {
+ const Data *d = &(data[i]);
+ struct tm tm;
+ struct tm tm2;
+ size_t rv;
+ char *rvp;
+
+ /* Print this just to help debug failures. */
+ printf("\n%s: %s %s %s\n", d->name, d->locale, d->format, d->printed);
+
+ tm.tm_year = d->y - 1900;
+ tm.tm_mon = d->m;
+ tm.tm_mday = d->d;
+ tm.tm_wday = d->w;
+ tm.tm_hour = d->hh;
+ tm.tm_min = d->mm;
+ tm.tm_sec = d->ss;
+ tm.tm_isdst = -1;
+
+ /* LC_ALL may interfere with the snprintf in tm_to_printed. */
+ if (setlocale (LC_TIME, d->locale) == NULL)
+ {
+ /* See the LOCALES list in the Makefile. */
+ printf ("locale %s does not exist!\n", d->locale);
+ exit (EXIT_FAILURE);
+ }
+
+ rv = strftime (buffer, sizeof(buffer), d->format, &tm);
+
+ TEST_COMPARE (rv, strlen (d->printed));
+ TEST_COMPARE_STRING (buffer, d->printed);
+
+ /* Copy the original time, so that any fields not affected by
+ the call to strptime() will match. */
+ tm2 = tm;
+
+ rvp = strptime (d->printed, d->format, &tm2);
+
+ /* Not all conversions are reversible. */
+ if (d->test_strptime_too)
+ {
+ TEST_COMPARE_STRING (rvp, "");
+
+ tm_to_printed (&tm, buf1);
+ tm_to_printed (&tm2, buf2);
+ TEST_COMPARE_STRING (buf1, buf2);
+ }
+ }
+
+ return 0;
+}
+
+#include