2015-11-21 22 views
4

现在正确的时区莫斯科是UTC +3。但Android 4.4.4只知道莫斯科的UTC +4Android上不正确的时区问题

而且java.util.Date给出错误的时间:

Date now = new Date();  
Sat Nov 21 00:37:24 GMT+04:00 2015 
1448051844024 in (milliseconds) 

使用乔达org.joda.time

DateTime nowWithCorrect = new DateTime() 
           .withZone(DateTimeZone.forID("Europe/Moscow")); 
2015-11-20T23:37:24.023+03:00 
1448051844024 in (milliseconds) 

但问题是用户(在不正确的时区设备)已经手动校正时间的装置。并且jodajava会以毫秒为单位给出错误的时间。

我从网络服务时间戳和设备上获得计算与当地时间不同。但是当地时间不正确并给出不正确的结果

我想检查jodajava时间并手动更正时间戳。

问题:我能得到的时区和不同的时间以小时为单位(nownowWithCorrect)之间有什么不同? 例如:differentTimeZone = 1differentTimeHours = 1

回答

1

混淆时区变化在俄罗斯

俄罗斯已经通过一些容易混淆的时区变化了,近年来,与莫斯科的offset-from-UTC转移+03:00+04:00之间的背部和反复。请参阅Time in RussiaMoscow Time上的Wikipedia页面。

2011年秋季之前,莫斯科的标准时间为+03:00Daylight Saving Time (DST)+04:00

从2011年秋季开始,俄罗斯决定永久停留在DST,+04:00,并取消标准时间+03:00。请参阅this RT.com article

2014年7月,该决定发生了巨大变化。现在俄罗斯永久在+03:00的标准时间,并已废除夏令时(不再更多+04:00)。

过时tz数据库

所以我假设你的烦恼是由于您的time zone tz database(前身为奥尔森数据库)是过时的。真正的Java平台有一个tz数据库,它的主机操作系统可能有一个tz数据库。 Joda-Time拥有自己的tz数据库。我认为Android也是如此,尽管我不了解Android。

显然保持所有这些tz数据库是最新的是一件真正的苦差事。

对于Joda-Time,只需使用最新版本替换您的Joda-Time库。尽管您可以用Joda-Time替换tz数据库,但据我记忆,Joda-Time 2几乎没有向后兼容性问题,所以没有理由不更新整个库。但请仔细阅读发布说明。如果使用Joda-Time,这是更新的唯一最低要求;我会建议更新Android,Java和主机操作系统,但不是必需的。

对于真正的Java平台,最新版本使得更新tz数据库变得更容易。以前的版本需要一些黑客攻击。或者,更新到最新的Java 8以获取最新的库。

对于您的主机操作系统,其常规更新系统可能包含tz更新。但是,其中一些更新可能会落后。所以你可能需要手动更新。

工作在UTC

日期时间工作最好的做法通常是做所有的后端工作的UTC。业务逻辑,数据存储,数据库,数据交换等都应该使用UTC。仅当用户或数据接收器预期/期望时才调整为时区,例如Europe/Moscow

在Java 8及更高版本中,我们将使用内置的java.time框架。在UTC中使用Instant片刻。当需要时区时指定ZoneId以获得ZonedDateTime。但Java 8技术尚未在Android上提供。我相信Android的java.time有后端库,但我不知道细节。

对于Joda-Time,请求UTC中的当前时刻。

DateTime nowUtc = DateTime.now(DateTimeZone.UTC); 

如果你不能信任用户的本地设备/计算机时钟是准确的设置正确,那么这UTC日期时间将是错误。你无能为力。取而代之的是信任外部来源,但假设有网络连接。

根据需要调整为莫斯科时间。

DateTime nowMoscow = nowUtc.withZone(DateTimeZone.forID("Europe/Moscow")); 

如果乔达时间用户的时区信息数据库已经过时,这将返回一个错误的结果。没有办法阻止,因为你无法预测俄罗斯当局在遵守时间规则方面会做什么。唯一的解决方案是让您的应用程序更新为具有更新后的tz数据库的Joda-Time库。或者,再次相信外部来源,例如您的服务器或其他Web服务,但假定网络连接。

验证计数,从历元

如果你感到困惑,并希望确认一个日期时间对象的真实价值,看看计数从 - epoch

Joda-Time和旧的java.util.Date/.Calendar类都从1970年的UTC开始计数milliseconds。这些值显示在问题中。看看问题中的两个毫秒的时间值是相同的,所以时间轴上的时间同样如此,但是由于Android的Date类(几乎肯定是因为过时的tz数据库)导致莫斯科时间的调整不正确。

请注意,java.time使用不同的从历元计数,从同一纪元(1970年UTC)计数nanoseconds。在Joda-Time中,拨打getMillis即可获得从时间计数。在java.util.Date中,请致电getTime

+0

我只能在外部帮助下解决问题,例如http://tf.nist.gov/tf-cgi/servers.cgi。谢谢,你以正确的方式思考。 – Alexandr

+0

如果从纪元计数是正确的,那么即使莫斯科的壁钟时间由于过时的tz数据库而错误,用户的时钟也是正确设置的。解决方案是捆绑Joda-Time,保持更新,并避免使用旧的Java.util.Date/.Calendar类。另外,我记得其他人为Android提供了一个不同版本的Joda-Time,因为Android的性能限制导致最初的放缓。 –