0

I was trying to get month value. But I wanted to check which is better, java.util or java.time to retrieve month value. This is my code to check performance of Calender vs ZonedDateTime.

    //import java.time.Instant;
    //import java.time.ZonedDateTime;
    //import java.util.Calendar;

    Instant instant, instant2; 
    String diff;

    instant = Instant.now();
    int month2 = Calendar.getInstance().get(Calendar.MONTH) + 1;
    instant2 = Instant.now();
    diff = String.valueOf(instant2.getNano() - instant.getNano());
    System.out.println("month value " + month2 + "at: " + diff);

    instant = Instant.now();
    int month1 = ZonedDateTime.now().getMonth().getValue();
    instant2 = Instant.now();
    diff = String.valueOf(instant2.getNano() - instant.getNano());
    System.out.println("month value " + month1 + "at: " + diff);

I thought java.time was better than java.util. Hence I was expecting ZonedDateTime to perform better than Calendar. But here I found the inverse. My result was:

month value 6at: 0  //Calendar
month value 6at: 9000000 //ZonedDateTime

Any ideas why this is happening. And any suggestion on why I should thus use java.util.Calender instead of java.timeZonedDateTime.

P.S. I even reversed retrieving month2 after month1 as:

    Instant instant, instant2; 
    String diff;

    instant = Instant.now();
    int month1 = ZonedDateTime.now().getMonth().getValue();
    instant2 = Instant.now();
    diff = String.valueOf(instant2.getNano() - instant.getNano());
    System.out.println("month value " + month1 + "at: " + diff);

    instant = Instant.now();
    int month2 = Calendar.getInstance().get(Calendar.MONTH) + 1;
    instant2 = Instant.now();
    diff = String.valueOf(instant2.getNano() - instant.getNano());
    System.out.println("month value " + month2 + "at: " + diff);

Still same:

month value 6at: 8000000   //ZonedDateTime
month value 6at: 0  //Calendar
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Ujjwal Jung Thapa
  • 604
  • 2
  • 8
  • 31
  • 5
    you should not use obesolete `java.util` time classes becauses they contain bugs. From Java 8 classes from `java.time` should be preffered. corectness > performance. – Michał Krzywański Jun 30 '19 at 11:40
  • 3
    There is no doubt whatsoever that java.time is better. The fact alone that for `Calendar` you have to add 1 and the reader needs to understand why you add 1. Awful. Bad. A lot more important than performance, for 99.5 % of cases. – Ole V.V. Jun 30 '19 at 12:18
  • I’m guessing it is faster because simply importing the Calendar class causes the static instance of Calendar to become instantiated before any of your benchmarking code runs, whereas with ZonedDateTime.now() you’re creating a new instance. There are 10^6 nanos per milli, so the big number you’re seeing is really only 8ms. – Blake Jun 30 '19 at 14:46
  • @Blake In all fairness `Calendar.getInstance()` is creating a new instance too. – Ole V.V. Jun 30 '19 at 16:53
  • @OleV.V. Are you sure? That’s a static instance and therefore I assume it was instantiated before the call to `getInstance` is made. As I was implying, simply importing `Calendar` will create that instance regardless of whether you call `getInstance` to retrieve the reference or not. I might be wrong. – Blake Jun 30 '19 at 16:55
  • @Blake What I do know for sure is (1) in most locales you are really getting an instance of `GregorianCalendar` (2) two calls to `getInstance` must return two distinct instances. So I wouldn’t expect the first of them to be already created. – Ole V.V. Jun 30 '19 at 17:34

1 Answers1

7

The design goals of java.time included clear and expected behaviour, immutable objects, thread-safety, leveraging of standards, and a number of other points. The goals did not include performing faster than the old date-time classes including Calendar. Also, while I have heard numerous complaints about the old classes, I have heard no complaints that they performed too poorly.

If the far superior design of the modern API in some cases costs a performance penalty, I don’t think that we should be surprised nor worried.

Your measurements are not trustworthy, though. Doing a correct benchmarking is more complicated than that. I did a few untrustworthy measurements too: On my computer I just got 124 178 930 nanos for Calendar and 66 794 865 for ZonedDateTime, about half, using System.nanoTime() for measurements. YearMonth.now().getMonthValue() (also from java.time) performed in just 8 339 306, about one 15th (1/15) of Calendar.

The fact alone that for Calendar you have to add 1 to the month value and the reader needs to understand why you add 1, is a lot more important than performance, for 99.5 % of cases.

Of course, if in your particular system you have a performance bottleneck and trustworthy measurements tell you that switching one of your methods to using Calendar, Time4J, Joda-Time, some Apache library or some C code will solve that problem, it’s a fully valid reason for doing so. I have a hard time imagining that it will be the case, but then again, I don’t know all computer systems in the world.

Links

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161