Nuxeo Core Developer Guide

Writing tests working with dates

Updated: November 4, 2022

java.util.Date methods are almost all deprecated

Consider java.util.Date as a time container with only basic methods:

  • public Date()
  • public long getTime()
  • public void setTime(long time)
  • public boolean before([Date]( "class in java.util") when)
  • public boolean after([Date]( "class in java.util") when)
  • public boolean equals([Object]( "class in java.lang") obj)
  • public int compareTo([Date]( "class in java.util") anotherDate)
  • public int hashCode()
  • public [String]( "class in java.lang") toString()

Although all other methods were very useful (especially the parse() one), they are deprecated as of JDK 1.1 and must not be used. Instead, it is recommended to use Calendar and DateFormat.

Date parsing

There is no equivalent to the public static long parse(String s) method. All other methods (either from DateFormat or other frameworks) require to explicitly set the format before parsing.

Recommended classes are SimpleDateFormat and DateTimeFormatter (from Joda Time).

Sample recommended usages

new java.text.SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy", Locale.ENGLISH);
org.joda.time.format.DateTimeFormat.forPattern("EEE MMM d HH:mm:ss zzz yyyy").withLocale(Locale.ENGLISH);
new java.util.GregorianCalendar(TimeZone.getTimeZone("+0100"), Locale.FRENCH);

The SimpleDateFormat class is not thread-safe.

Recommendations (from the worst to the best, in terms of performance) are:

  • use SimpleDateFormat.getDateInstance(),
  • externally synchronize the DateFormat instances usage,
  • use a ThreadLocal<DateFormat>.


Here's an implementation allowing to use the ThreadLocal approach with various formats:

Tests must not depend on the timezone

Be warned that Calendar and GregorianCalendar are locale-sensitive classes.

When writing a test, focus on effectively testing the code, not the data setup: construct fixed locale parsers and calendars, put asserts and comparisons on reliant values such as **getTime()** (the millisecond offset from the Epoch) instead of toString().