Why does Java's Date.after() return 'true' when the date is actually earlier?

  • A+

I had a program where I compared two dates with each other; even though date1 was before date2, date1.after(date2) returned true. Time zones had no effect; both dates were in UTC.

import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone;  public class Test {     public static void main(String[] args) throws Exception {         TimeZone.setDefault(TimeZone.getTimeZone("Etc/UTC"));         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");         Date date1 = dateFormat.parse("2018-07-27 01:22:14.077");         Date date2 = new Timestamp(1532654534390l);         System.out.println(dateFormat.format(date1));         System.out.println(dateFormat.format(date2));         System.out.println(date1.getTime() > date2.getTime());         System.out.println(date1.after(date2));     } } 

This outputs:

2018-07-27 01:22:14.077
2018-07-27 01:22:14.390

What is happening here?

In my real program, date1 is parsed from a log file and date2 is retrieved from the database by Hibernate, which causes the different data types. Even though I found the root cause and know how to avoid the problem, I'm still very interested in solutions which prevent this pitfall.


The underlying 'problem' here is that java.sql.Timestamp, while extending java.util.Date, doesn't store milliseconds in the designated field (fastTime, equivalent to Unix time), but in a separate field nanos. The after method only considers the fastTime field (which makes sense, since it can be used on all Date objects).

What happens in this situation is that the fastTime of the Timestamp is rounded down from 1532654534390 to 1532654534000, which is lower than the 1532654534077 of the other date (and lower means an earlier date). Therefore, after() and before() are not reliable in this case; the solution is to use getTime() (which is overloaded for Timestamp to provide the correct value) on both dates and compare those.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: