From: nobu@... Date: 2014-05-14T06:28:43+00:00 Subject: [ruby-core:62576] [ruby-trunk - Bug #9836] Bad Implementation of Time.strptime Issue #9836 has been updated by Nobuyoshi Nakada. I guess the OP expects `%U` not to be ignored. ~~~diff diff --git a/lib/time.rb b/lib/time.rb index 3728fef..ec45767 100644 --- a/lib/time.rb +++ b/lib/time.rb @@ -194,13 +194,18 @@ class Time LeapYearMonthDays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] # :nodoc: CommonYearMonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] # :nodoc: - def month_days(y, m) + def month_days_of_year(y) if ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0) - LeapYearMonthDays[m-1] + LeapYearMonthDays else - CommonYearMonthDays[m-1] + CommonYearMonthDays end end + private :month_days_of_year + + def month_days(y, m) + month_days_of_year(y)[m-1] + end private :month_days def apply_offset(year, mon, day, hour, min, sec, off) @@ -432,7 +437,34 @@ class Time else year = d[:year] year = yield(year) if year && block_given? - t = make_time(date, year, d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:sec_fraction], d[:zone], now) + mon = d[:mon] + mday = d[:mday] + unless mon and mday + case + when (w = d[:wnum0]) # %U + range = 0..53 + mday = +1 + when (w = d[:wnum1]) # %W + range = 0..53 + mday = +2 + when (w = d[:cweek]) # %V + range = 1..53 + mday = -6 + end + if mday + raise ArgumentError, "invalid date" unless range.cover?(w) + t = make_time(date, year, 1, 1, nil, nil, nil, nil, d[:zone], now) + mday += w * 7 - t.wday + if w = d[:wday] || d[:cwday] + mday += w + end + month_days_of_year(t.year).each_with_index do |n, m| + break mon = m+1 if mday <= n + mday -= n + end + end + end + t = make_time(date, year, mon, mday, d[:hour], d[:min], d[:sec], d[:sec_fraction], d[:zone], now) end t end ~~~ ---------------------------------------- Bug #9836: Bad Implementation of Time.strptime https://bugs.ruby-lang.org/issues/9836#change-46720 * Author: Max Anselm * Status: Feedback * Priority: Normal * Assignee: * Category: * Target version: * ruby -v: ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-linux] * Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN ---------------------------------------- According to the documentation, `Time.strptime` "parses +date+ using `Date._strptime` and converts it to a Time object." However this conversion is extremely naive, using only certain fields return by `Date._strptime` and ignoring the rest (for example `:wnum0`). This creates confusing and inconsistent behavior when compared to `Date` and `DateTime`'s `strptime` methods. For example: ``` puts Date.strptime('201418', "%Y%U") => 2014-05-04 puts DateTime.strptime('201418', "%Y%U") => 2014-05-04T00:00:00+00:00 puts Time.strptime('201418', "%Y%U") => 2014-01-01 00:00:00 -0500 ``` -- https://bugs.ruby-lang.org/