Reputation: 1901
Now correct time zone for Moscow is UTC +3
. But Android 4.4.4 only knows UTC +4
for Moscow.
And java.util.Date
give wrong time:
Date now = new Date();
Sat Nov 21 00:37:24 GMT+04:00 2015
1448051844024 in (milliseconds)
Using Joda org.joda.time
DateTime nowWithCorrect = new DateTime()
.withZone(DateTimeZone.forID("Europe/Moscow"));
2015-11-20T23:37:24.023+03:00
1448051844024 in (milliseconds)
But problem is the user (on devices with incorrect time zone) has manually corrected time on device. And joda
and java
give incorrect time in milliseconds.
I get from web service timestamp and on device calculate different with local time. But local time incorrect and give incorrect results.
I want check joda
and java
time and manually to correct timestamp.
Question: can I get different between time zone and different between time in hours (now
and nowWithCorrect
)?
For example: differentTimeZone = 1
, differentTimeHours = 1
Upvotes: 4
Views: 4449
Reputation: 1741
You could find the difference between joda-time timezone (which is based on last IANA) and android system timezone:
long diff = DateTimeZone.getDefault().getOffset(yourTimeStapm) - TimeZone.getDefault().getOffset(yourTimeStapm);
Also you could use fork of joda-time which is used system timezones: https://gitlab.com/olekdia/common/utils/support-joda-time
Upvotes: 0
Reputation: 340350
Russia has gone through some confusing time zone changes in recent years, with Moscow’s offset-from-UTC shifting back-and-forth between +03:00
and +04:00
. See Wikipedia pages on Time in Russia and Moscow Time.
Before autumn of 2011, Moscow had standard time was +03:00
with a Daylight Saving Time (DST) of +04:00
.
Starting in the autumn of 2011, Russia took a decision to stay permanently on DST, +04:00
, and abolish the standard time of +03:00
. See this RT.com article.
In July 2014, that decision was drastically altered. Now Russia is permanently on a standard time of +03:00
and has abolished DST (no more +04:00
).
tz
DatabaseSo I assume your troubles are due to your time zone tz database (formerly known as the Olson database) being outdated. The real Java platform has a tz database, and its host operating system likely has a tz database. Joda-Time has its own tz database. I assume Android does as well, though I do not know about Android.
Obviously keeping all these tz database up-to-date is a real chore.
For Joda-Time, simply replace your Joda-Time library with the latest. While you can replace just the tz database in Joda-Time, as far as I can remember, there are virtually no backward-compatibility issues with Joda-Time 2, so no reason not to update the entire library. But read the release notes to be sure. If using Joda-Time, this is the only minimum requirement for updating; I would recommend updating Android, Java, and host OS as well but not necessary.
For the real Java platform, recent versions made it much easier to update the tz database. Previous versions required some hacking. Alternatively, update to the latest Java 8 to get the latest library.
For your host OS, its regular updating system probably contains tz updates. However, some of those updates may lag behind. So you may need to do a manual update.
The best practice for date-time work is usually to do all of your back-end work in UTC. Business logic, data storage, database, data exchange, and such should all be in UTC. Adjust into a time zone such as Europe/Moscow
only when expected/desired by the user or data sink.
In Java 8 and later, we would use the built-in java.time framework. Use Instant
for a moment in UTC. Specify a ZoneId
to get a ZonedDateTime
when a time zone is needed. But Java 8 technology is not yet available in Android. I believe there is back-port library for java.time for Android, but I do not know the details.
For Joda-Time, ask for the current moment in UTC.
DateTime nowUtc = DateTime.now( DateTimeZone.UTC );
If you cannot trust the user’s local device/computer clock to be accurate and set correctly, then this UTC date-time will be wrong. Nothing you can do about that. Instead trust an outside source, but that assumes a network connection.
Adjust into Moscow time as needed.
DateTime nowMoscow = nowUtc.withZone( DateTimeZone.forID( "Europe/Moscow" ) );
If the user’s tz database for Joda-Time is outdated, this will return a wrong result. No way to prevent that as you cannot predict what the Russian authorities will do next to their time-keeping rules. The only solution is to keep your app updated with a Joda-Time library that has an updated tz database. Or, again, trust an outside source such as your server or some other web service, but that assumes a network connection.
If you are getting confused and want to verify a date-time object’s true value, look at the count-from-epoch.
Both Joda-Time and the old java.util.Date/.Calendar classes count milliseconds from first moment of 1970 UTC. These values are shown in the Question. See how both milliseconds-from-epoch values in the Question are the same, so same moment on the timeline but an incorrect adjustment into Moscow time by Android's Date
class (almost certainly because of an outdated tz database).
Note that java.time uses a different count-from-epoch, counting nanoseconds from same epoch (1970 UTC). In Joda-Time, call getMillis
to get the count-from-epoch. In java.util.Date, call getTime
.
Upvotes: 2