diff options
author | Ludovic Courtès <ludo@gnu.org> | 2019-06-30 21:31:36 +0200 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2019-06-30 21:31:36 +0200 |
commit | ab2fd70ef1e36c6532128b73082809ef3c056556 (patch) | |
tree | 0c2e94ba20d85d670271fc805956ea6b49408680 | |
parent | 63f54a7bc6adbc0f1b397872fb7eb96e84967ff1 (diff) |
'strftime' and 'strptime' honor the locale encoding.
Fixes <https://bugs.gnu.org/35920>.
Reported by Christopher Lam <christopher.lck@gmail.com>.
* libguile/stime.c (scm_strftime): Use 'scm_to_locale_stringn' instead
of 'scm_to_utf8_stringn'.
(scm_strptime): Likewise, and use 'scm_string_length' instead of
'u8_strnlen'.
* test-suite/tests/time.test ("strftime")["strftime passes wide
characters"]: Wrap body in 'with-locale'.
["strftime fr_FR.utf8", "strftime fr_FR.iso88591"]: New tests.
("strptime")["strftime fr_FR.utf8", "strftime fr_FR.iso88591"]: New
tests.
-rw-r--r-- | libguile/stime.c | 24 | ||||
-rw-r--r-- | test-suite/tests/time.test | 35 |
2 files changed, 43 insertions, 16 deletions
diff --git a/libguile/stime.c b/libguile/stime.c index b681d7ee3..9a21b61fe 100644 --- a/libguile/stime.c +++ b/libguile/stime.c @@ -662,9 +662,9 @@ SCM_DEFINE (scm_strftime, "strftime", 2, 0, 0, SCM_VALIDATE_STRING (1, format); bdtime2c (stime, &t, SCM_ARG2, FUNC_NAME); - /* Convert string to UTF-8 so that non-ASCII characters in the - format are passed through unchanged. */ - fmt = scm_to_utf8_stringn (format, &len); + /* Convert the format string to the locale encoding, as the underlying + 'strftime' C function expects. */ + fmt = scm_to_locale_stringn (format, &len); /* Ugly hack: strftime can return 0 if its buffer is too small, but some valid time strings (e.g. "%p") can sometimes produce @@ -727,7 +727,7 @@ SCM_DEFINE (scm_strftime, "strftime", 2, 0, 0, #endif } - result = scm_from_utf8_string (tbuf + 1); + result = scm_from_locale_string (tbuf + 1); free (tbuf); free (myfmt); #if HAVE_STRUCT_TM_TM_ZONE @@ -754,16 +754,16 @@ SCM_DEFINE (scm_strptime, "strptime", 2, 0, 0, { struct tm t; char *fmt, *str, *rest; - size_t used_len; + SCM used_len; long zoff; SCM_VALIDATE_STRING (1, format); SCM_VALIDATE_STRING (2, string); - /* Convert strings to UTF-8 so that non-ASCII characters are passed - through unchanged. */ - fmt = scm_to_utf8_string (format); - str = scm_to_utf8_string (string); + /* Convert strings to the locale encoding, as the underlying + 'strptime' C function expects. */ + fmt = scm_to_locale_string (format); + str = scm_to_locale_string (string); /* initialize the struct tm */ #define tm_init(field) t.field = 0 @@ -807,14 +807,14 @@ SCM_DEFINE (scm_strptime, "strptime", 2, 0, 0, zoff = 0; #endif - /* Compute the number of UTF-8 characters. */ - used_len = u8_strnlen ((scm_t_uint8*) str, rest-str); + /* Compute the number of characters parsed. */ + used_len = scm_string_length (scm_from_locale_stringn (str, rest-str)); scm_remember_upto_here_2 (format, string); free (str); free (fmt); return scm_cons (filltime (&t, zoff, NULL), - scm_from_signed_integer (used_len)); + used_len); } #undef FUNC_NAME #endif /* HAVE_STRPTIME */ diff --git a/test-suite/tests/time.test b/test-suite/tests/time.test index 2c829abfe..0291b6bdf 100644 --- a/test-suite/tests/time.test +++ b/test-suite/tests/time.test @@ -1,7 +1,7 @@ ;;;; time.test --- test suite for Guile's time functions -*- scheme -*- ;;;; Jim Blandy <jimb@red-bean.com> --- June 1999, 2004 ;;;; -;;;; Copyright (C) 1999, 2004, 2006, 2007, 2008 Free Software Foundation, Inc. +;;;; Copyright (C) 1999, 2004, 2006, 2007, 2008, 2019 Free Software Foundation, Inc. ;;;; ;;;; This library is free software; you can redistribute it and/or ;;;; modify it under the terms of the GNU Lesser General Public @@ -204,8 +204,9 @@ (pass-if-equal "strftime passes wide characters" "\u0100" - (let ((t (localtime (current-time)))) - (substring (strftime "\u0100%Z" t) 0 1))) + (with-locale "en_US.utf8" + (let ((t (localtime (current-time)))) + (substring (strftime "\u0100%Z" t) 0 1)))) (with-test-prefix "C99 %z format" @@ -229,7 +230,17 @@ (putenv "TZ=EST+5") (tzset) (let ((tm (localtime 86400))) - (strftime "%z" tm)))))) + (strftime "%z" tm)))) + + (pass-if-equal "strftime fr_FR.utf8" + " 1 février 1970" + (with-locale "fr_FR.utf8" + (strftime "%e %B %Y" (gmtime (* 31 24 3600))))) + + (pass-if-equal "strftime fr_FR.iso88591" ;<https://bugs.gnu.org/35920> + " 1 février 1970" + (with-locale "fr_FR.iso88591" + (strftime "%e %B %Y" (gmtime (* 31 24 3600))))))) ;;; ;;; strptime @@ -261,6 +272,22 @@ (let ((tm (car (strptime "%s" "86400")))) (eqv? 0 (tm:gmtoff tm)))) + (pass-if-equal "strftime fr_FR.utf8" + '(1 2 1999) + (with-locale "fr_FR.utf8" + (let ((tm (car (strptime "%e %B %Y" " 1 février 1999")))) + (list (tm:mday tm) + (+ 1 (tm:mon tm)) + (+ 1900 (tm:year tm)))))) + + (pass-if-equal "strftime fr_FR.iso88591" ;<https://bugs.gnu.org/35920> + '(1 2 1999) + (with-locale "fr_FR.iso88591" + (let ((tm (car (strptime "%e %B %Y" " 1 février 1999")))) + (list (tm:mday tm) + (+ 1 (tm:mon tm)) + (+ 1900 (tm:year tm)))))) + ;; prior to guile 1.6.9 and 1.8.1 we didn't pass tm_gmtoff back from ;; strptime (pass-if "gmtoff on EST+5" |