I have a requirement where I only have GMT time without any offset, example 15:00:00, my requirement is to find out what timezone this GMT time belongs to, I have tried to solve it by using my local time and converting it to GMT time and doing some comparison but I don't think that it might be the right way to do it.
Assuming that the time is definitely offset from GMT, you should be able to produce a GMT timestamp using the following, and then compare the two. Your resulting answer, converted back to hours, should be the offset, which you can then lookup.
new Date().getTime();
Note that this doesn't take into account daylight savings/summer time etc, and assumes that the time given is right now, and can therefore be compared to the current GMT time. Specifically, remember that a timezone can fluctuate by a couple of hours if, like the UK and Australia, their summer/winter periods are reversed, so a +11 hour time zone offset may actually be +10 or +12 at any given point in time. And some countries don't use DST at all, even in the same time zone.
Note also that the entire point of time zone offsets and use of a centralised time (eg UTC) is to avoid the above confusion. By definition, you're doing things the long way round and introducing levels of uncertainty.
You may therefore have one country in the northern hemisphere varying +/- 1 hour, one in the southern varying -/+ 1 hour, and one near the equator using the same time constantly... and you'd have no idea which ones are meant to be in that time zone. You can find the offset, but that's about it.
Related
I detect the following output when converting an Instant that is far in the past to a ZonedDateTime.
Code as Unit-Test:
#Test
public void testParseDate() {
Instant instant = Instant.parse("0000-12-30T07:00:00Z");
System.out.println(instant);
System.out.println(instant.atZone(ZoneId.of("Europe/Berlin")));
instant = Instant.parse("1800-12-30T07:00:00Z");
System.out.println("---------------------------------");
System.out.println(instant);
System.out.println(instant.atZone(ZoneId.of("Europe/Berlin")));
instant = Instant.parse("1900-12-30T07:00:00Z");
System.out.println("---------------------------------");
System.out.println(instant);
System.out.println(instant.atZone(ZoneId.of("Europe/Berlin")));
}
Output:
0000-12-30T07:00:00Z
0000-12-30T07:53:28+00:53:28[Europe/Berlin]
---------------------------------
1800-12-30T07:00:00Z
1800-12-30T07:53:28+00:53:28[Europe/Berlin]
---------------------------------
1900-12-30T07:00:00Z
1900-12-30T08:00+01:00[Europe/Berlin]
In the first two outputs the time is 07:53:28+00:53:28 and the last output is 08:00+01:00[Europe/Berlin]. Maybe the root cause is that the time zone stuff doesn't yet exists in the years of the first two examples, but the offset of +00:53:28 is really strange.
Any idea where this offset "+00:53:28" comes from?
Because history.
On April 1st, 1893, the time zone was adjusted from Local Mean Time (LMT), a local time zone (which was common at that time), to Central European Time (CET), adjusting the clock by 6 minutes and 32 seconds.
Timezones are regularly changed due to political decisions, but those strange amounts like 6 minutes and 32 seconds are often the result of moving from a local mean time to a standardized time.
Many known historical changes are found at timeanddate.com, and Berlin specifically at https://www.timeanddate.com/time/zone/germany/berlin.
Timezones, Daylight Saving, and all those annoying and fancy features, did not exist at the beginning of the 20th century.
There were many "variations" of the time, like the infamous Dutch Time which was about 19 minutes ahead of UTC, mostly based on the clock of a tower which was simply that amount of time ahead.
I don't know exactly where the time difference comes from in the case of Germany and Berlin, but it's a known offset (likely based on similar reasons as the Dutch Time).
You can see how it has evolved over time.
I never would believe that this could amount to being such a hassle. I am trying to make a clock that always displays the local time in specific timezones.
My laptop is currently set in GMT0 timezone (UK).
I want to get the milliseconds of the timezone "Europe/Stockholm".
So let's say it's 17:00 here in the UK I would like to get the milliseconds corresponding to 18:00 which would be the Swedish time.
The time in milliseconds as used by Date is independent of the time zone. Only when you print (or parse) a time, you use a DateFormat that is localized, so it ensures you get the time in the specific timezone.
When time is represented as milliseconds (or seconds or nanoseconds, etc), that is almost always milliseconds since some epoch. In the case of unix and java, this is midnight Jan 1, 1970 UTC.
Time zones are generally arranged as a round number of hours relative to UTC. In certain time zones it's not a round hour but 30 minutes, 15 minutes or 45 minutes from a round hour.
Nevertheless, for any time unit below a minute, all those time zones match UTC exactly.
Therefore, whatever the current second or millisecond is in Sweden, it is the same as it is, for example, in Nepal, whose time zone is 5:45 minutes from UTC.
When you work with an object that allows you to retrieve the separate fields of the given time, the milliseconds field will usually reflect just the number of milliseconds since the beginning of the current second, not the number of milliseconds since midnight. Therefore it will never be more than 999, and it will be the same the world over.
After reading the answers here and discovering another route, this is what finally worked for me.
DateTime curDateTime = new DateTime();
int offset = DateTimeZone.forID("Europe/Stockholm").getOffset(curDateTime.getMillis());
long milli = (curDateTime.getMillis()+offset);
I have two longs representing time since the epoch. They both have the same timezone. I want to find the difference in seconds between these two times, respecting day light savings.
(def a (java.util.Date. 1259568796000)) ;; Before Day Light Savings
(def b (java.util.Date. 1255147200000)) ;; After Day Light Savings
Where 'a' is 2009-11-30T08:13:16.000-00:00
and
Where 'b' is 2009-10-10T04:00:00.000-00:00
Using JodaTime, I can make an Interval out of these two times, turn them into a Duration, and get the StandardSeconds.
(.getStandardSeconds (.toDuration (Interval. a b)))
This doesn't work though, because the docs for Period indicate that Duration will mess up Day Light Savings:
When this time period is added to an instant, the effect is of adding
each field in turn. As a result, this takes into account daylight
savings time. Adding a time period of 1 day to the day before daylight
savings starts will only add 23 hours rather than 24 to ensure that
the time remains the same. If this is not the behaviour you want, then
see Duration.
How can I accomplish this task?
The long in Java represents a certain point in time (milliseconds since midnight on 1.1.1970, ignoring leap seconds). They don't carry a time zone and do not switch with daylight savings time, it is always expressed in UTC. To find the difference in seconds between two such timepoints you can use
(secondTime - firstTime) / 1000
The two times you have given are expressed in GMT, i.e.
1259568796000 = 2009-11-30T08:13:16.000-00:00 GMT
1255147200000 = 2009-10-10T04:00:00.000-00:00 GMT
And GMT does not switch to daylight savings time either. Maybe you were confused by that.
The java.util.Calendar class has support for daylight savings. Perhaps run your dates through that first? It should do the normalization for you. Check out this other post.
I want to calculate the number of days from the "beginning of time" to a current date. This could be easily achieved with a simple calculation (timestamp / 24 / 60 / 60 / 1000 = daysFromBeginningOfTime) but the twist is that i need to be aware of time zones as well. The timestamp is the same everywhere in the world but when you parse it with the proper time zone then it reflects the differences between locations so using just the timestamp doesn't work and i don't want to handle all the time zone transitions myself.
Example:
if it's 23:30 in London and the day number is 18843 then in Amsterdam it's 0:30 and the day number should be 18844.
I looked at joda.time but didn't really find what i was looking for.
Anyone have any ideas?
The problem appears due to a wrong initial assumption, I think.
The argument the OP makes in his example is not correct. No matter what the clock shows in London or Amsterdam, the time difference to the start of the epoch is - at every point of time - independent of where you are in the world.
Hence, the solution is to parse a given input date to an UTC timestamp and proceed as before.
(Ignoring the point that zero is not "the beginning of time" ... and that the actual time point for the beginning of time is probably unknowable ...)
Here's how to calculate the number of days since "the local-time UNIX epoch in a given timezone"1.
Get hold of the object that represents the local timezone.
Get the timezone's offset from the object
Convert it to milliseconds and add it to the current UTC time.
Calculate the day number as before.
1 - ... whatever that means.
When I run the below line,
System.out.println(java.util.TimeZone.getDefault());
I got the following output.
sun.util.calendar.ZoneInfo[id="Asia/Calcutta",
offset=19800000,
dstSavings=0,
useDaylight=false,
transitions=6,
lastRule=null]
and
System.out.println(Locale.getDefault()); gives
`en_US`
My doubt is
How could the Locale be en_US, When My Zone id is Asia/Calcutta?
in the first output, I haven't understood what are offset, dstSavings, useDaylight, transitions and rules ?
Could anybody help in understanding these.
Thanks in advance...
Locale has nothing to do with TimeZone, you can setup your computer in French in Australia if you want... you won't need France TimeZone for that.
To know more about TimeZone, you should read theses :
TimeZone
What is a TimeZone
The class that actualy give you the toString() : ZoneInfo
useDaylightTime
public abstract boolean useDaylightTime()
Queries if this time zone uses daylight savings time.
What is Daylight Saving Time.
getDSTSavings
public int getDSTSavings()
Returns the amount of time to be added to local standard time to get local wall clock time.
So this is the difference between the UTC + TimeZone + (DSTSavings - 0 or 1 hour). If you are currently in DST savings mode, will return 1 hour.
rules
Rules mean the date when the DST is active and date when it is no more. More info SimpleTimeZone.
transitions
This array describes transitions of GMT offsets of this time zone, including both raw offset changes and daylight saving time changes. A long integer consists of four bit fields.
The most significant 52-bit field represents transition time in
milliseconds from Gregorian January 1 1970, 00:00:00 GMT.
The next 4-bit field is reserved and must be 0.
The next 4-bit field is an index value to offsets[] for the amount of daylight saving at the transition. If this value is zero, it means
that no daylight saving, not the index value zero.
The least significant 4-bit field is an index value to offsets[] for total GMT offset at the transition.
If this time zone doesn't observe daylight saving time and has never
changed any GMT offsets in the past, this value is null.
Check this question to understand how Locale.getDefault() actually works.
As for your output for System.out.println(java.util.TimeZone.getDefault());
DST Savings: The base implementation returns 3600000 (1 hour) for
time zones that use daylight savings time and 0 for timezones that
do not
Offset: This is the offset of your timezone w.r.t GMT. For India,
it is 5hr30min which is 19800000 ms
UseDaylight: This shows that there is no daylight adjustment for
this timezone .
Transitions: This refers to the daylight saving time transitions
of a timezone.
LastRule: Returns a SimpleTimeZone object representing the last GMT
offset and DST schedule or null if this time zone doesn't observe
DST.
Hope this helps.