Java spring time of instants elapsed in assertEquals statement - java

I have some tests in my testsuite that run on all my colleagues, but fail on me. And that is to return two times from different entities in the form of an instant and compare them with each other. They actually match, but not for me.
This is the described line:
assertEquals(notUpdatedRule.getModStamp(), rule.getModStamp());
As error message I get back the following:
org.opentest4j.AssertionFailedError:
Expected :2023-01-22T19:46:20.754829Z
Actual :2023-01-22T19:46:20.754829486Z
I have already tried to adapt my openjdk version to that of my colleagues, but this has not changed anything.

I recommend that you use Instant.now(Clock clock) instead. From its JavaDocs: "Using this method allows the use of an alternate clock for testing."
The problems could arise from different time zones, different operating systems, different hardware precision of timers in your systems etc.
When you specify a Clock you could create that with a defined precision (milliseconds, seconds, minutes or any other Duration) for your tests.
Or you could provide a Clock that always returns the same instant for your tests (which I really would recommend to have reproducible tests!) with Clock.fixed(Instant fixedInstant, ZoneId zone).
For production use, you can simply provide a Clock.systemUTC() to have the current behaviour of Instant.now().
Clocks JavaDocs explain the reason for using it in more detail.

Related

Which one is recommended: Instant.now().toEpochMilli() or System.currentTimeMillis()

In Java, we can have many different ways to get the current timestamp, but which one is recommended:
Instant.now().toEpochMilli() or System.currentTimeMillis()
Both are fine. And neither is recommended except for a minority of purposes.
What do you need milliseconds since the epoch for?
In Java, we can have many different ways to get the current timestamp,
For current timestamp just use Instant.now(). No need to convert to milliseconds.
Many methods from the first years of Java, also many in the standard library, took a long number of milliseconds since the epoch as argument. However, today I would consider that old-fashioned. See if you can find — or create — or more modern method that takes for instance an Instant as argument instead. Go object-oriented and don’t use a primitive long. It will make your code clearer and more self-explanatory.
As Eliott Frisch said in a comment, if this is for measuring elapsed time, you may prefer the higher resolution of System.nanoTime().
If you do need milliseconds since the epoch
Assuming that you have good reasons for wanting a count of milliseconds since the epoch, …
which one is recommended: Instant.now().toEpochMilli() or
System.currentTimeMillis()[?]
Opinions differ. Some will say that you should use java.time, the modern date and time API, for all of your date and time work. This would imply Instant here. Unsg java.time is generally a good habit since the date and time classes from Java 1.0 and 1.1 (Date, Calendar, TimeZone, DateFormat, SimpleDateFormat and others) are poorly designed and now long outdated, certainly not any that we should use anymore. On the other hand I am not aware of any design problem with System.curremtTimeMillis() in particular (except what I mentioned above about using a long count of milliseconds at all, which obviously is intrinsic to both Instant.now().toEpochMilli() and System.currentTimeMillis()).
If there is a slight performance difference between the two, I have a hard time imagining the situation where this will matter.
Take the option that you find more readable and less surprising in your context.
Similar questions
JSR 310 :: System.currentTimeMillis() vs Instant.toEpochMilli() :: TimeZone
Java current time different values in api
As per my understanding Instant.now().toEpochMilli() is better as Java-8 onward usage of Instant has been recommended.
Also, it works based on timeline and instant represents a specific moment on that timeline.
In case of java.lang.System.currentTimeMillis() method it returns the current time in milliseconds. The granularity of the value depends on the underlying operating system and may be larger.
Hence, to be consistent altogether use Instant.
I want to add that System.nanoTime() is less about precision but more about accuracy.
System.currentTimeMillis() is based on the system clock, which is, most of the time, based on a quartz clock inside a computer. It is not accurate and it drifts. (VM is even worse since you don't have a physical clock and have to sync with the host) When your computer syncs this quartz clock with a global clock, you might even observe your clock jumps backward/forward because your local clock is too fast or slow.
On the other hand, System.nanoTime() is based on a monotonic clock. This clock has nothing to do with the actual time we humans speak. It only moves forward at a constant pace. It does not drift like the quartz clock and there is no sync required. This is why it is perfect for measuring elapses.
For what it's worth, I've done a quick non-ideal performance test comparing the two methods.
On my system (Ubuntu 20.04, OpenJDK 17.0.4), running System.currentTimeMillis ten million times takes cca 230ms while running Instant.now().toEpochMilli() ten million times takes cca 370ms.
import java.time.Instant;
public class A {
public static void main(String[] args) {
long a = 0;
long start = System.currentTimeMillis();
for (int i = 0; i < 10_000_000; i++) {
//a += Instant.now().toEpochMilli();
a += System.currentTimeMillis();
}
System.out.println(a);
System.out.println(System.currentTimeMillis() - start);
}
}

Equivalent of Erlang now() in Java

I am working on a project which requires timestamps for running threads. In Erlang, when we do now() we get something like
{1529,709564,578215} which represent {megaseconds, seconds, microseconds}
since epoch. So, for two processes spawned at the same time, I can get same microseconds value. Is there a way to replicate this function in Java?
I know about Date.getTime() which gives us the milliseconds since epoch time, but it does not serve the purpose since I cannot get a unique microsecond value from it after dividing by order of magnitude.
Any alternative?
System.out.println(Instant.now());
Output just now was:
2018-06-23T05:16:45.768006Z
On the Java 10 on my Mac it gave microsecond precision. Since Java 9 it will on many operating systems, maybe not all. Instant.now() returns an Instant. An Instant is implemented as seconds and nanoseconds since the epoch, and you can get out those individually if you want.

Java time zone display string (GMT-06:00 vs. CST) on Windows

Java application writes events to a log file, including a timestamp (as returned from Date.toString()), which in turn includes the time zone. On the Windows machines I use, I see the string returned by Date.toString() having the time zone represented as a three-character string (e.g. "CST"). But on some customer machines, the dates are being written to the log file with the time zone represented as an offset from GMT (e.g. "GMT-06:00").
We have a tool that parses the text of log files for various pieces of information, but unfortunately, its original implementation assumed the three-character representation and won't work on those log files that have the GMT-offset representation. We've fixed the tool to be indifferent to that now, but we'd like to be able to advise customers who are running an old version and are having this problem due to their strings having GMT-offset time zones, that they can get the tool to start working if they change their system settings so that their logs files are written with three-character string time zone strings going forward. Additionally, we'd like to account for this variability in our future test plans, ensuring that we test things using each setting. But I haven't been able to determine just what in Windows setting tells Java to use "CST" vs. use "GMT-06:00".
I see a couple of time-zone related registry settings, but nothing that I can clearly identify as controlling that particular choice. Some of the registry settings refer to tzres.dll. Is the choice baked into that? Is there any simple way on Windows to get Date.toString() to formulate its string using one time zone representation vs. using the other?
I don't know the exact cause of this difference in behavior, but I can guess. A time zone is an offset from UTC and history & info about anomalies for that particular are such as Daylight Saving Time. Some machines (or the JVM default) may be set to only an offset rather than a specific named time zone.
The java.util.Date class is notoriously troublesome in general, and should be avoided. Specifically, the toString is terrible in two ways. (A) The format it uses to generate the string is bad, as you have discovered. (B) the JVM's default time zone is applied. That application causes confusion as it implies a Date has a time zone when in fact it does not. This method should only be used temporarily for quick-and-dirty purposes, never for logging.
Use a decent date-time library. That means either Joda-Time or the new java.time package in Java 8. Both use the sensible and useful ISO 8601 format by default.
Generally best practice is to do your logging in UTC time zone (no offset).
Example: 2014-05-04T10:36:34Z
To generate such a value in Joda-Time:
String output = new DateTime( DateTimeZone.UTC ).toString();
If your question is, "How do I change the time zone used by a JVM running an app I cannot alter?", one solution is setting the JVM's time zone by passing an argument when launching the JVM. See this question.

Time stamp class in org.apache.commons.net package

I want to use time stamp as part of my application(I am using JAVA).I was asked to use Network Time Protocol(NTP).I have searched in google and I was able to find a package "org.apache.commons.net" where there is a TimeStamp class.I have gone through this link to know more about the class.
What should I pass to the constructors of this class(what is the significance of each constructor). Actually TS class should return us the time stamp,instead it is asking to input time stamp.I am confused with that.
You can use the following overload of the constructor to create the TimeStamp Object.
public TimeStamp(Date d)
pass an object of java.util.Date as argument.
This will give you a timestamp value which is represented as a
64-bit unsigned fixed-point number in seconds relative to 0-hour on 1-January-1900.
The main significance is that it is a protocol, a standard followed by different systems. Different systems present in a network may not have their clock synchronized, and may not understand how others are measuring time, may follow different time zones. using NTP they synchronize their clock to UTC
You can use the static getCurrentTime() to get a timestamp that represents the current time measured to the nearest milliseconds:
Timestamp myTs = Timestamp.getCurrentTime();

Is java.util.Date using TimeZone?

I have 2 different computers, each with different TimeZone.
In one computer im printing System.currentTimeMillis(), and then prints the following command in both computers:
System.out.println(new Date(123456)); --> 123456 stands for the number came in the currentTimeMillis in computer #1.
The second print (though typed hardcoded) result in different prints, in both computers.
why is that?
How about some pedantic detail.
java.util.Date is timezone-independent. Says so right in the javadoc.
You want something with respect to a particular timezone? That's java.util.Calendar.
The tricky part? When you print this stuff (with java.text.DateFormat or a subclass), that involves a Calendar (which involves a timezone). See DateFormat.setTimeZone().
It sure looks (haven't checked the implementation) like java.util.Date.toString() goes through a DateFormat. So even our (mostly) timezone-independent class gets messed up w/ timezones.
Want to get that timezone stuff out of our pure zoneless Date objects? There's Date.toGMTString(). Or you can create your own SimpleDateFormatter and use setTimeZone() to control which zone is used yourself.
why is that?
Because something like "Oct 4th 2009, 14:20" is meaningless without knowing the timezone it refers to - which you can most likely see right now, because that's my time as I write this, and it probably differs by several hours from your time even though it's the same moment in time.
Computer timestamps are usually measured in UTC (basically the timezone of Greenwich, England), and the time zone has to be taken into account when formatting them into something human readable.
Because that milliseconds number is the number of milliseconds past 1/1/1970 UTC. If you then translate to a different timezone, the rendered time will be different.
e.g. 123456 may correspond to midday at Greenwich (UTC). But that will be a different time in New York.
To confirm this, use SimpleDateFormat with a time zone output, and/or change the timezone on the second computer to match the first.
javadoc explains this well,
System.currentTimeMillis()
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.
See https://docs.oracle.com/javase/7/docs/api/java/util/Date.html#toString().
Yes, it's using timezones. It should also print them out (the three characters before the year).

Categories