Will System.Currenttimemillis Always Return a Value ≫= Previous Calls

Will System.currentTimeMillis always return a value = previous calls?

The short answer is no, System.currentTimeMillis() is not monotonic. It is based on system time, and hence can be subject to variation either way (forward or backward) in the case of clock adjustments (e.g. via NTP).

System.nanoTime() is monotonic, if and only if the underlying platform supports CLOCK_MONOTONIC -- see the comments on Java bug report 6458294 for a good writeup on some circumstances where this is/isn't true.

(And, as an additional anecdote, I have personally observed (several times) System.currentTimeMillis() run 'backwards', in the absence of clock adjustments, across threads -- that is, a call to that method in one thread returned a lower value than a call in another thread, even though it occurred chronologically after it in 'real-time')

If you need a monotonic source, System.nanoTime() on a platform supporting monotonicity is your best option.

does System.currentTimeMillis() return UTC time?

All three of the lines you've shown will give the number of milliseconds since the unix epoch, which is a fixed point in time, not affected by your local time zone.

You say "this time is not the UTC time" - I suspect you've actually diagnosed that incorrectly. I would suggest using epochconverter.com for this. For example, in your example:

1372060916 = Mon, 24 Jun 2013 08:01:56 GMT

We don't know when you generated that value, but unless it was actually at 8:01am UTC, it's a problem with your system clock.

Neither System.currentTimeMillis nor the value within a Date itself are affected by time zone. However, you should be aware that Date.toString() does use the local time zone, which misleads many developers into thinking that a Date is inherently associated with a time zone - it's not, it's just an instant in time, without an associated time zone or even calendar system.

Is `System.currentTimeMillis()` correct across multiple processes?

The call to System.currentTimeMillis, and its modern replacement Instant.now, both capture the current moment as reported by the host OS and the underlying computer clock hardware. The Javadoc and source code promise a clock “based on the best available system clock”.

So, no, there should be no jumping into the future. Every time you call either of those methods, you capture the current moment.

However, you may see the illusion of jumping into the future. This may happen for these reasons:

  • thread scheduling
  • clock resetting
  • fake clock

Thread scheduling

This illusion may occur because of what happens after the current moment is captured. The split-second after capturing the current moment, that thread’s execution may be paused. Some other thread may then capture a later moment, continue to report that moment. Eventually, that first thread resumes, and reports its earlier captured moment — but note how the reporting of that moment happens later.

Take this example code.

package work.basil.example;

import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TellTime
{
public static void main ( String[] args )
{
TellTime app = new TellTime();
app.demo();
}

private void demo ( )
{
ExecutorService executorService = Executors.newCachedThreadPool();

int countThreads = 15;
List < Callable < Object > > tasks = new ArrayList <>( countThreads );
for ( int i = 0 ; i < countThreads ; i++ )
{
Runnable tellTimeRunnable = ( ) -> System.out.println( Instant.now() );
tasks.add( Executors.callable( tellTimeRunnable ) );
}
try
{
List < Future < Object > > list = executorService.invokeAll( tasks );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
}
}

The very first time I ran that code, I found such a jump in the last two lines of output. The 4th line shows a moment earlier than the 3rd. The 5th line shows a moment even earlier.

2020-11-23T01:07:34.305318Z
2020-11-23T01:07:34.305569Z
2020-11-23T01:07:34.305770Z
2020-11-23T01:07:34.305746Z
2020-11-23T01:07:34.305434Z

In my case here, the calls to System.out.println got delayed in their execution, so some earlier moments were reported later. Likewise, I suspect that in your case, the act of logging your captured moments involved various delays so that some earlier moments were logged later.

Clock resetting

As Stephen C points out in comments below, computers are often configured to auto-adjust the hardware clock based on info from a time server. The hardware clocks in many computers are less accurate than you might imagine. So the host computer’s clock may well be reset to an earlier or later time-of-day to correct for time-tracking drift.

Be aware that some computers reset their clock back to an epoch reference point such as 1970-01-01 00:00Z when booted with a faulty or exhausted battery/capacitor backing the hardware clock. That epoch reference moment may be reported as the current moment until the computer gets a chance to check in with the time server.

Or some human could manually adjust the computer clock’s current date and time. :-(

Your code may capture the current moment on either side of this clock adjustment. Now a later event may appear to have occurred earlier.

Fake clock

In java.time, calls such as Instant.now access the currently-assigned Clock implementation. By "currently assigned", I refer to the fact that in java.time, the default Clock object can be overridden. Usually that would be for testing purposes only. Various Clock object can report a fixed moment, a shifted moment, or may report with an altered cadence.

So be aware that an alternate Clock may purposely tell a different time, if your testing code specified an alternate Clock object. By default though you always get the current moment at the time that method call executes.

Conclusion

There is a major implication here: Time-tracking cannot be completely trusted. The current moment may be incorrectly captured, and the reporting of captured moments may be out-of-order.

So when debugging or investigating, always keep this thought tucked away in the back of your mind: The timestamps and their ordering may not be telling you whole truth. You ultimately cannot know with 100% certainty what happened when.

How to get the current date/time in Java

It depends on what form of date / time you want:

  • If you want the date / time as a single numeric value, then System.currentTimeMillis() gives you that, expressed as the number of milliseconds after the UNIX epoch (as a Java long). This value is a delta from a UTC time-point, and is independent of the local time-zone1.

  • If you want the date / time in a form that allows you to access the components (year, month, etc) numerically, you could use one of the following:

    • new Date() gives you a Date object initialized with the current date / time. The problem is that the Date API methods are mostly flawed ... and deprecated.

    • Calendar.getInstance() gives you a Calendar object initialized with the current date / time, using the default Locale and TimeZone. Other overloads allow you to use a specific Locale and/or TimeZone. Calendar works ... but the APIs are still cumbersome.

    • new org.joda.time.DateTime() gives you a Joda-time object initialized with the current date / time, using the default time zone and chronology. There are lots of other Joda alternatives ... too many to describe here. (But note that some people report that Joda time has performance issues.; e.g. https://stackoverflow.com/questions/6280829.)

    • in Java 8, calling java.time.LocalDateTime.now() and java.time.ZonedDateTime.now() will give you representations2 for the current date / time.

Prior to Java 8, most people who know about these things recommended Joda-time as having (by far) the best Java APIs for doing things involving time point and duration calculations.

With Java 8 and later, the standard java.time package is recommended. Joda time is now considered "obsolete", and the Joda maintainers are recommending that people migrate.3.


1 - System.currentTimeMillis() gives the "system" time. While it is normal practice for the system clock to be set to (nominal) UTC, there will be a difference (a delta) between the local UTC clock and true UTC. The size of the delta depends on how well (and how often) the system's clock is synced with UTC.

2 - Note that LocalDateTime doesn't include a time zone. As the javadoc says: "It cannot represent an instant on the time-line without additional information such as an offset or time-zone."

3 - Note: your Java 8 code won't break if you don't migrate, but the Joda codebase may eventually stop getting bug fixes and other patches. As of 2020-02, an official "end of life" for Joda has not been announced, and the Joda APIs have not been marked as Deprecated.

How to get current time and date in Android

You could use:

import java.util.Calendar

Date currentTime = Calendar.getInstance().getTime();

There are plenty of constants in Calendar for everything you need.

Check the Calendar class documentation.

Get the current date in java.sql.Date format

A java.util.Date is not a java.sql.Date. It's the other way around. A java.sql.Date is a java.util.Date.

You'll need to convert it to a java.sql.Date by using the constructor that takes a long that a java.util.Date can supply.

java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());

Can Java's random function be zero?

According to the documentation, "Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0." This means it can be zero.

As Hank wrote, it is exclusive on the upper boundary (can never be 1), so maybe that's where your confusion comes from :-).



Related Topics



Leave a reply



Submit