[Bug #20929] Win32: Encode timezone name in UTF-8

This commit is contained in:
Nobuyoshi Nakada 2024-12-06 16:56:29 +09:00 committed by Nobuyoshi Nakada
parent 78762b5218
commit 1c15f641cc
Notes: git 2024-12-06 10:00:00 +00:00
3 changed files with 20 additions and 5 deletions

View File

@ -717,13 +717,15 @@ class TestTime < Test::Unit::TestCase
assert_equal("2000-01-01 09:12:34 +091234", t2000.localtime(9*3600+12*60+34).inspect) assert_equal("2000-01-01 09:12:34 +091234", t2000.localtime(9*3600+12*60+34).inspect)
end end
FIXED_ZONE_ENCODING = (Encoding::UTF_8 if /mswin|mingw/.match?(RUBY_PLATFORM))
def assert_zone_encoding(time) def assert_zone_encoding(time)
zone = time.zone zone = time.zone
assert_predicate(zone, :valid_encoding?) assert_predicate(zone, :valid_encoding?)
if zone.ascii_only? if zone.ascii_only?
assert_equal(Encoding::US_ASCII, zone.encoding) assert_equal(Encoding::US_ASCII, zone.encoding)
else else
enc = Encoding.find('locale') enc = FIXED_ZONE_ENCODING || Encoding.find('locale')
assert_equal(enc, zone.encoding) assert_equal(enc, zone.encoding)
end end
end end

20
time.c
View File

@ -31,6 +31,10 @@
# include <sys/time.h> # include <sys/time.h>
#endif #endif
#if defined(HAVE_LOCALE_H)
# include <locale.h>
#endif
#include "id.h" #include "id.h"
#include "internal.h" #include "internal.h"
#include "internal/array.h" #include "internal/array.h"
@ -950,7 +954,11 @@ zone_str(const char *zone)
str = rb_usascii_str_new(zone, len); str = rb_usascii_str_new(zone, len);
} }
else { else {
#if defined(_WIN32)
str = rb_utf8_str_new(zone, len);
#else
str = rb_enc_str_new(zone, len, rb_locale_encoding()); str = rb_enc_str_new(zone, len, rb_locale_encoding());
#endif
} }
return rb_fstring(str); return rb_fstring(str);
} }
@ -1649,11 +1657,15 @@ localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, VAL
if (zone) { if (zone) {
#if defined(HAVE_TM_ZONE) #if defined(HAVE_TM_ZONE)
*zone = zone_str(tm.tm_zone); *zone = zone_str(tm.tm_zone);
#elif defined(_WIN32)
{
char buf[64];
_locale_t utf8_locale = _create_locale(LC_TIME, ".65001");
size_t n = _strftime_l(buf, numberof(buf), "%Z", &tm, utf8_locale);
_free_locale(utf8_locale);
*zone = zone_str((ssize_t)n < 0 ? NULL : buf);
}
#elif defined(HAVE_TZNAME) && defined(HAVE_DAYLIGHT) #elif defined(HAVE_TZNAME) && defined(HAVE_DAYLIGHT)
# 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 */ /* this needs tzset or localtime, instead of localtime_r */
*zone = zone_str(tzname[daylight && tm.tm_isdst]); *zone = zone_str(tzname[daylight && tm.tm_isdst]);
#else #else

View File

@ -779,6 +779,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub
#define HAVE_STRUCT_TIMEVAL 1 #define HAVE_STRUCT_TIMEVAL 1
!if $(MSC_VER) >= 1900 !if $(MSC_VER) >= 1900
#define HAVE_STRUCT_TIMESPEC #define HAVE_STRUCT_TIMESPEC
#define HAVE_LOCALE_H 1
!endif !endif
!if $(MSC_VER) >= 1600 !if $(MSC_VER) >= 1600
#define HAVE_INTTYPES_H 1 #define HAVE_INTTYPES_H 1