I've an application that depends heavily on Java. We do extensive logging, database insertion, etc. After the day light timing switch we noticed that all Java time is about an hour behind. We've Jre version of 1.6_18. I thought this issue was resolved in earlier versions of Java. Do suggest as to what can be done, if there are any patches for this.
Timezone information is modified periodically. Java 6 update 18 is likely to have out of date DST settings for your location.
Either upgrade to the latest (update 25) or run the TZupdater tool.
EDIT: I have just discovered that Oracle provides an RSS feed for timezone updates. If your application absolutely must have the most recent TZ data keep an eye on this.
tl;dr
Your database of time zone ‘tz’ info is likely out-of-date.
Use the back-port of java.time classes.
See Tutorial.
Includes up-to-date ‘tz’ database.
Avoid troublesome old legacy date-time classes from earliest Java.
Use UTC for most of your work.
Use UTC
Think of UTC as the “one true time”. Any date-time for a particular time zone is a derivation of UTC. When at work doing programming or sys-admin work, forget about your own local time zone. I strongly suggest adding a clock to both your physical and digital desktops displaying UTC. In a pinch, use a web site such as Time.is.
Most of your business logic, logging, data storage, data exchange, and database persistence should all be in UTC. Adjust into a time zone only for presentation.
Avoid old date-time classes
Avoid the troublesome old legacy date-time classes bundled with the earliest versions of Java. Now supplanted by the java.time classes.
Instant
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds.
Instant now = Instant.now(); // Current moment in UTC.
Specify time zone
The Java Virtual Machine has a current default time zone. This may be picked up at launch from the host OS. Or it may be set at launch by configuration settings. Or it may be changed at any moment by any code in any thread of any app within the JVM -- affecting all other code during execution!
Given that the JVM’s current default time zone varies, and is outside your control as a programmer, never depend on it. Always specify your desired/expected time zone.
Generally best to keep server host OS set to a time zone of UTC, but again, never depend on that in your programming.
ZonedDateTime
To adjust an Instant into a time zone, generate a ZonedDateTime object.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
Call toString to generate a String in standard ISO 8601 format. For other formats, search Stack Overflow for the class DateTimeFormatter.
Update your tz time zone database
Time zone definitions and their anomalies such as Daylight Saving Time (DST) change frequently, surprisingly often.
Oracle release regular updates of Java that include fresh copies of the tz database. If you cannot install those Java updates, or if a nearly last-minute change to zones was made by some careless politicians, you can manually update your Java using the Timezone Updater Tool by Oracle.
Locale
Know that Locale has nothing to do with time zone. A Locale defines (a) a human language to use for translation, and (b) cultural norms deciding issues such as abbreviation, punctuation, and order of parts. So you only need a Locale when generating Strings, when using the DateTimeFormatter class.
Locale l = Locale.CANADA_FRENCH;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( l );
String output = zdt.format( f );
So a time zone defines the meaning of a date-time value, but a Locale defines its presentation.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Related
I need to store datetime records with IANA database current version used (2022g for example). How could I get it with Go?
I tried to search this on standard "time" package, but it seems that there isn't any functionality for this. I am expecting that there is some function that can return IANA tzdb version as a string.
UPDATE 1 according to comments below I need to clarify the problem:
The main problem is I want to store some FUTURE events. The event object has several fields:
Local dateTime
Timezone
UTC datetime
To keep my data up to date with IANA database (timezone, daylight saving time may change) I need to store current version of tzdb version. That will help me to write correct data migration of my events when new version of tzdb was released. So I need to add one more field with version of current tzdb that had been used to populate the time.
And I am trying to figure out how can I get the current version of my tzdb that Go application is using right now to store that version.
Also I am opened to alternative solutions of storing time records with extra accuracy of long-lived future events.
Update 2: This events are bounded to exact location.
The discussion thread in the comment is pretty long, but I'll attempt to answer and address some of the concerns. (I won't address the question in the title, as I believe that is not straightforward in Go.)
Indeed, future scheduling of events should be in terms of the time zone where the event takes place - which is usually not UTC.
Time zone identifiers will never be removed or renamed (with rare exception anyway). Once introduced, the identifier will either maintained as a Zone or as a Link in the TZDB indefinitely. Thus, you don't need to check that the time zone still exists. (Windows time zone IDs are also like this.)
DST is only one aspect of picking the correct offset. The standard time may have changed as well. However, all of that is encapsulated in the tzdb itself. You shouldn't need to concern yourself about which version of the tzdb was in effect when you created the event.
The general approach to this issue in most cases is:
Store the scheduled local date, time, and time zone ID of the event (local with regard to the time zone of the event).
Example: 2030-12-31T00:00:00[America/New_York]
At the time you create the event, also calculate a UTC value (or equivalent DateTimeOffset value) and store that in a separate field - so you know exactly when to fire the event:
Example: 2030-12-31T05:00:00Z (or 2030-12-31T00:00:00-05:00)
Periodically check that your UTC equivalent is correct. This can be in a daily maintenance task, or on application startup, or just before the event (perhaps also an hour before the event), or all of these.
The offset will only be different than projected if the time zone data changed on the device to give it a new offset. For example, let's hypothetically say the lawmakers in the USA succeed at making DST permanent sometime before this event takes place. Then the equivalent UTC time for the same event would now be 2030-12-31T04:00:00Z (or 2030-12-31T00:00:00-04:00).
In such cases, update the UTC time of the event if it has changed, but the original local time of the event usually should not be modified. Human beings tend to schedule things in terms of local time, not in terms of their UTC equivalents.
The only advantage knowing the TZDB version would give you, is you could do that last step less often - only when knowing the data has changed. I see that as an optimization though - it's not usually required.
Without such legal changes to time zone definitions, the mere start/stop of DST as scheduled is not a reason to worry about this. That is already accounted for by using the TZDB in the first place.
If the event is recurring (say a 10:00 AM daily meeting), each occurrence might have a different offset, but the local time will be consistent and the TZDB doesn't need to be updated to calculate it.
Seems easy but I didn't find a way to convert an UTC datetime to a specified timezone. I found how to convert an UTC date time to local date-time, but now I want to convert to a specific timezone (i.e. for example Moscow time)
For example in c# we can do:
// user-specified time zone
TimeZoneInfo southPole =
TimeZoneInfo.FindSystemTimeZoneById("Antarctica/South Pole Standard Time");
// an UTC DateTime
DateTime utcTime = new DateTime(2007, 07, 12, 06, 32, 00, DateTimeKind.Utc);
// DateTime with offset
DateTimeOffset dateAndOffset =
new DateTimeOffset(utcTime, southPole.GetUtcOffset(utcTime));
Console.WriteLine(dateAndOffset);
But how to do in Delphi ?
A few things:
"Antarctica/South Pole Standard Time" isn't a real time zone identifier. I assume you gave that in jest, but it makes it unclear as to whether you want to use Windows time zone identifiers (like "Eastern Standard Time"), or IANA time zone identifiers (like "America/New_York").
Assuming you want to use Windows identifiers, you can indeed use the functions in the Win32 API. The comment in the question suggested the wrong API however. You should instead use SystemTimeToTzSpecificLocalTimeEx.
It uses the DYNAMIC_TIME_ZONE_INFORMATION structure, which have been available since Windows Vista. To get one of those from a named Windows time zone identifier, use the EnumDynamicTimeZoneInformation function to loop through the system time zones until you find the one matching on the TimeZoneKeyName field.
The "dynamic" structures are important to use, and should always be preferred over their older counterparts. They allow access to changes in time zones and daylight saving time rules that are stored in the Windows registry. Without them, you only get access to the current rule, which might not be the correct rule for the date you are converting.
If you instead wanted to use IANA time zone identifiers, use the Delphi tzdb library, as shown in this post.
If you are uncertain of which to use, I highly recommend this approach. IANA identifiers are inter-operable with other operating systems, programming languages, frameworks, and libraries. (Windows identifiers, less so.)
I work for an organization in two locations. One of them is Chile, where daylight savings time is extremely unpredictable and often varies from year-to-year. We have an application that is dependent on time and up until now, have been using joda time. When the Chilean government decides to change daylight savings, we use joda code to set an offset to the default DateTimeZone:
/**
* Updates the default time zone, i.e. the time zone which is used as local time.
*/
private void updateDefaultTimeZone() {
if (isEmpty(Configuration.Value.TIME_ZONE_OFFSET)) {
// make the site's default time zone the current time zone for joda time,
// this should always be the case for the non-Chile site, and work for the Chile site during most of the year
DateTimeZone.setDefault(siteService.getSiteTimeZone());
} else {
// makes a user defined time zone the current time zone for joda time
// this will be used when Chile is delaying or pulling forward the transition from/to daylight
// saving time and the JVM is therefore not able to calculate the local times appropriately
Integer offset = getInteger(Configuration.Value.TIME_ZONE_OFFSET);
DateTimeZone.setDefault(DateTimeZone.forOffsetHours(offset));
}
}
We're trying to transition our code base from joda time to Java 8 time, but I have really no idea the classes that are involved in doing something similar. I'm guessing perhaps ZoneRules, but I'm not sure. Does anyone have any hints as to how to most cleanly accomplish this?
Additionally, what is the best way of converting units in Java 8 time? Say I have 24 hours and I want to convert it into days. (I ask because in this case, it seems many methods work with milliseconds and I want to work with hours, but think there must be a better built-in way to convert than to do the arithmetic by hand.)
Use java.util.TimeZone.setDefault(TimeZone). Because JSR-310 java.time.* is integrated with the JDK, there is no need for a separate method.
(To convert units, you may find it easiest to use TimeUnit, but perhaps a separate more focussed question would help you there.)
JodaStephen has said it. He’s the lead developer of both Joda-Time and java.time, so definitely the authority here. I add just some supplementary thoughts.
Consider not relying on a default time zone
The default time zone of the JVM can be changed at any time from another part of your program and from other programs running in the same JVM. So relying on it is fragile. java.time (Java 8 time) consistently offers you the possibility of specifying time zone for all time zone sensitive operations. My habit is to use this. So my suggestion is that you store the time zone somewhere in your program where you alone control who’s tampering with it and code your date and time operations to use this stored setting and not the default time zone of the JVM.
If you still rely on the default: The TimeZone class has a bad design flaw. This would look sound to me at first sight:
TimeZone.setDefault(TimeZone.getTimeZone("America/Santiago_de_Chile"));
It isn’t! Look at the output from
System.out.println(TimeZone.getDefault().getID());
GMT
Extremely confusing IMHO. The correct time zone ID is America/Santiago, not America/Santiago_de_Chile. So we should have expected an IllegalArgumentException or similar here. Instead TimeZone just tacitly gives us a completely wrong time zone, GMT.
Instead use:
TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("America/Santiago_de_Chile")));
Exception in thread "main" java.time.zone.ZoneRulesException: Unknown time-zone ID: America/Santiago_de_Chile
Time unit conversions
Like JodaStephen I routinely use TimeUnit for time unit conversions, but I try to remember to think twice before doing so.
System.out.println(TimeUnit.HOURS.toDays(24));
System.out.println(TimeUnit.DAYS.toHours(400_000_000_000_000_000L));
1
9223372036854775807
It looks right, doesn’t it? It isn’t either! For two reasons:
A day is not always 24 hours. When Chile goes from standard time to summer time (DST) or vice versa, a day is 23 or 25 hours.
The conversion doesn’t report long overflow. The latter conversion overflows. TimeUnit tacitly gives us the closest value that can fit in a long, in this case the value of Long.MAX_VALUE.
When you know what you are doing and you know your conversions don’t overflow, you may use it. I also do most of my int math without checking for overflow. java.time offers a nice converstion that does check for overflow:
System.out.println(Duration.ofDays(400_000_000_000_000_000L).toHours());
Exception in thread "main" java.lang.ArithmeticException: long overflow
I even find this code a bit more readable than the TimeUnit code.
I want to have one feature in my windows phone application where i will require to see if for the time zone whether the daylight settings is currently on or off.
I can get this detail for the time zone which is set in my phone, but what i want is that i can get this for any time zone i pass or set.
For example, if i pass time zone "Antarctica/Palmer", i should able to find whether currently daylight setting is on or off. I tried few things but not able to find anything. I do
not want to use any web api to give me this.
Is there any facility where i can set the timezone via code to get the result and then revert it back to original or some other solution?
Thanks.
There's the IsDaylightSavingTime method:
Indicates whether a specified date and time falls in the range of daylight saving time for the time zone of the current TimeZoneInfo object.
It requires you to have a TimeZoneInfo object, but you indicate that you already have that.
For example, if i pass time zone "Antarctica/Palmer", i should able to find whether currently daylight setting is on or off.
That looks like a zoneinfo/tzdb/Olsen time zone ID to me, not one that Windows in general uses. My Noda Time project uses tzdb and would be able to get you that information, but we don't currently build a Silverlight version - we probably could with a bit of work, but it wouldn't be trivial. Patches would be welcome, of course...
Do you definitely want to use tzdb IDs, or would the appropriate Windows ID be okay for you? Unfortunately TimeZoneInfo.FindSystemTimeZoneById appears not to be supported on Silverlight :(
All the Timezone in Windows are displayed in such a way like
(GMT+10:00) Canberra, Melbourne, Sydney,
GMT and Offset and the place. In turn , the Linux is having every timezone as directory mapping in /usr/share/zoneinfo/[Continent]/[Place].
I am in need of mapping every Windows timezone to the Linux timezone for my application.
like
(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi => Asia/Calcutta
Now the problem surface for the International Date Line West which lies between Russia and America. In Windows, its marked by (GMT-12:00) International Date Line West and from various sources I found that in Linux its Etc/GMT+12.
(GMT-12:00) International Date Line West => Etc/GMT+12
also
(GMT+12:00) Coordinated Universal Time+12 => Etc/GMT-12
(GMT-02:00) Coordinated Universal Time-02 => Etc/GMT+2
(GMT-11:00) Coordinated Universal Time-11 => Etc/GMT+11
This keeps me puzzled and my app works closely with the Timestamp w.r.t UTC and the UTC offset. So this mapping is confusing me and the app.
Can anyone explain why there is a vice versa of -12 and +12 Offset in both for a same place?
Thanks in Advance :)
Unicode.org hosts a mapping as part of the CLDR. You can get to the latest version here. There are also XML versions of the data linked from that page.
You can find example code (in Python) of how to generate a mapping from the XML data here.
Obligatory Time Zone Rant:
Note that whoever implemented the timezone support in Windows was on drugs. I'm not kidding you. Look at the timezone names. Why is Central European time known as "Romance standard Time". Romance? What, because it includes Paris, or? Roman Standard Time could have made sense a it also includes Rome, but Romance!?
Also, in the registry the timezones are not organized under their id. No, they are, insanely, organized under their display name! Since that is localized, it means every timezone will be located under a different key in different translations of Windows!!! So to find the right timezone, you have to look through all the timezone to see which has the correct id.
I have example code of that too here. See the get_win_timezone() function.
I wonder if it is the same guy who designed this that decided that POSIX should reverse the sign on timezones, so that -8 hours mean plus 8 hours. In any case, I'm sure they were smoking something illegal together.
If all the files have the signs reversed, then the files you are looking at are forward mapping offsets, while what you are probably more familiar with is reverse mapping offsets.
Windows typically uses the local timezone for the machine's internal time, so it needs timezone files which can translate back to UTC. Linux typically uses UTC as the machine's internal time, so it needs timezone files which can translate to local time.
Since the offsets for the two machines describe complimentary but opposite directions of time, it stands to reason that the time zone files are inversely related to each other. In other words, if you pick up a set of zone files from one, the other set will be negative.
The definitions in the Etc directory are meant to be POSIX style, thus they have their sign reversed from what you would expect. I'm not an expert for POSIX, but as far as I get it, the basic idea was to express timzones by the combination of their local name and the offset to GMT. An example for middle europe (Central European Time / CET):
Europe/Berlin (w/o daylight savings) equals GMT+01:00 equals CET-1
GMT-1 in the Etc directory in fact describes a (fictous) timezone called "GMT" which is one hour ahead of (the real) GMT.
As far as I know, these files are only there to allow you to create (symbolic) links against them, so if you were situated somwhere in middle europe, you would create a link to GMT-1 and call it CET-1.
The best recommendation I can give you is to entirely ignore the Etc directory and use some mapping table from windows timezone names to unix timezone folders/files. Windows timezone info does not only give the offset to GMT, but also knows about Daylight Savings (and when in begins or ends). The same is true for the folders/files in the timezone database, but not for the files in the Etc directory - they give a simple static offset to GMT.
A list of time zones in the tz database can be found in the wikipedia.