What's the best practices to handle frequently changing timezones - java

I'm writing a toy logistics service. As a result, products will travel through lots of different timezones, and I'll need to query both the strict ordering of events, as well as what hour of day it is for products (for example, what happened when the sun was at its hottest, at 1200).
At the moment, I'm saving jodatime DateTimes and trying to deal with them exclusively, but I know time is mighty tricky, and I'm wondering if I need to do anything else to make sure it all works.

Given that you're recording events as they occur (rather than planning for future events), you probably don't need to worry about changes to time zone rules which occur in the future.
As such, it would be reasonable to store a timestamp (e.g. as UTC) and also the time zone ID for the location of the event. To make querying easier, you could also store the local time at the time of the event. Just be aware that as a toy is travelling through time zones, there could be multiple events at different instants in time, all of which occur at "midday" on the same day (but in different zones). You really need to think carefully about what queries you really want to perform on the local date/time values.

I am not familiar with jodatime but when I need to store the time I always enjoy using Epoch time because it is very easy to manipulate to get different formats. If you're interested in it here is a converter website that I find very helpful: http://www.epochconverter.com/

Related

How to globally fix the timezone in android app?

I am looking for the most simple and cleanest way to fix the timezone for all dates in an Android app. The idea is to have the app running as if the user were in another timezone. Let me clarify what I am looking for:
Let's say the user's phone is set to America/New_York then I would like my app to show all dates (are in UTC) in the Europe/Amsterdam timezone, regardless of the timezone that is set on the phone itself. And if I make a comparison with a new Date() it would be very nice if that new Date() is also in the current time of the Europe/Amsterdam timezone.
After searching the internet for solutions, I started to get the feeling that I will have to update every place in my app where a Date is used and force the use of the target timezone, like the solution of this stackoverflow post: Converting UTC dates to other timezones
Does anybody know how to get this done in a more easy and cleaner way?
The answer for anyone using java.time, the modern Java date and time API.
java.time does not include an option for setting the JVM default time zone. And wisely so. It’s not something you should want to do. By doing it you affect every program running in the same JVM, and also every part of your program and other program in the JVM may set it differently, ruining your intentions.
Avoid the need
In your time operations be explicit about which time zone you want, and you will always know what you get independently of the JVM setting. Example:
System.out.println(ZonedDateTime.now(ZoneId.of("Asia/Dushanbe")));
Example output:
2021-05-09T00:36:25.171213+05:00[Asia/Dushanbe]
System.setProperty
If you have already written a lot of code relying on the default time zone of the JVM, the hack to set it is:
System.setProperty("user.timezone", "Australia/Tasmania");
System.out.println(ZonedDateTime.now());
This just printed:
2021-05-09T05:38:03.568350+10:00[Australia/Tasmania]
It’s not very robust, though, for the reasons mentioned in the beginning.
If you want validation of the string you are passing, use:
System.setProperty("user.timezone", ZoneId.of("Australia/Tasmania").getId());
Disclaimer
It seems from your question that you are already using the old, poorly designed and long outdated java.util.Date class and friends. I still wanted to post the answer for users who have the option to go modern. (You may also use each of the two ideas presented with the out-dated API.)
I would try TimeZone.setDefault(TimeZone) like in:
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Amsterdam"));
(advice to check returned time zone, getTimeZone does not throw exception for unknown time zone - or use ZoneId instead of the String)
see TimeZone (this also mentions the user.timezone system property)
but I am not an android programmer/user

How to efficiently trigger events in Java according to date?

I am building a relatively complex app for a company that keeps track of several objects and triggers events according to the object's age or preset dates contained in it.
For example:
Object object_A contains a "renewal date". When the renewal date and the system date coincide, the application needs to run a particular routine.
My question is: Since there will be thousands of such objects, what is the most efficient way of keeping track of all of them and triggering the respective routines at the respective dates and times?
Worth mentioning that I've used Calendar objects for describing these dates (though they can easily be converted into Date objects, so that's not entirely relevant).
I'd appreciate any pointing into the right direction...
Quartz is an excellent library for robust/complex task scheduling.
I will encourage you (since you say you're building the app) to reconsider about responsibilities. I don't think it should be object responsibility to maintain that renewal date. I mean you can do it that way and has an agent that will periodically visit those items to see if its renewal date is today.
But, if you think as an external agent that will contain a renewal dates table it will be more efficient since:
All objects' triggers with same renewal date will fire at the same time.
Managing the check logic will be centralized
Cost (in space) of storing renewal date will reduce if collapse into a same date.
This is a big picture view but hopes it serves.

Java Midi Receiver and Calendar Time in Millis

I currently use a Receiver class which receives my Midi Events from my Midi keyboard.
With each event the send() method returns some information along with the timestamp of the MidiEvent.
When I create a Calendar instance and getTimeInMillis() I get a completely different number to the Receiver's timestamp. The difference of the two values change every time, so I know it's not just a constant value.
Is there a way to get the Receiver's timestamp value at any time without it being through the Receiver's send() method?
By this I mean get a timestamp in a method which follows the same time scale as the Receiver's timestamp.
I believe you may be operating under a misconception - the value of the timestamp Receiver.send() expects is in microseconds, not milliseconds like in Calendar. That means you're off by a factor of 1000, which would appear to be a 'constantly changing value'.
I don't know whether you want to just reduce the resolution of your timestamps, or use the microseconds. It would depend on the exact nature of your application, what data you're getting in your messages, and what you want to do with them.
EDIT:
This is based on the assumption that you're receiving the data, not that you're populating the timestamp value.
If you need to preserve the resolution, here are some options:
Use the java.sql.Timestamp subclass of Date. This can store resolutions down to nanoseconds (more then what you need). However, all of the standard date utilities in the library have some odd behaviour, and the namespace is perhaps less than ideal.
Write your own JRE/JDK/JVM. Calendar and Date are part of the standard library. If you want to distribute your code, you have to expect people to use your version of the standard library. This is inadvisable, for a large number of reasons.
Find/Write your own timestamp-type class. There are probably audio libraries that have a relevant implementation. If you do have to write your own, I'd probably grab the code from Joda Time, and just change the resolution - that would still be a fair bit of work, though.
Just leave the value as the primitive. It's unlikely you need anything more than the numeric values, after all (not like you need to translate to year-month-day values). Although it would be good to have type safety for this, especially in light of the resolution differences. If this doesn't match your use case, I'm sorry.

Creating a user-friendly list of timezones for user-preferences

Below is a snippet of the list of timezones returned from java (I've printed the timezone offset, timezone ID, and long name, using JodaTime).
(GMT-10:00) HST, Hawaii Standard Time
(GMT-10:00) Pacific/Apia, -10:00
(GMT-10:00) Pacific/Fakaofo, Tokelau Time
(GMT-10:00) Pacific/Honolulu, Hawaii Standard Time
(GMT-10:00) Pacific/Johnston, Hawaii Standard Time
What is the difference between HST, Pacific/Honolulu, and Pacific/Johnston, for example? They all seem to use Hawaii Standard Time, why are there 3 entries in the database?
My ultimate goal is to just create a list of timezones for user preferences in a web app.
If I use all of the timezones from the tzDatabase the list is long and appears to have effective duplicates (example above). I could just list unique long-form-names such as "Hawaii Standard Time", but then I need to decide how to map it to any one of the timezones that use that same long name.
What do other people do in this case? How do you create a nice user-friendly list of timezones and map them to their relevant java TimeZone?
I think you are making the assumption that "user-friendly" means to show them a small list. The fact is though that all of those time zones are used by someone, somewhere. They may look the same to you but they often have slightly different behaviour. I live in Saskatchewan and we have our own version of CST. The long name is only "Central Standard Time" but we don't use DST so for half of the year, we don't line up with real CST. There is even one small area of Saskatchewan which has a 15 min difference in the time. Even if they seem the same, they are different and I think you should allow the users to select from the whole list.
Trying to intelligently shorten the list might be comparable to not listing all possible currency codes when allowing a user to select a preferred currency. Yes, there may only be a handful of people who use certain ones. Sure, there may be some with the same conversion rates currently. In the end, let the user decide what they care about.
One solution for showing large lists or potentially un-important data with only a few items of real interest: Determine the commonly used ones first and then separate them to the top of the list. This can be seen on various websites for selecting Country, for example:
Canada
United States
------------------
Argentina
Australia
...
This strategy is also often used for my previous example of currency. It could look something like this for time-zones (If your main user base is in North America):
EST
CST
MST
PST
------------------
Hawaii
Saskatchewan
...
Remember though, this will require you to manually, pre-determine what the common time zones are.
I feel the best approach is to simply list all timezones, sorted by offset because most people will know where to find there zone based on offset. For instance, I always look first for "-6:00", not Saskatchewan. Hope this helps!
The CLDR data contains a list of "important" time-zones and can probably be used to pick the ones to display. (I remember something else, but this is the best I can find now)
Multiple time zone ids will exist for the same place if the data was different in the past, or if the place has been renamed (the alias feature in the time-zone data). Removing the backward file when compiling the time-zone data would remove most aliases.
Whether or not the timezone uses daylight savings time is probably the most common difference.

How to use Java timezone id in a Windows (non-Java) application?

I need to add timezone information to a db table with user maintained locations. The data will be accessed mostly from Java code but there is also some PL/SQL and Win32 (Delphi) code which needs to understand the timezone information.
It seems straight forward to use the id from java.util.TimeZone. Java can easily convert that (obviously), Hibernate has built-in support for it and apparently also Oracle understands those timezone ids:
select TZ_OFFSET('Pacific/Marquesas') from dual.
The problem is: the timezone ids do not seem to be compatible with the Windows Timezone DB. For example, the java.util.timezone id "Pacific/Marquesas" (-09:30) is not in the timezone picklist in Windows. The registry does not contain it at all; see
\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones
Here I can only pick either -09:00 or -10:00. So, if I were to store the timezone like this, how can I get to the actual offset/DST infos in Windows (without Java)? Hopefully this does not require a mapping table which I have to keep up to date whenever it changes. Is there a globally accepted standard which works better than the java timezone id?
Update
The timezone info is used in combination with DATE columns on the database. Those columns contain local date/time values. If a location can be associated with those values, the location's timezone enables me to convert the date/time value to UTC or any other timezone whenever needed.
I realize that instead of DATE a TIMESTAMP_TZ data type or something similar would be more appropriate. However, this would require a data migration (for which the TZ is required again) and is not supported by the legacy applications which also work on the data (unless a lot of code is changed). The problem is almost the same if I had to convert the values to UTC.
Bottom line is I need to keep the DATE values in local time but I need to know for some of them which TZ that means.
I can give a little background, if not a real answer.
Many systems use the Olson implementation of timezone data. So those names work in many systems (most Unix, Java, Oracle I think). Microsoft does their own thing.
I see at the bottom of that Wikipedia link there's a reference to some mapping to the Windows world.
Good luck!
I realize this is not the best way to do it, but it might be sufficient in your case. Without knowing all the requirements I can't tell.
What do you need to use the time zone information for? Just to present the time with the correct offset and maybe also the name of the time zone?
You could continue to use Java to determine what the offset of the user is by looking up the user's selected time zone using Java. Each time the user logs in record in your database what the offset currently is. Then other apps can look at this information to determine how to format the time.
This assumes that users who regularly login are the ones that this needs to be done for. If that's not the case you could run a daily job to lookup the time zone for each user in Java and record the offset currently in effect.
Hackish, agreed, but the only other way I see is to maintain a mapping. And what happens when someone selects a time zone that you don't have a mapping for?

Categories