I was trying to sort out a YAML parsing issue on Windows XP SP 2 and
traced it to Time.gm failing on pre-1970 dates ... this works fine on
both Ubuntu Linux and my Mac... Any ideas or workarounds?
Control Panel -> Regional and Language Options -> Regional Options -> Customize... -> Date -> "Calendar"
You'll find the default time ranges for date assumptions.
It's quite likely that ruby doesn't use these though.
···
On 3 Jan 2008, at 14:12, Tim Ferrell wrote:
I was trying to sort out a YAML parsing issue on Windows XP SP 2 and
traced it to Time.gm failing on pre-1970 dates ... this works fine on
both Ubuntu Linux and my Mac... Any ideas or workarounds?
I'd expect it to be the other way around, when using Time as opposed to Date:
···
On Jan 3, 2008, at 12:12 PM, Tim Ferrell wrote:
I was trying to sort out a YAML parsing issue on Windows XP SP 2 and
traced it to Time.gm failing on pre-1970 dates ... this works fine on
both Ubuntu Linux and my Mac... Any ideas or workarounds?
In message "Re: Time.gm(1969) chokes on Windows" on Fri, 4 Jan 2008 03:12:31 +0900, Tim Ferrell <s0nspark@gmail.com> writes:
I was trying to sort out a YAML parsing issue on Windows XP SP 2 and
traced it to Time.gm failing on pre-1970 dates ... this works fine on
both Ubuntu Linux and my Mac... Any ideas or workarounds?
As many pointed out, Windows time library (probably intentionally)
does not support pre-1970 time. Until Microsoft fixes the bug (or
spec), we can't help it. The alternative is implementing our own time
handling functions but I don't think we have enough resource.
It handled any date you'd care to throw at it and 1969/1970 is not an issue.
-Rob
···
On Jan 3, 2008, at 1:20 PM, James Tucker wrote:
It may or may not be related, but check in:
Control Panel -> Regional and Language Options -> Regional Options -> Customize... -> Date -> "Calendar"
You'll find the default time ranges for date assumptions.
It's quite likely that ruby doesn't use these though.
On 3 Jan 2008, at 14:12, Tim Ferrell wrote:
I was trying to sort out a YAML parsing issue on Windows XP SP 2 and
traced it to Time.gm failing on pre-1970 dates ... this works fine on
both Ubuntu Linux and my Mac... Any ideas or workarounds?
Hi,
As many pointed out, Windows time library (probably intentionally)
does not support pre-1970 time. Until Microsoft fixes the bug (or
spec), we can't help it. The alternative is implementing our own time
handling functions but I don't think we have enough resource.
matz.
Hello matz - I do understand both sides of this - Window is "broken" in
this respect and working around it is (pardon the pun) time consuming...
It would be helpful, at least, to have Syck fall back to using DateTime
when Time.gm fails though... this is what the Rails core extensions in
ActiveSupport do to work around the overflow...
Thanks Rob, but unfortunately I am not the one doing the parsing - YAML
is... and it uses Time.gm/Time.utc, which are apparently "built-in"
functions in Ruby (i.e. implemented in C) ... I can't help but think
this is just a setting somewhere...
I checked my regional settings (as James Tucker suggested) but that
setting only appears to affect how Windows interprets 2-digit years.
Ruby must be doing some kind of system api call for this and it is just
limited on Windows...
Any other thoughts?
Rob Biedenharn wrote:
···
If you want a date, use Date. (require 'date')
It handled any date you'd care to throw at it and 1969/1970 is not an
issue.
Thanks Rob, but unfortunately I am not the one doing the parsing - YAML
is... and it uses Time.gm/Time.utc, which are apparently "built-in"
functions in Ruby (i.e. implemented in C) ... I can't help but think
this is just a setting somewhere...
I checked my regional settings (as James Tucker suggested) but that
setting only appears to affect how Windows interprets 2-digit years.
Ruby must be doing some kind of system api call for this and it is just
limited on Windows...
Nope. It's not going to work on windows. You can always force the value in
the YAML file to be a string by prepending it with !str, and then you can
convert it however you want in your script.
Thanks Rob, but unfortunately I am not the one doing the parsing - YAML
is... and it uses Time.gm/Time.utc, which are apparently "built-in"
functions in Ruby (i.e. implemented in C) ... I can't help but think
this is just a setting somewhere...
I checked my regional settings (as James Tucker suggested) but that
setting only appears to affect how Windows interprets 2-digit years.
Ruby must be doing some kind of system api call for this and it is just
limited on Windows...
Any other thoughts?
Rob Biedenharn wrote:
> If you want a date, use Date. (require 'date')
>
> It handled any date you'd care to throw at it and 1969/1970 is not an
> issue.
--
Posted via http://www.ruby-forum.com/.
Nope. It's not going to work on windows. You can always force the
value in
the YAML file to be a string by prepending it with !str, and then you
can
convert it however you want in your script.
Well, in this case I have no control over how the yaml file gets
created...
This just seems to me to be a bad design decision somewhere. Why would
YAML use Time.gm to deserialize rather than DateTime given the fact that Time.gm behavior is so system-dependent?!
What I ended up doing to work around this temporarily was get a hold of
the pure ruby yaml library, RbYAML, and hacked the timestamp code to use
DateTime.parse instead of Time.gm - I haven't finished fully testing it
yet and I may be missing some kind of big issue as well, but it seems to
work at the moment.
This, in concert with the Rails ActiveSupport Date/Time/DateTime core
extensions gives me some ability to work with timestamps in a fairly
interchangeable fashion but... honestly, this kind of thing sucks!
Having two seemingly similar timestamp classes just leads to confusion,
especially with those new to the language! The fact that their APIs
aren't similar doesn't help matters, as that must end up dictating which
to use in some cases... IMO, DateTime and Time objects should be fully
interchangeable!
You still haven't shown the exact format of the string that YAML doesn't parse the way you want. I showed you that the format of the string influences whether YAML creates a Date or a Time object. If you have a string that appears to be in the format of a time, but is outside the range of a Time object (on your platform), there may not be any way to get YAML to do what you want. You can either get a better platform or preprocess the YAML to add the type specifier !str as Jamey suggests. (Or perhaps some other hackery to change how YAML treats timestamps on your platform.)
Nope. It's not going to work on windows. You can always force the
value in
the YAML file to be a string by prepending it with !str, and then you
can
convert it however you want in your script.
Well, in this case I have no control over how the yaml file gets
created...
You still haven't shown the exact format of the string that YAML
doesn't parse the way you want. I showed you that the format of the
string influences whether YAML creates a Date or a Time object. If
you have a string that appears to be in the format of a time, but is
outside the range of a Time object (on your platform), there may not
be any way to get YAML to do what you want. You can either get a
better platform or preprocess the YAML to add the type specifier !str
as Jamey suggests.
Obviously the string in question is a timestamp - YAML/Syck handles
plain pre-1970 dates just fine. So, assuming I have valid pre-1970
timestamps to deal with, I am left with no choice BUT to work around
Syck's (IMO shortsighted) choice of using Time.gm rather than DateTime,
which I'm fairly certain was done for performance reasons... Still, it
seems a rather bad choice given that it is not always portable.
My workaround was to drop Syck for this app and use a customized version
of RbYAML, as mentioned in my previous post.
As for the "better platform" comment - believe me, it is not my choice
to use Windows for this particular case but, given some constraints I am
in no position to address right now, there is no other option.
I am left with no choice BUT to work around
Syck's (IMO shortsighted) choice of using Time.gm rather than DateTime,
which I'm fairly certain was done for performance reasons...
I find it unfortunate to still see a difference of behaviour for the
Time class, depending on your runtime platform. I don't expect each
library developer to actually care for that personally.
I have been littl'bitten (caught it thanks to unit tests a while
back and was kind of disappointed to discover this !
Does anyone know if there are plans to make Time behaviour
'homogeneous' ? (like: fixing the Windows version maybe ?)
Obviously the string in question is a timestamp - YAML/Syck handles
plain pre-1970 dates just fine. So, assuming I have valid pre-1970
timestamps to deal with, I am left with no choice BUT to work around
Syck's (IMO shortsighted) choice of using Time.gm rather than DateTime,
which I'm fairly certain was done for performance reasons... Still, it
seems a rather bad choice given that it is not always portable.
I'm gonna have to call bullshit on this one, given that you were asked twice to provide the bad YAML in question and it never materialized, but especially given that the following seems to work just fine:
>> YAML.dump(Time.gm(1969, 1, 1))
=> "--- 1969-01-01 00:00:00 Z\n"
>> YAML.load(YAML.dump(Time.gm(1969, 1, 1)))
=> Wed Jan 01 00:00:00 UTC 1969
I am left with no choice BUT to work around
Syck's (IMO shortsighted) choice of using Time.gm rather than DateTime,
which I'm fairly certain was done for performance reasons...
I find it unfortunate to still see a difference of behaviour for the
Time class, depending on your runtime platform. I don't expect each
library developer to actually care for that personally.
I have been littl'bitten (caught it thanks to unit tests a while
back and was kind of disappointed to discover this !
Does anyone know if there are plans to make Time behaviour
'homogeneous' ? (like: fixing the Windows version maybe ?)
Well, the bug tracker would be a good place to start
Ryan, was this on a non-Windows device? IIRC, it is not Ruby or YAML that
is the culprit, but the underlying OS library that Ruby's Time class uses.
The OS library works fine on Unix-based platforms. It is only the
underlying Windows library that has an issue with times prior to 1970.
But you are correct, Tim can bitch as long as he wants about Syck's
shortsitedness, but he should really be bitching that the underlying Windows
library can't handle pre-1970 times.
> Obviously the string in question is a timestamp - YAML/Syck handles
> plain pre-1970 dates just fine. So, assuming I have valid pre-1970
> timestamps to deal with, I am left with no choice BUT to work around
> Syck's (IMO shortsighted) choice of using Time.gm rather than
> DateTime,
> which I'm fairly certain was done for performance reasons... Still, it
> seems a rather bad choice given that it is not always portable.
I'm gonna have to call bullshit on this one, given that you were asked
twice to provide the bad YAML in question and it never materialized,
but especially given that the following seems to work just fine:
>> YAML.dump(Time.gm(1969, 1, 1))
=> "--- 1969-01-01 00:00:00 Z\n"
>> YAML.load(YAML.dump(Time.gm(1969, 1, 1)))
=> Wed Jan 01 00:00:00 UTC 1969
I'm gonna have to call bullshit on this one, given that you were asked
twice to provide the bad YAML in question and it never materialized,
but especially given that the following seems to work just fine:
>> YAML.dump(Time.gm(1969, 1, 1))
=> "--- 1969-01-01 00:00:00 Z\n"
>> YAML.load(YAML.dump(Time.gm(1969, 1, 1)))
=> Wed Jan 01 00:00:00 UTC 1969
Ryan, you obviously didn't follow closely enough... That code simply
does not work on Windows.
ArgumentError: time out of range
from (irb):2:in 'gm'
from (irb):2
Nor does this:
Yaml.load("--- 1969-01-01 00:00:00 Z")
ArgumentError: time out of range
from C:/Ruby/lib/ruby/1.8/yaml/rb:133:in 'utc'
from C:/Ruby/lib/ruby/1.8/yaml/rb:133:in 'node_import'
from C:/Ruby/lib/ruby/1.8/yaml/rb:133:in 'load'
from C:/Ruby/lib/ruby/1.8/yaml/rb:133:in 'load'
from (irb):3
And yes, Jamey, it is not Syck's fault that the Time class is broken in
this way on Windows. Syck could have alleviated some of the pain by
making the more sensible (i.e. portable, reliable) choice of using
DateTime to deserialize, but the bottom line IMO is that this is a core
issue and should be fixed.