2015-11-21 53 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的性能限制導致最初的放緩。 –