平臺
RK3288 + Android 7.1
問題
修改系統時區後, 使用SimpleDateFormat 無法轉化出正確的時間.
final String DatePattern = "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(DatePattern, Locale.getDefault());
@Override
protected void onResume() {
super.onResume();
Date date = new Date();
android.util.Log.d("DateTest", sdf.format(date);
}
測試步驟:
- 進入測試Activity
- 按HOME鍵返回Launcher
- 打開設置->時間和日期
- 關閉自動確認日期和時間, 關閉自動確定時區.
- 選擇一個與當前不同的時區.
- 返回測試Activity.
在這個過程中, onResume會執行兩次, 假設在2->6總共花費了1分鐘, 時區由 GMT+8 切換爲 GMT+1 :
第一次輸出的時間爲:
2019-07-17 08:00:00
第二次輸出的時間爲:
預期: 2019-07-17 01:01:00
實際: 2019-07-17 08:01:00
分析與解決方案
測試後發現, 原因在於SimpleDateFormat中的時區並沒有跟隨實際時區變化而改變:
final String DatePattern = "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(DatePattern, Locale.getDefault());
解決的方法是在時區變化後, 重新創建SimpleDateFormat.
final String DatePattern = "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(DatePattern, Locale.getDefault());
@Override
protected void onResume() {
super.onResume();
sdf = new SimpleDateFormat(DatePattern, Locale.getDefault());
Date date = new Date();
android.util.Log.d("DateTest", sdf.format(date);
}
擴展
在Android中, 可以通過註冊時區變化廣播來觸發更新相關代碼, 參考:
|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filter.addAction(Intent.ACTION_LOCALE_CHANGED);
getContext().registerReceiver(mIntentReceiver, filter, null, null);