0

I have written some class encode decode routines to json and back. This works except for one explicit type which is Date

without showing the complete library, here is my problem

Date now = Date.newInstance()
println "now : $now"
Date reconverted = new SimpleDateFormat('EEE MMM dd HH:mm:ss Z yyyy').parse(now.toString())
println "reconverted : $reconverted"

assert reconverted == now  //this assertion fails 

if you look at the output string text for both they are the same. But the 'reconverted' object is not equal to the 'now' object.

Is this due to lost precision somewhere in Date? I had assumed that the reconstructed value would be equal.

This is just a problem as i cannot assert that my encoded/decoded class instance are the same, if the class has Date fields

I don't have this problem with LocalDateTime encode/decode where my decode parse looks like this

LocalDateTime.parse (jsonStrValue) 

when when i check for equivalence works just fine

What am i missing for Date that stops this working ?

WILLIAM WOODMAN
  • 1,185
  • 5
  • 19
  • 36
  • 4
    You've essentially truncated milliseconds. – Sotirios Delimanolis May 15 '20 at 14:48
  • 1
    *"Is this due to lost precision somewhere in Date?"* Yes, the milliseconds in the original date value has been lost. – Andreas May 15 '20 at 15:33
  • 2
    I recommend you don’t use `Date`. That class is poorly designed and long outdated. Instead use `Instant` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). It will also parse back to an equal `Instant` object, even without any explicit formatter. More in [my answer here](https://stackoverflow.com/a/56374732/5772882). – Ole V.V. May 15 '20 at 20:30
  • 1
    By the way, that format is a terrible choice for exchanging date-time values as text. Learn about [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601). – Basil Bourque May 16 '20 at 00:22
  • 2
    The `java.util.Date` class was years ago supplanted by `java.time.Instant`. – Basil Bourque May 16 '20 at 00:23
  • I agree the the use of Date is not current but this is a generic library and so Dates will still be found objects that need to be encoded. so my problem was that the standard toString() drops the milliseconds. Fixing this seems to be resolved (using older libraries) using SimpleDateFormat and format string that adds the milissecond precision. like this `SimpleDateFormat sdtf = new SimpleDateFormat('EEE MMM dd HH:mm:ss.SSS z yyyy')` then you encode for json (using same format approach as toString() as `String fds = sdtf.format (now)` – WILLIAM WOODMAN May 18 '20 at 14:59
  • then you can parse that string back `Date parsedDate = sdtf.parse(fds)` and finally assert the equality `assert parsedDate == now` which now works. In reality I have opted to use the more refined Date.toLocalDate() and encoded from that and decoded back to date using LDT as the intermediary. Thanks to all for pointing out the missed precision digits implicit in the standard toString() format for dates which was the basic cause of my original problem – WILLIAM WOODMAN May 18 '20 at 15:03

1 Answers1

1

As noted in comments, your parse excludes milliseconds. You can use some java.util.Date extension methods to get a comparable result, if you are not interested in the time.

def today = new Date().clearTime() // requires groovy-dateutil library for Groovy 2.5+
def parsed = Date.parse('EEE MMM dd HH:mm:ss Z yyyy', today.toString())
assert parsed == today
emilles
  • 1,104
  • 7
  • 14