Search code examples
javamillisecondsjava.util.calendar

Java Calendar getTimeInMillis() Returning the Same Time


I have a piece of code like this:

    Calendar c = Calendar.getInstance();
    long startTime = c.getTimeInMillis();

    while (x < 10000000) {//check all the integers from 1 to 10000000 to
                          //to see if they're prime or not}

    long endTime = c.getTimeInMillis();
    long totalTime = endTime - startTime;

The loop runs 10 million times so surely startTime and endTime would contain different values.

However totalTime is always equal to 0.

Why does startTime and endTime contain the same value?

Any help would be appreciateed =)


Solution

  • tl;dr

    Duration.between(       // Represent a span-of-time as a count of nanoseconds, to be calculated as hours-minutes-seconds.
        then ,              // Earlier in your code, capture the previous current moment: `Instant then = Instant.now() ;`
        Instant.now()       // Capture the current moment. 
    )                       // Returns a `Duration` object, our elapsed time.
    .toNanos()              // Get the total number of nanoseconds in the entire span-of-time. Returns a `long`. 
    

    Capturing current moment

    Your code is capturing the current moment, a snapshot, frozen. The resulting object is not updated. That is what the phrase “a specific instant in time” means in the class JavaDoc.

    To track elapsed time, you must capture the current moment twice, resulting in two separate objects.

    Avoid legacy date-time classes

    The Calendar class is terrible, and was supplanted years ago by the java.time classes with the adoption of JSR 310. Specifically, ZonedDateTime replaces GregorianCalendar, the usual implementation of Calendar.

    Instant

    The modern approach to tracking the current moment uses the Instant class. An Instant represents a moment in UTC.

    Instant start = Instant.now() ;
    …  // Do some stuff.
    Instant stop = Instant.now() ;
    

    Resolution

    In Java 9 and later, the current moment is captured with a resolution of microseconds (6 decimal digits of fractional second). In Java 8, an Instant the older implementation of Clock is limited to capturing the current moment in milliseconds (3 decimal digits). In all versions of Java, the Instant class has the capacity to represent a moment in nanoseconds (9 decimal digits). But conventional computer clocks cannot accurately track time so finely.

    Duration

    Calculate elapsed time as a Duration object.

    Duration duration = Duration.between( start , stop ) ;  // Represents a span of time in terms of hours-minutes-seconds.
    long nanoseconds = duration.toNanos() ;                 // Converts this duration to the total length in nanoseconds expressed as a long.
    

    System.nanoTime

    For microbenchmarking, you may want to use System.nanoTime(). That method captures the current moment as a number of nanoseconds since some arbitrary starting point. Beware: This value returned does not represent the current moment according to any clock or calendar. But it is useful for tracking elapsed time at a resolution possibly finer than Instant.

    long start = System.nanoTime() ;  // Some arbitrarily defined count of nanoseconds. *NOT* the current time/date by any clock/calendar. 
    …  // Do some stuff.
    long stop = System.nanoTime() ;
    long nanoseconds = ( stop - start ) ;
    

    JEP 230: Microbenchmark Suite

    For serious benchmarking, check out the newly built-in benchmarking framework added to Java 12 and later, based on JMH. See JEP 230: Microbenchmark Suite.