From: "nobu (Nobuyoshi Nakada) via ruby-core" Date: 2023-01-27T13:22:07+00:00 Subject: [ruby-core:112083] [Ruby master Bug#19383] Time.now.zone encoding for German display language in Windows is incorrect Issue #19383 has been updated by nobu (Nobuyoshi Nakada). Maybe msvcrt converts timezone names to ACP, not ConsoleCP. If so, this patch may work, but I have no idea how to test this in a CI. ```diff diff --git i/time.c w/time.c index 9c4c93939e0..2e1a2dca29b 100644 --- i/time.c +++ w/time.c @@ -929,7 +929,7 @@ timegmw_noleapsecond(struct vtm *vtm) } static VALUE -zone_str(const char *zone) +zone_str_enc(const char *zone, rb_encoding *enc) { const char *p; int ascii_only = 1; @@ -950,11 +950,18 @@ zone_str(const char *zone) str = rb_usascii_str_new(zone, len); } else { - str = rb_enc_str_new(zone, len, rb_locale_encoding()); + if (!enc) enc = rb_locale_encoding(); + str = rb_enc_str_new(zone, len, enc); } return rb_fstring(str); } +static VALUE +zone_str(const char *zone) +{ + return zone_str_enc(zone, NULL); +} + static void gmtimew_noleapsecond(wideval_t timew, struct vtm *vtm) { @@ -1653,12 +1660,18 @@ localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, VAL #if defined(HAVE_TM_ZONE) *zone = zone_str(tm.tm_zone); #elif defined(HAVE_TZNAME) && defined(HAVE_DAYLIGHT) + rb_encoding *enc = NULL; +# if defined(_WIN32) + char cp[DECIMAL_SIZE_OF_BITS(sizeof(UINT) * CHAR_BIT) + sizeof("CP")]; + snprintf(cp, sizeof(cp), "CP%u", GetACP()); + enc = rb_enc_find(cp); +# endif # if defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 140 # define tzname _tzname # define daylight _daylight # endif /* this needs tzset or localtime, instead of localtime_r */ - *zone = zone_str(tzname[daylight && tm.tm_isdst]); + *zone = zone_str_enc(tzname[daylight && tm.tm_isdst], enc); #else { char buf[64]; ``` ---------------------------------------- Bug #19383: Time.now.zone encoding for German display language in Windows is incorrect https://bugs.ruby-lang.org/issues/19383#change-101517 * Author: stringsn88keys (Thomas Powell) * Status: Feedback * Priority: Normal * ruby -v: 3.1.3 * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- OS: Verified on Windows 10 and Windows Server 2022 and Ruby 2.7.7 through 3.1.3 Display language: Verified on German, but may impact other languages in which Time.now.zone returns characters that aren't [A-Za-z]. Time zone: CET (UTC +01:00) Amsterdam, Berlin, ... Time.now.zone # => "Mitteleuro\xE3ische Zeit" Time.now.zone.encoding # => # puts Time.now.zone # => "Mitteleurop���ische Zeit" (should be "Mitteleurop��ische Zeit") Time.now.zone.encode(Encoding::UTF_8) # => "Mitteleurop���ische Zeit" Doing a force_encoding on all encodings in Encoding.list reveals that ISO-8859-(1..16) and Windows-125(0,2,4,7) work to coerce the �� out of the time zone string: Time.now.zone.force_encoding(Encoding::WINDOWS_1252) # => "Mitteleuro\xE3ische Zeit" ... but ... Time.now.zone.force_encoding(Encoding::WINDOWS_1252).encode(Encoding::UTF_8) #=> "Mitteleurop��ische Zeit" Related issue: This improper encoding/rendering caused Ohai's JSON output to be unparseable. Workaround was forcing to Windows-1252. https://github.com/chef/ohai/pull/1781 -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/