YAML and DateTime


#1

It seems that cannot store instances of DateTime, but instead stores
them
as Time.

irb(main):001:0> require “yaml”
=> true
irb(main):003:0> YAML.load(DateTime.now.to_yaml).class
=> Time

This causes issues when you have a DateTime that is out of range of Time

irb(main):005:0> date_time = DateTime.new(2041,1,1)
=> #<DateTime: 4933041/2,0,2299161>
irb(main):006:0> YAML.load(date_time.to_yaml)
ArgumentError: time out of range
from /usr/local/lib/ruby/1.8/yaml.rb:133:in utc' from /usr/local/lib/ruby/1.8/yaml.rb:133:innode_import’
from /usr/local/lib/ruby/1.8/yaml.rb:133:in load' from /usr/local/lib/ruby/1.8/yaml.rb:133:inload’
from (irb):6

Does anyone have a fix or workaround for this?

Thanks,

Paul McMahon


#2

There’s a workarount you can do,
in /usr/local/lib/ruby/1.8/yaml/rubytypes.rb you have this definition of
#to_yaml on Date class.

1 class Date
2 yaml_as “tag:yaml.org,2002:timestamp#ymd”
3 def to_yaml( opts = {} )
4 YAML::quick_emit( self, opts ) do |out|
5 out.scalar( “tag:yaml.org,2002:timestamp”, self.to_s, :plain )
6 end
7 end
8 end

What I do in my Rails app is to overide this implementation,

1 class Date
2 yaml_as “tag:yaml.org,2002:timestamp#ymd”
3 def to_yaml( opts = {} )
4 YAML::quick_emit( self, opts ) do |out|
5 out.scalar( “tag:yaml.org,2002:timestamp”, self.to_s(:utc), :plain
)
6 end
7 end
8 end

“self.to_s(:utc)” is the difference in line 5.It works for me.

I hope this help.
Bye.
Juan M…