Closed emchristiansen closed 10 years ago
I am also having this issue.
scala> import scala.pickling._
scala> import json._
scala> import org.joda.time.DateTime
scala> val date = DateTime.now
date: org.joda.time.DateTime = 2013-09-23T15:59:46.201-06:00
scala> date.pickle
res1: scala.pickling.json.JSONPickle =
JSONPickle({
"tpe": "org.joda.time.DateTime"
})
Tried it with JSON serialization, there are no populated members, just the type. The parameterless constructor and DateTime.now both yield an object with current system timestamp.
Also fails for DateTime with specified constructor. The result of the deserialization is the current time.
scala> val date = new DateTime(2013, 9, 1, 21, 50, 21)
date: org.joda.time.DateTime = 2013-09-01T21:50:21.000-06:00
scala> date.pickle
res2: scala.pickling.json.JSONPickle =
JSONPickle({
"tpe": "org.joda.time.DateTime"
})
scala> date.pickle.unpickle[DateTime]
res3: org.joda.time.DateTime = 2013-09-23T16:04:23.494-06:00
})
I got this working by defining a custom SPickler/Unpickler implementation, using exported ISO 8601 string and corresponding constructor.
import org.joda.time._
import scala.pickling._
import scala.pickling.binary._
import org.scalatest._
class PicklingSpec extends FunSpec with matchers.ShouldMatchers {
class CustomDateTimePickler(implicit val format: PickleFormat)
extends SPickler[DateTime] with Unpickler[DateTime] {
def pickle(picklee: DateTime, builder: PBuilder) {
builder.beginEntry(picklee)
builder.putField("iso8601", b =>
b.hintTag(FastTypeTag.ScalaString).beginEntry(picklee.toString()).endEntry())
builder.endEntry()
}
def unpickle(tag: => FastTypeTag[_], reader: PReader): DateTime = {
reader.beginEntry()
val date = reader.readField("iso8601").unpickle[String]
reader.endEntry()
new DateTime(date)
}
}
implicit def customDateTimePickler(implicit format: PickleFormat) = new CustomDateTimePickler()
describe("Playing with custom pickling") {
it("should pickle dates correctly") {
val date = new DateTime(2013, 9, 5, 20, 8, 13)
date.pickle.unpickle[DateTime] should be (date)
}
}
}
Which returns correctly
% sbt test
....
[info] PicklingSpec:
[info] Playing with pickling
[info] - should pickle dates correctly
....
Nothing to add except for a "me too" and heartfelt thanks to yashton for providing the custom SPickler/Unpickler implementation.
Thanks yashton, works perfectly.
From my side another "need this". Joda is just such a widely used lib so that integration should be part of pickling imho.
Thanks yashton. Was scratching my head on this one!
This is fixed by #211.
While it would be nice to include these custom picklers/unpicklers in the library, it puts a dependency on jodadate time, which I'm sure most users don't want (we'd be tied to whatever version we pull in in the pickling library).
Instead, we fixed the (difficult-to-fix) root cause. Which is detecting when stuff comes from Java, and then handling Java's getters/setters. It comes down to differences between constructors in Java and Scala that caused this bug – and now we differentiate between Java and Scala and do the correct thing.
When picking then unpickling a
DateTime
, the original value of theDateTime
is lost, replaced with the current time.Here's a console session: