Joda: get local milliseconds of specific timezone - java

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);

Related

java.time.Instant.atZone(...) far in the past return crazy values

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.

Calculating local time offset from GMT time

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.

Java: how to calculate number of days from the beginning of time (with time zones)

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.

How can I parse a Date String with the format "\/Date(1339638938087-0500)\/" in Java?

I have String with the format "\/Date(1339638938087-0500)\/" from a web service api.
Using java, how can I put this into a org.joda.time.DateTime variable?
You need to extract these two bits of information:
-2208967200000: milliseconds since the unix epoch (January 1st 1970 UTC)
-0600: offset from UTC
This assumes that the example represents January 1st 1900 at midnight local time - as the -2208967200000 part represents 6am UTC.
To convert this into a Joda Time DateTime, you should extract the two parts (get rid of everything outside the brackets, and then either use the length to split it, or find the middle +/- symbol).
Next, parse the first part as a long for the millis section.
Then, parse the second part - probably as hours, minutes and sign separately. (I'm assuming it's always in the form xHHmm where x is the sign, HH is the minutes as two digits, and mm is the hours as two digits.)
Create a fixed time zone for the offset using DateTimeZone.forHoursMinutesOffset or something similar.
Finally, create the time with
new DateTime(millis, zone);
Oh, and then kick whoever's producing such a horrible format...
this look like unix timestamp
The unix time stamp is a way to track time as a running total of
seconds. This count starts at the Unix Epoch on January 1st, 1970
If the "2208967200000" is a time in milliseconds since January 1, 1970, 00:00:00, you can use it in constructor for Date(time);
String dateStr="Date(-2208967200000-0600)";
String timeInMillis=dateStr.Split("-")[1];
String utcStr=dateStr.Split("-")[2].Substring(0,4);
Date d=new Date(Long.parseLong(timeInMillis));
if you want you can handle utcStr if it is necessary (if the second part after "-" is a time zone)

JodaTime - how can I know whether a daylight saving occurs within a specified period of time?

I need to know whether the period defined by:
DateTime start;
DateTime end;
has a DST inside.
I am iterating over collection of periods defined by {start,end} and shifting start and end 24 hours forward in every iteration. The resulting period starts at midnight and ends at 1 ms before next midnight. I found that if the period has a daylight saving point inside the shift produces incorrect result, e.g:
having:
Duration targetDuration = new Duration(24*60*60*1000L-1);
DateTime start = new DateTime("2012-03-10T00:00:00.000-08:00");
DateTime end = new DateTime("2012-03-10T23:59:59.999-08:00");
then the shift is done:
start = end.plusMillis(1);
end = start.plus(targetDuration);
produces:
start = "2012-03-11T00:00:00.000-08:00"
end = "2012-03-12T00:59:59.999-07:00"
I wonder is there any standard API in JodaTime that can check whether the period of time has a DST inside?
Use the DateTimeZone.nextTransition method. If the start is less than the end DateTime, then at least one time zone transition has occurred in between. This does not account for rule changes vs. DST. That is, a time zone might have a new rule indicating that standard time has a new offset, and this would appear as a time zone transition.
if (start.getZone().nextTransition(start.getMillis()) < end.getMillis()) {
// Time zone transition occurred, possibly due to DST
...
}
As long as start and end are in the correct time zone (e.g., created using this constructor) then the Interval created using them should take DST for that time zone into account. If the Duration of that Interval is not equal to 24 hours, then you've crossed the DST point.
Because Daylight Savings Time is heavily reliant on TimeZones (some areas don't practice DST, some move clocks 1 hour, some 2 etc) your time variables are going to have to account for location as well.
As such, you might have to have a look at the DateTimeZone class
DateTimeZone

Categories

Resources