Why we need to update time zone information of jdk/jre? - java

I know that is required because of changes that occurs after the release of the jdk/jre, but why don't get those informations from the server?
As "from the server" i mean from OS. The question is: "Why doesn't Java use the time zone system from the operating system instead of having its own copy of the time zone database"?

Here is my rough understanding. I believe it should at least give you the main reasons.
When Java was designed in the 1990s, a main design goal was that your Java program should be write once run anywhere, popularly abbreviated WORA. At that time cross-platform programs were not that commonplace. Porting your Windows program to a Mac or vice versa required quite some effort. Sun, the company that developed Java, was selling an operating system called Solaris, a Unix variant that not that many wanted to port to or from.
Different operating systems have different time zone data: different structure, different names for the time zones, different amounts of detail. Windows, for example, hasn’t got the full history of offsets for all time zones. What Mac and Unix had in the 1990s I don’t know. There were many Unix variants back then, and I am not even sure whether they all had built-in time zone information.
So relying on the operating system would mean that a program doing for example TimeZone.getTimeZone("America/Sao_Paulo") (using the time zone class from back then, now long outdated) would not be portable because on another operating system the time zone would not be called that. The write once run anywhere idea would be seriously harmed.
I suppose that this was the main reason for choosing that Java needed to have its own built-in time zone database, the same on all operating systems. I also believe that the choice of the Olson database, also known as tzdata, the zoneinfo database or IANA time zone database, was rather obvious. And from this choice came also the need for being able to update the timezone data, since the database is constantly evolving, especially since politicians around the globe are constantly (and eagerly, it would appear) deciding on new time zone rules.
Links for comparison:
List of tz database time zones
Windows Default Time Zones
Please notice that the former uses time zone IDs like America/Sao_Paulo, that is the region/city format, while the latter instead uses names like E. South America Standard Time.

Related

Why Java localDateTime does not recognize Canada/Yukon as GMT-7?

Canada/Yukon timezone no longer observe DST (source https://www.timeanddate.com/time/change/canada/yukon) and is now permanently GMT-7. But when I tried this:
ZonedDateTime nowZoned = LocalDateTime.parse("2021-02-03T08:04:00").atZone(ZoneOffset.UTC).toInstant().atZone(ZoneId.of("Canada/Yukon"));
nowZoned is shown as 2021-02-03T00:04-08:00[Canada/Yukon].
Does it mean that java.time library does not update when some timezones have decided not to observe DST or decided to move ahead of the clock permanently? What are some ways to work around this issues? I thought about manually checking for these but there are simply way too many timezones to handle them manually. Thanks!
Yes indeed, the Yukon time zone rules changed in early 2020. The politicians there decided to stay on Daylight Saving Time (DST) indefinitely, using an offset of -07:00 year-round. So the sun will never again be overhead at noon.
Staying on DST year-round is the new fad among politicians around the world. Countries such as Morocco and Turkey have gone that way. Others are headed that way, such as Washington State in the United States.
Your code:
ZonedDateTime nowZoned = LocalDateTime.parse("2021-02-03T08:04:00").atZone(ZoneOffset.UTC).toInstant().atZone(ZoneId.of("Canada/Yukon"));
… is overwrought. Simply put a Z at the end of your input string if that date and time is intended to be a moment as seen in UTC.
ZonedDateTime zdt =
Inatant
.parse("2021-02-03T08:04:00Z")
.atZone(
ZoneId.of( "Canada/Yukon" )
)
;
You asked:
Does it mean that java.time library does not update when some timezones have decided not to observe DST or decided to move ahead of the clock permanently?
Politicians around the world have shown a predilection towards changing the rules of the time zones in their jurisdiction. They do so with surprising frequency. And some do so with astonishingly little forewarning.
The rules are stored in a tzdata file. When politicians change the rules, ICANN/IANA publishes a new updated version of the tzdata. This typically happens a few times a year.
And, no, there is no automatic immediate updating on your computer. As a SysAdmin or DBA, you are responsible for these updates. Of course, you need not update unless a time zone of interest to your company changes.
You will find at least two or three of these on your machines.
Your JVM has one embedded. Updates to the JVM will typically include the latest tzdata. But that Java update may not come soon enough. So you may need to manually obtain a tzdata file, ad replace the one in your JVM. Oracle provides a tool to assist. But I’m not aware of its current licensing terms, so study their terms. Or check with the vendor of your JVM such as Azul Systems, Adoptium, SAP, Amazon, Microsoft, BellSoft, Red Hat/IBM, etc.
Your host operating system such as macOS, BSD, Linux, Windows, etc. has a copy of the tzdata. While updating this tzdata does not affect your Java apps, you’ll want to update it for other apps.
Sophisticated database servers such as Postgres also keep their own internal copy of tzdata. Update as needed by either manual replacement or through an updated version of the DBMS.
Every SysAdmin & DBA should consider subscribing to the tzdata announcement mailing list.

Is there an equivalent to System.nanoTime() which do not change when changing the system time? [duplicate]

I would like to measure elapsed time in a Java. However differences in System.currentTimeMillis() and (I believe) System.nanoTime() can be changed by external changes eg someone (or the system) altering the system clock.
Using network calls is not an option as it's possible very frequent and fast returns are required.
Is there a common solution for this?
EDIT
Sorry, I should have elaborated about the reason. It isn't to stop malicious users - it's things like client initiated logout for being idle and routine client events.
This doesn't really answer your question, but bug #6458294 implies that where possible, Sun's implementation of nanoTime() will use mechanisms which are truly monotonic (CLOCK_MONOTONIC on Linux, QueryPerformanceFrequency/QueryPerformanceCounter on Windows). Only if these are unavailable will it fall back to a mechanism which is susceptible to system clock changes.
If you have control (or at least knowledge) of the hardware you're running on, and can ensure that these clock mechanisms will be available, you might be in luck and nanoTime() will do fine.
You may also like to read this blog post, which discusses the HotSpot-on-Windows case in more detail.
I don't think there is a way to do this.
There is certainly no way to do this that cannot be subverted. Fundamentally, you are at the mercy of the operating system and the JVM as to what is reported to the Java app as the current time. Either or both of these could be patched so that the Java code ends up getting a bogus timestamp value. You could try to defend against this, but then all the hacker needs to do is to patch your app to disable license checking entirely.
For the record, this "vulnerability" applies whether or not you are using Java.
If you're trying to stop people from subverting a license scheme by setting the clock back, you need to store the highest time you've seen so far in some sort of encrypted and secure storage, and then disable the program if either the time goes less than the highest you've seen (with some allowance for NTP clock adjustments and DST changes of course), or if they somehow tamper with or delete the secure store.
I don't know if nanoTime() is likely to change if the system clock changes, but I suppose it's possible. Also nanoTime() may not be accurate.
If you really need to guard against clock changes, you could monitor the clock in a thread. Sleep for 100ms or 1000ms, then call currentTimeMillis(). If clock advanced more then 1000 + x or has gone backwards then likely the clock changed (or the thread got hung up on something, which is possible).
In the event of a disjunction, you could actually make the network call to check. Of course, it's possible that network time might change due to the insertion of leap seconds. I once read a Slashdot comment by some scientists who was coordinating astronomical data from lots of different sources. A leap second was added during his experiment, and it basically ruined it because some sites inserted it and others didn't.
Another possibility might be to use a low level native API to get some other system timers. Such as system or network uptime to calibrate the API. Windows has the getTickCount() function that returns the number of milliseconds since boot. On unix systems you can use the uptime command to get a rough estimate. You can periodically check these values to see if the system clock has changed.
If you don't mind adding a bit of native code to your Java app, use:
QueryPerformanceCounter() and QueryPerformanceFrequency() on Windows; or
POSIX clock_gettime() function with CLOCK_MONOTONIC clock ID.
Note that the use of the x86 TSC register is discouraged on multiprocessor systems, so you better use the above APIs.

Different current time produces through XSLT and Java

I have two services running on separate machine. I'm seeing strange behavior in the boxes when generating the current time. The current time is being generated differently.
In one machine it's being done in XSLT using current-dateTime() function e.g.
<xsl:variable name="dateNow" select="format-dateTime(adjust-dateTime-to-timezone(current-dateTime()), '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01]')"/>
In the second machine, the current time is being generated in Java code using Joda Time e.g.DateTime.now()
Why is box one 1h ahead of box two?
I've checked the current time in and the time zone in both machine. They are the same.
Update:
Originally I thought it was time zone issue which is why I added adjust-dateTime-to-timezone . adjust-dateTime-to-timezone has no effect.
When you say "different boxes" I assume you mean different computers. The most likely explanation is that the default timezone is set differently on the two machines.

Run servers in one machine in different timezone

I am running Three Quartz servers(as java wrapper services) from one Linux Virtual Server machine. My requirement is to run these servers in different time zone in one machine. e.g. Say there are three servers name A, B and C then A should schedule job based on Central Time zone, B should schedule jobs based on Eastern Time zone and so on. Is there any way we could achieve this?
Time zones are but concepts in Unix land. Each system clock should run with UTC, calculating displayed times based on the timezone you configure within the system.
Depending on which software should deal with that, it might be totally sufficient to set the TZ environment variable correctly.
I created three users for three different servers and set the desired time zones in .bashrc file. Say user name is user1 then do the following:
Open file /home/user1/.bashrc usinf any editor.
Modify and enter this line:
export TZ="/usr/share/zoneinfo/{TIMEZONE-DIRECTORY}/{TIMEZONE_FILE}"
Save the file.
Timezone is set for the user now.

How can I measure time in Java not susceptible to System clock changes?

I would like to measure elapsed time in a Java. However differences in System.currentTimeMillis() and (I believe) System.nanoTime() can be changed by external changes eg someone (or the system) altering the system clock.
Using network calls is not an option as it's possible very frequent and fast returns are required.
Is there a common solution for this?
EDIT
Sorry, I should have elaborated about the reason. It isn't to stop malicious users - it's things like client initiated logout for being idle and routine client events.
This doesn't really answer your question, but bug #6458294 implies that where possible, Sun's implementation of nanoTime() will use mechanisms which are truly monotonic (CLOCK_MONOTONIC on Linux, QueryPerformanceFrequency/QueryPerformanceCounter on Windows). Only if these are unavailable will it fall back to a mechanism which is susceptible to system clock changes.
If you have control (or at least knowledge) of the hardware you're running on, and can ensure that these clock mechanisms will be available, you might be in luck and nanoTime() will do fine.
You may also like to read this blog post, which discusses the HotSpot-on-Windows case in more detail.
I don't think there is a way to do this.
There is certainly no way to do this that cannot be subverted. Fundamentally, you are at the mercy of the operating system and the JVM as to what is reported to the Java app as the current time. Either or both of these could be patched so that the Java code ends up getting a bogus timestamp value. You could try to defend against this, but then all the hacker needs to do is to patch your app to disable license checking entirely.
For the record, this "vulnerability" applies whether or not you are using Java.
If you're trying to stop people from subverting a license scheme by setting the clock back, you need to store the highest time you've seen so far in some sort of encrypted and secure storage, and then disable the program if either the time goes less than the highest you've seen (with some allowance for NTP clock adjustments and DST changes of course), or if they somehow tamper with or delete the secure store.
I don't know if nanoTime() is likely to change if the system clock changes, but I suppose it's possible. Also nanoTime() may not be accurate.
If you really need to guard against clock changes, you could monitor the clock in a thread. Sleep for 100ms or 1000ms, then call currentTimeMillis(). If clock advanced more then 1000 + x or has gone backwards then likely the clock changed (or the thread got hung up on something, which is possible).
In the event of a disjunction, you could actually make the network call to check. Of course, it's possible that network time might change due to the insertion of leap seconds. I once read a Slashdot comment by some scientists who was coordinating astronomical data from lots of different sources. A leap second was added during his experiment, and it basically ruined it because some sites inserted it and others didn't.
Another possibility might be to use a low level native API to get some other system timers. Such as system or network uptime to calibrate the API. Windows has the getTickCount() function that returns the number of milliseconds since boot. On unix systems you can use the uptime command to get a rough estimate. You can periodically check these values to see if the system clock has changed.
If you don't mind adding a bit of native code to your Java app, use:
QueryPerformanceCounter() and QueryPerformanceFrequency() on Windows; or
POSIX clock_gettime() function with CLOCK_MONOTONIC clock ID.
Note that the use of the x86 TSC register is discouraged on multiprocessor systems, so you better use the above APIs.

Categories

Resources