diff options
| author | KOBAYASHI Shuji <[email protected]> | 2019-07-31 19:20:03 +0900 |
|---|---|---|
| committer | KOBAYASHI Shuji <[email protected]> | 2019-07-31 20:34:27 +0900 |
| commit | 5116789aa0abcf731aaad883ea99d79844b66a85 (patch) | |
| tree | 53c5f6af8e4b6a5c25fa1281cd1a4404a90ca062 /mrbgems/mruby-time | |
| parent | 96ac49b75b5981c7b286da8ef60236de5412d342 (diff) | |
| download | mruby-5116789aa0abcf731aaad883ea99d79844b66a85.tar.gz mruby-5116789aa0abcf731aaad883ea99d79844b66a85.zip | |
Fix UTC offset representation in `Time#to_s` on some environments; ref #4604
Use own implementation to calculate UTC offset on Visual Studio 2015 or
earlier or MinGW because `strftime("%z")` on these environments does not
conform C99.
Diffstat (limited to 'mrbgems/mruby-time')
| -rw-r--r-- | mrbgems/mruby-time/src/time.c | 43 | ||||
| -rw-r--r-- | mrbgems/mruby-time/test/time.rb | 3 |
2 files changed, 36 insertions, 10 deletions
diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index e3b5d3fe7..0d144c4e7 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -926,20 +926,45 @@ mrb_time_utc_p(mrb_state *mrb, mrb_value self) return mrb_bool_value(tm->timezone == MRB_TIMEZONE_UTC); } +static size_t +time_to_s_utc(mrb_state *mrb, struct mrb_time *tm, char *buf, size_t buf_len) +{ + return strftime(buf, buf_len, TO_S_FMT "UTC", &tm->datetime); +} + +static size_t +time_to_s_local(mrb_state *mrb, struct mrb_time *tm, char *buf, size_t buf_len) +{ +#if defined(_MSC_VER) && _MSC_VER < 1900 || defined(__MINGW64__) || defined(__MINGW32__) + struct tm datetime = {0}; + time_t utc_sec = timegm(&tm->datetime); + size_t len; + int offset; + + if (utc_sec == (time_t)-1) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time."); + } + offset = abs((int)(utc_sec - tm->sec) / 60); + datetime.tm_year = 100; + datetime.tm_hour = offset / 60; + datetime.tm_min = offset % 60; + len = strftime(buf, buf_len, TO_S_FMT, &tm->datetime); + buf[len++] = utc_sec < tm->sec ? '-' : '+'; + + return len + strftime(buf + len, buf_len - len, "%H%M", &datetime); +#else + return strftime(buf, buf_len, TO_S_FMT "%z", &tm->datetime); +#endif +} + static mrb_value mrb_time_to_s(mrb_state *mrb, mrb_value self) { char buf[64]; struct mrb_time *tm = time_get_ptr(mrb, self); - const char *fmt = tm->timezone == MRB_TIMEZONE_UTC ? TO_S_FMT "UTC" : TO_S_FMT "%z"; - size_t len = strftime(buf, sizeof(buf), fmt, &tm->datetime); - char *utf8; - mrb_value mrb_string; - buf[len] = '\0'; - utf8 = mrb_utf8_from_locale(buf, (int)len); - mrb_string = mrb_str_new_cstr(mrb, utf8); - mrb_utf8_free(utf8); - return mrb_string; + mrb_bool utc = tm->timezone == MRB_TIMEZONE_UTC; + size_t len = (utc ? time_to_s_utc : time_to_s_local)(mrb, tm, buf, sizeof(buf)); + return mrb_str_new(mrb, buf, len); } void diff --git a/mrbgems/mruby-time/test/time.rb b/mrbgems/mruby-time/test/time.rb index f59e27bc1..be1de7bc6 100644 --- a/mrbgems/mruby-time/test/time.rb +++ b/mrbgems/mruby-time/test/time.rb @@ -239,7 +239,8 @@ assert('Time#to_s') do end assert('Time#inspect') do - assert_match("2013-10-28 16:27:48 [^U]*", Time.local(2013,10,28,16,27,48).inspect) + assert_match("2013-10-28 16:27:48 [+-][0-9][0-9][0-9][0-9]", + Time.local(2013,10,28,16,27,48).inspect) end assert('day of week methods') do |
