A
anon luker
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, ffset=>-14400, :min=>37,
:mon=>4, :sec=>35, :year=>2004} (correct)
p Date._parse(s2) #{:hour=>14, :mday=>26, ffset=>-14400, :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})
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, ffset=>-14400, :min=>37,
:mon=>4, :sec=>35, :year=>2004} (correct)
p Date._parse(s2) #{:hour=>14, :mday=>26, ffset=>-14400, :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})