Clock.systemUTC() docs say that this method may use System.currentTimeMillis() or a higher resolution clock if available. What clock does System.currentTimeMillis() use then? Can there be a difference in the granularity of these two values?
Can there be a difference in the granularity of these two values?
The Clock class has 2 methods for retrieving the current time:
millis()
instant()
Since instant() returns an Instant, which can represent time with a precision of nano-seconds, the answer is obvious.
Answer: Yes.
What clock does System.currentTimeMillis() use then?
If you look at the source code of Clock.systemUTC(), you will find that it uses an internal SystemClock class. In a comment in the millis() method, it says (quoting Java 15):
System.currentTimeMillis() and VM.getNanoTimeAdjustment(offset)
use the same time source - System.currentTimeMillis() simply
limits the resolution to milliseconds.
So we take the faster path and call System.currentTimeMillis()
directly - in order to avoid the performance penalty of
VM.getNanoTimeAdjustment(offset) which is less efficient.
Answer: System.currentTimeMillis() and Clock.instant() use the same time source.
Related
I already read an answer about if it's possible in Java 8 to get the current microseconds and the answer was no, but is it possible now in Java11?
The solution by using System.nanoTime() * 1000 is too inefficient.
Note: The Goal is NOT to get the exact current time in nanoseconds (for example 12:00 PM), obviously that's not working like this.
I would appreciate any help :)
As before, Instant.now() uses the most accurate time source available to the system. Depending on the system, there may not be anything finer-grained than System.currentTimeMillis.
As mentioned in the comments, System.nanoTime() / 1000 can be used for measuring the time between values, but doesn't give you anything like "the current time" -- you can't tell from it, for example, whether or not it's 3:00 PM.
If you need to measure or calculate e.g. the time between events in your program, there is nothing that will do better for you than System.nanoTime.
The Answer by Wasserman is correct. Here are more thoughts.
Not real-time
You commented:
When you try to do a very exact scheduler
Conventional implementations of Java, and conventional computer hardware, are not “very exact” along the scale of nanosecond and microsecond that you seemed to be targeting.
For “very exact” scheduling, you would have to use special hardware with special software. Look for the buzzword real-time, such as real-time Java.
System.nanoTime()
You said:
The solution by using System.nanoTime() * 1000 is too inefficient. Note: The Goal is NOT to get the exact time in nanoseconds
Be aware that System.nanoTime() does not tell you the current time.
System.nanoTime() tells you the approximate amount of nanoseconds that have elapsed since some arbitrarily chosen moment. In some implementations of Java, that moment may have been when the JVM was launched, or when the computer was booted, or something else. But you cannot count on that origin, nor should you care about the origin.
Represent elapsed time using Duration class.
To capture elapsed time in Java for micro-benchmarking:
long start = System.nanoTime() ;
…
Duration elapsed = Duration.between( start , System.nanoTime() ) ;
You can interrogate the Duration for its parts such as nanoseconds, whole seconds, minutes, and hours.
You said:
System.nanoTime() * 1000 is too inefficient
You must have meant:
( start - System.nanoTime() ) / 1_000
… to get a count of elapsed microseconds.
And, no, dividing or multiplying integers is not “inefficient“. If you care about optimizing for integer division operations, you should not be using conventional Java on conventional hardware, as discussed in section above.
Instant.now()
If you want to capture elapsed time as seen by human clocks:
Instant start = Instant.now() ; // May be precise to milliseconds, microseconds, or such depending on your implementation of Java and your host computer hardware clock.
…
Instant end = Instant.now() ;
To represent that elapsed time unattached to the timeline, use Duration.
Duration elapsed = Duration.between( start , end ) ;
To represent that elapsed time attached to the timeline, write a class storing a pair of Instant objects.
record SpanOfTime ( Instant start , Instant end ) {}
Or better yet, add the ThreeTen-Extra library to your project. This library brings classes that add functionality to the built-in java.time classes. One of these is Interval, with handy comparison methods such as abuts, contains, encloses, overlaps, etc.
The Java class library has a class named DateTime. DateTime has this method:
int daysBetween(DateTime other)
which returns the number of days between this and the parameter.
It doesn't have a method
int secondsBetween(DateTime other)
which I happen to need.
Is there a class which is similar to DateTime but has such a method?
Not familiar with DateTime...
If you have two Dates you can call getTime on them to get millseconds, get the diff and divide by 1000. For example
Date d1 = ...;
Date d2 = ...;
long seconds = (d2.getTime()-d1.getTime())/1000;
If you have Calendar objects you can call
c.getTimeInMillis()
and do the same
I should like to provide the modern answer. The other answers were fine when this question was asked, but time moves on. Today I recommend you use java.time, the modern Java date and time API.
ZonedDateTime aDateTime = ZonedDateTime.of(2017, 12, 8, 19, 25, 48, 991000000, ZoneId.of("Europe/Sarajevo"));
ZonedDateTime otherDateTime = ZonedDateTime.of(2017, 12, 8, 20, 10, 38, 238000000, ZoneId.of("Europe/Sarajevo"));
long diff = ChronoUnit.SECONDS.between(aDateTime, otherDateTime);
System.out.println("Difference: " + diff + " seconds");
This prints:
Difference: 2689 seconds
ChronoUnit.SECONDS.between() works with two ZonedDateTime objects or two OffsetDateTimes, two LocalDateTimes, etc.
If you need anything else than just the seconds, you should consider using the Duration class:
Duration dur = Duration.between(aDateTime, otherDateTime);
System.out.println("Duration: " + dur);
System.out.println("Difference: " + dur.getSeconds() + " seconds");
This prints:
Duration: PT44M49.247S
Difference: 2689 seconds
The former of the two lines prints the duration in ISO 8601 format, the output means a duration of 44 minutes and 49.247 seconds.
Why java.time?
The Date class used in several of the other answers is now long outdated. Joda-Time also used in a couple (and possibly in the question) is now in maintenance mode, no major enhancements are planned, and the developers officially recommend migrating to java.time, also known as JSR-310.
Question: Can I use the modern API with my Java version?
If using at least Java 6, you can.
In Java 8 and later the new API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310).
On Android, use the Android edition of ThreeTen Backport. It’s called ThreeTenABP, and there’s a thorough explanation in this question: How to use ThreeTenABP in Android Project.
You should do
org.joda.time.Seconds.secondBetween(date1, date2)
That should do it:
Date a = ...;
Date b = ...;
Math.abs(a.getTime()-b.getTime())/1000;
Here the relevant documentation: Date.getTime(). Be aware that this will only work for dates after January 1, 1970, 00:00:00 GMT
You can use org.apache.commons.lang.time.DateUtils to make it cleaner:
(firstDate.getTime() - secondDate.getTime()) / DateUtils.MILLIS_PER_SECOND
There is no such class as DateTime in the standard Java SE API. Although there is one in joda-time, even that does not have a daysBetween method.
Using the standard Java API, the easiest way to get seconds between two java.util.Date objects would be to subtract their timestamps and divide by 1000:
int secondsBetween = (date1.getTime() - date2.getTime()) / 1000;
It is not recommended to use java.util.Date or System.currentTimeMillis() to measure elapsed times. These dates are not guaranteed to be monotonic and will changes occur when the system clock is modified (eg when corrected from server). In probability this will happen rarely, but why not code a better solution rather than worrying about possibly negative or very large changes?
Instead I would recommend using System.nanoTime().
long t1 = System.nanoTime();
long t2 = System.nanoTime();
long elapsedTimeInSeconds = (t2 - t1) / 1000000000;
EDIT
For more information about monoticity see the answer to a related question I asked, where possible nanoTime uses a monotonic clock. I have tested but only using Windows XP, Java 1.6 and modifying the clock whereby nanoTime was monotonic and currentTimeMillis wasn't.
Also from Java's Real time doc's:
Q: 50. Is the time returned via the
real-time clock of better resolution
than that returned by
System.nanoTime()?
The real-time clock and
System.nanoTime() are both based on
the same system call and thus the same
clock.
With Java RTS, all time-based APIs
(for example, Timers, Periodic
Threads, Deadline Monitoring, and so
forth) are based on the
high-resolution timer. And, together
with real-time priorities, they can
ensure that the appropriate code will
be executed at the right time for
real-time constraints. In contrast,
ordinary Java SE APIs offer just a few
methods capable of handling
high-resolution times, with no
guarantee of execution at a given
time. Using System.nanoTime() between
various points in the code to perform
elapsed time measurements should
always be accurate.
If you're using Joda (which may be coming as jsr 310 in JDK 7, separate open source api until then) then there is a Seconds class with a secondsBetween method.
Here's the javadoc link: http://joda-time.sourceforge.net/api-release/org/joda/time/Seconds.html#secondsBetween(org.joda.time.ReadableInstant,%20org.joda.time.ReadableInstant)
For java 8+ you can use
ChronoUnit.SECONDS.between(temporal1,temporal2)
Which class ? Do you mean the Joda DateTime class ? If so, you can simply call getMillis() on each, and perform the appropriate subtraction/scaling.
I would recommend Joda for date/time work, btw, due to it's useful and intuitive API, and its thread-safety for formatting/parsing options.
Just a pointer:
If you're calculating the difference between two java.util.Date the approach of subtracting both dates and dividing it by 1000 is reasonable, but take special care if you get your java.util.Date reference from a Calendar object.
If you do so, you need to take account of daylight savings of your TimeZone since one of the dates you're using might take place on a DST period.
That is explained on Prasoon's link, I recommend taking some time to read it.
Use this method:
private Long secondsBetween(Date first, Date second){
return (second.getTime() - first.getTime())/1000;
}
Use time unit class.
long timeDifferentInSeconds = TimeUnit.MILLISECONDS.toSeconds(currentDate.getTime()) - TimeUnit.MILLISECONDS.toSeconds(previousDate.getTime());
I need to convert a standard long System.currentmillis to a temporal accessor and have no clue how to even begin.
Instant is a TemporalAccessor, so you can create an Instant from a number of milliseconds since the epoch:
TemporalAccessor ta = Instant.ofEpochMilli(System.currentTimeMillis());
Note that the docs for System.currentTimeMillis says that the granularity of the value depends on the OS, so it might not be the exact time in milliseconds.
Returns the current time in milliseconds. Note that while the unit of
time of the return value is a millisecond, the granularity of the
value depends on the underlying operating system and may be larger.
For example, many operating systems measure time in units of tens of
milliseconds.
I am using JDK8 on Windows and JDK8 on Linux
When I run System.nanoTime()/System.currentTimeMillis() on windows, the result is 49,
System.nanoTime(): 74786833960332
System.currentTimeMillis():1507786236263
When run it on Linux, the result is 26236
System.nanoTime(): 39560110918205325
System.currentTimeMillis():1507786262105
I am confused with the result, that the two values are different so much.
Also, I thought that nanoTime is 1,000,000 times milliseconds, so that the two values above both look wrong to me(that is, both of them should be approximately 1000000)
Apples and Oranges
System.nanotime has nothing to do with current date and time-of-day. Its purpose is for calculating elapsed time.
Your math and your comparison to System.currentTimeMillis() makes no sense at all. The two functions are incomparable.
Read the documentation before posting to Stack Overflow.
For date-time handling you should not be using the System class at all. Instead use the industry-leading java.time classes built into Java 8 and later.
If you want current moment in UTC, call Instant.now().
If you want current moment in a time zone, call ZonedDateTime.now.
In Java 9 and later, both classes use a new implementation of Clock to capture the current moment in a resolution up to nanoseconds. But keep in mind that mainstream computers lack a hardware clock with such fine sensitivity. Microseconds is likely the finest resolution you'll see in the real world as of 2017.
According to System.nanotime() docs it is not system time in nanoseconds and it is not related to System.currenTimeMillis. It is platform dependent (this is why the difference) nanoseconds generator and it is used for measuring time elapsed between two invocations.
From the Java System documentation:
[System.nanoTime] Returns the current value of the running Java Virtual Machine's high-resolution time source, in nanoseconds.
This means System.nanoTime() returns the elapsed running time of the JVM in nanos, whereas System.currentTimeMillis() returns the time in milliseconds since midnight, January 1, 1970 UTC.
This results in a non-consistent nanoTime over each run.
Since the Java doc tell me, not to use System.currentTimeMillis for comparison, I started using System.nanoTime which is fine.
But I ran into some problems, I have to compare events which are in the past.
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_MONTH, xyz);
cal.getTimeMillis();
works fine to get the time in milliseconds, but converting it to nanoseconds (by multiplying it with 1000000) is far to inaccurate.
How can I get time of a event in the past in milliseconds?
The Calendar class in Java doesn't contain nanosecond information. So you can't get that.
You need to store the nanoseconds as long for the event you want to compare later if you need that detail.: you can't do that too, the nanoTime() is not a representation of current time, but you may still store that to evaluate elapsed time of old processes.
What data type are you using for the multiplication by 1,000,000 ? Perhaps you should use a BigDecimal, which would be accurate enough for you.