From: hatespyware@... (anon luker) Date: 2004-04-29T08:29:02+09:00 Subject: Date._parse vs Time.parse [repost w/ minor corrections] Hi folks, While doing some WMI stuff in Ruby, I noticed that my datetimes were getting all messed up. A brief inspection showed that the ddd parser in Date._parse was missing the UTC offset for the CIM datetimes that MS uses for WMI (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/date_and_time_format.asp). Adding support for the WMI datetime format in Date._parse (and thusly Time.parse via ParseDate.parsedate) is a snap, but it looks like the Ruby date/time system is unable to gracefully handle cases where an offset is specified with a number instead of a region (EST, EDT, etc). Date._parse parses them, but ParseDate just (incorrectly, I think) drops them without consideration. ex: #!/usr/bin/ruby require 'Time' require 'Date' now = Time.now s1 = now.strftime('%Y%m%d%H%M%S.000000-240') #pretend we're on the east coast s2 = now.strftime('%Y%m%d%H%M%S.000000-360') #pretend we're on the west coast p Date._parse(s1) #{:hour=>14, :mday=>26, :offset=>-14400, :min=>37, :mon=>4, :sec=>35, :year=>2004} (correct) p Date._parse(s2) #{:hour=>14, :mday=>26, :offset=>-21600, :min=>37, :mon=>4, :sec=>35, :year=>2004} (correct) p Date._parse(s1) == Date._parse(s2) #false (correct) p Time.parse(s1) #Mon Apr 26 14:37:35 Eastern Daylight Time 2004 (The offset was ignored on both of these) p Time.parse(s2) #Mon Apr 26 14:37:35 Eastern Daylight Time 2004 (inputs - the EDT is for _my_ local tz ) p Time.parse(s1) == Time.parse(s2) #true (definitely not correct) The obvious workaround is to convert all times to machine local time when parsing them in Date._parse, but I don't like losing that information to the classes that properly handle the offset and call _parse directly (like DateTime). Am I missing something, or is this a problem? Thanks, Prs p.s. sorry for my awful formatting. ruby 1.8.0 (2003-08-04) [i386-mswin32] +++ format.rb @@ -361,6 +361,28 @@ year, mon, mday = mon, mday, year end + # MS WMI CIM datetimes (ms-help://MS.VSCC/MS.MSDNVS/wmisdk/r_mof_3ovo.htm) + #yyyymmddHHMMSS.mmmmmmsUUU + elsif str.sub!(/([\d*]{4})([\d*]{2})([\d*]{2})([\d*]{2})([\d*]{2})([\d*]{2})\.[\d*]{6}([-+*])([\d*]{3})/no,' ') + year = $1.to_i if $1 != '*' * 4 + mon = $2.to_i if $1 != '*' * 2 + mday = $3.to_i if $1 != '*' * 2 + hour = $4.to_i if $1 != '*' * 2 + min = $5.to_i if $1 != '*' * 2 + sec = $6.to_i if $1 != '*' * 2 + offset = 60*($7+$8).to_i if $7 != '*' and $8 != '*' * 3 + comp = false + # MS WMI CIM datetimes (ms-help://MS.VSCC/MS.MSDNVS/wmisdk/r_mof_3ovo.htm) + #yyyy-mm-dd HH:MM:SS:mmm + elsif str.sub!(/([\d*]{4})-([\d*]{2})-([\d*]{2})\s([\d*]{2}):([\d*]{2}):([\d*]{2}):[\d*]{3}/no,' ') + year = $1.to_i if $1 != '*' * 4 + mon = $2.to_i if $1 != '*' * 2 + mday = $3.to_i if $1 != '*' * 2 + hour = $4.to_i if $1 != '*' * 2 + min = $5.to_i if $1 != '*' * 2 + sec = $6.to_i if $1 != '*' * 2 + comp = false + # ddd elsif str.sub!( /([-+]?)(\d{4,14})