Skip to content

Instantly share code, notes, and snippets.

@tmm1
Created February 6, 2013 06:07
Show Gist options
  • Save tmm1/4720711 to your computer and use it in GitHub Desktop.
Save tmm1/4720711 to your computer and use it in GitHub Desktop.
Fix marshal incompatibility between Date/DateTime on 1.8 and 1.9
require 'date'
class Date
if RUBY_VERSION < '1.9'
## accept 1.9 marshaled data on 1.8
## based on ext/date/date_core.c d_lite_marshal_dump_old
def marshal_load(data)
nth, jd, df, sf, of, @sg = data
real_jd =
if nth == 0
jd
else
jd + nth * (0xfffffff / 71149239 * 71149239)
end
if jd == 0 && sf == 0 && of == 0
@ajd = Rational.new!(real_jd * 2 - 1, 2)
else
df -= 86400 / 2
if df != 0
real_jd += Rational.new!(df, 86400)
end
if sf != 0
real_jd += Rational.new!(sf, 86400 * 1000000000)
end
@ajd = real_jd
@of = Rational.new!(of, 86400)
end
end
else
## accept 1.8 marshaled data on 1.9
## based on ruby/1.8/date.rb Date._load
class ::FakeRational
def to_r
Rational(@numerator, @denominator)
end
end
def self._load(str)
ajd, of, sg = Marshal.load(str.gsub("\rRational","\x11FakeRational"))
ajd = ajd.to_r if ajd.is_a?(FakeRational)
of = of.to_r if of.is_a?(FakeRational)
new.marshal_load([ajd, of, sg])
end
end
end
if __FILE__ == $0
require 'test/unit'
class MarshalCompatTest < Test::Unit::TestCase
def setup
# Marshal.dump(Date.today)
@date_obj = Date.parse('2013-02-05')
@date_18 = "\004\bu:\tDate=\004\b[\bo:\rRational\a:\021@denominatori\a:\017@numeratori\003\021\366Ji\000i\003\031\025#"
@date_19 = "\x04\bU:\tDate[\vi\x00i\x03\t{%i\x00i\x00i\x00f\f2299161"
# Marshal.dump(DateTime.now)
@datetime_obj = DateTime.parse('2013-02-05T19:33:03.123456789-08:00')
@datetime_18 = "\004\bu:\rDateTimeV\004\b[\bo:\rRational\a:\021@denominatorl+\b\000\000\305\2051\032:\017@numeratorl+\n\a\241\2477u\035\277\325\003\000o;\000\a;\006i\b;\ai\372i\003\031\025#"
@datetime_19 = "\x04\bU:\rDateTime[\vi\x00i\x03\n{%i\x02\xEF1i\x04\x15\xCD[\ai\xFE\x80\x8Ff\f2299161"
end
def test_decode_date
assert_equal @date_obj, Marshal.load(@date_18)
assert_equal @date_obj, Marshal.load(@date_19)
end
def test_decode_date_time
assert_equal @datetime_obj, Marshal.load(@datetime_18)
assert_equal @datetime_obj, Marshal.load(@datetime_19)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment