Java for C# Programmers 5: Date & Time

Date, Calendar And Joda-Time

Very early developers found out that Java’s Date class is bad and it is not possible to improve it. Because of this, most methods of Java’s Date class are deprecated now and early the class Calendar has been added.

But soon after adding Calendar, people realized that Calendar is not very good as well. Then development of the successor API Joda-Time started.

Joda-Time is available from Java SE 8 on. It is located in the namespace java.time and contains the main classes LocalDate, LocalTime and LocalDateTime. Joda-Time contains full support of timezones with classes ZoneId, ZonedDateTime, OffsetTime, OffsetDateTime and ZoneOffset. The older class java.util.TimeZone is deprecated.

Joda-Time supports periods of time with the classes Period and Duration. Both are similar to C#’s TimeSpan. Period and Duration deal with different precisions.

// 3 years, 2 months, 1 day
Period period = Period.of(3, 2, 1);

// You can modify the values of dates using periods
LocalDate newDate = oldDate.plus(period);

// Components of a Period are represented by ChronoUnit values
assertEquals(1, period.get(ChronoUnit.DAYS)); 

// A duration of 3 seconds and 5 nanoseconds
Duration duration = Duration.ofSeconds(3, 5);

As expected, you can add and subtract durations and you can modify date values with durations.

Joda-Time also contains

  • Chronolgy and associated classes to represent calendars different from the Gregorian calendar.
  • MonthDay to represent a birthday.
  • YearMonth to represent a credit card expiration date.

From Java SE 8 on all three date-time systems (Date, Calendar and Joda-Time) exist in Java in parallel.

Date Formatting

Locale Specific

It is easy to format a Date in a localized way.

DateFormat daf = DateFormat.getDateInstance(DateFormat.SHORT, 
        Locale.German);
Date now = new Date();         // new Date() is now. 
String s = daf.format(now);    // "15.05.14"  for 15th of May 2014

DateFormat tif = DateFormat.getTimeInstance(DateFormat.SHORT, 
        Locale.German);
String z = tif.format(now);    // "09:54"     for 9:54 AM

// uses the current locale
DateFormat.getDateInstance(DateFormat.SHORT); 

// long date and short time combined
DateFormat dtf = DateFormat.getDateTimeInstance(DateFormat.LONG,
        DateFormat.SHORT, Locale.GERMAN);
String a = dtf.format(now);   // "15. Mai 2014 09:54"

These are the available style constants and the resulting output for 15th of May 2014, 09:51:17 o’clock with locale ENGLISH.

Style Date Time
DateFormat.SHORT 5/15/14 9:51 AM
DateFormat.MEDIUM May 15, 2014 9:51:17 AM
DateFormat.LONG May 15, 2014 9:51:17 AM CEST
DateFormat.FULL Thursday, May 15, 2014 9:51:17 AM CEST

Extended Date Formatting

You have full control over your date format with the class SimpleDateFormat and format placeholder strings.

    now = new Date(114, 0, 17, 14, 15, 16);  

    daf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    System.out.println(daf.format(now));        // 2014-01-17 14:15:16

    daf = new SimpleDateFormat("dd. MMM yy HH:mm");
    System.out.println(daf.format(now));        // 17. Jan 14 14:15

Gotcha: The format strings in Java are quite similar to those used in C#, but not identical. Look there for details:
http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html.

Date Oddities

If you are using Java’s Date, be aware of its oddities.

  • getMonth() is zero-based.
  • getDay() returns the day of week, not the day of month.
  • getDate() returns the day of month, 1-based.
  • getYear() returns the gregorian year minus 1900.

If today was Tuesday, 13th of May 2014…

Date d = new Date();
String z = String.format("%04d-%02d-%02d", 
        d.getYear(), d.getMonth(), d.getDay());
System.out.println(z);

Gotcha: this would print 0114-04-02. Not one of the three numbers is what I would have expected before having studied the intricacies of Date.

Stopwatch

There’s nothing like C#’s Stopwatch in plain Java. There are stopwatches available in org.apache.commons.lang.time.StopWatch and one in com.google.common.base.Stopwatch.

If you don’t want to pull in these packages, you can use
System.currentTimeMillis() or System.nanoTime() to imitate a simple stopwatch.

Function Returns
System.currentTimeMillis() Returns the current time in milliseconds. Date d = new Date(System.currentTimeMillis()) will represent the current time.
System.nanoTime() Returns nanoseconds since some fixed but arbitrary origin time which even may vary between different instances of Java VMs. Only use nanoTime() for profiling.