As you can see below, after serializing and unserializing, you get DateTime instances that are supposedly different:
scala> import org.joda.time.DateTime
import org.joda.time.DateTime
scala> val a = new DateTime()
a: org.joda.time.DateTime = 2014-01-08T19:00:08.883+02:00
scala> val b = DateTime.parse(a.toString())
b: org.joda.time.DateTime = 2014-01-08T19:00:08.883+02:00
scala> a == b
res0: Boolean = false
As per AbstractInstant's javadoc, equals
"compares this object with the specified object for equality based on the millisecond instant, chronology and time zone." So this shouldn't be happening right? What am I missing?
Here is the only right answer, found by own testing:
DateTime a = new DateTime(); // uses default time zone
System.out.println(a); // 2014-01-08T19:38:00.696+01:00
DateTime b = DateTime.parse(a.toString());
System.out.println(b); // 2014-01-08T19:38:00.696+01:00
System.out.println(a.getChronology()); // ISOChronology[Europe/Berlin]
System.out.println(b.getChronology()); // ISOChronology[+01:00]
System.out.println(a.equals(b)); // false!!!
I have assumed that in Scala the comparison by == indeed means comparison by equals() as @aris1348880 has stated in his comment, therefore I have replaced in the translation to java code the operator correspondingly.
So the cause of failed equals()-comparison is obvious: It is the time zone id which is not printed correctly in the toString()
-method of DateTime
object a
. I consider it as a bug in JodaTime because toString()
should always print the whole state of an immutable value object. By the way, in this detail old java.util.Date
is even worse! Well, as work around you can use the format engine of JodaTime in order to print out correctly.
System.out.println(
DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'['ZZZ']'").print(a));
// Output: 2014-01-08T19:38:00.696[Europe/Berlin]
To make the behaviour more clear:
The DateTime-constructor uses the default time zone (in my test Europe/Berlin). Its toString()-method prints the offset instead, not the real time zone (that is the problem).
The DateTime-parse()-method uses according to the JodaTime documentation ISODateTimeFormat#dateTimeParser() which again can only parse offsets, but in this code it was also feeded with just offset information, not with the real time zone, otherwise the parsing would have stopped with an exception.
In both cases instances of DateTime are created differently that is with different time zones / offsets and hence different chronologies. So the equals()-result is on first glance astonishing but understandable.
I opened an issue on GitHub, here is the author's response:
A long time ago I chose the toString format of DateTime, and I omitted to include the full state of the value type. As a result, two objects look like they are equal (by toString) but they are not. That was a mistake as it causes this kind of confusion. Unfortunately, it cannot be corrected.
The parsing behaviour is also unfortunate, as it focuses too much on the offset and not enough on the time-zone (as ISO-8601 does not handle time zone IDs). Again, its too late to make changes here.
I haven't org.joda.time.DateTime but I just tried a test with java.util.Date.
You should try this:
val a = new DateTime()
val b = new DateTime(a.getMillis())
a == b
I also tried this:
import org.joda.time.DateTime;
public class TestDateTime {
public static void main(String[] args) {
DateTime a = new DateTime();
System.out.println(a.toString());
DateTime b = DateTime.parse(a.toString());
System.out.println(b.toString());
System.out.println(a.equals(b));
}
}
and this is the output:
2014-01-08T19:05:52.182+01:00
2014-01-08T19:05:52.182+01:00
false
And the problem is that equals of DateTime fails because different time zone. I think it's wrong to assume equivalence of two DateTime instances created in such different way.
When you serialize and deserialize a java.util.Date the long (the wrapped value) is passed not a String.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With