Android 修改系统时区导致SimpleDateFormat无法输出正确时间

平台

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

测试步骤:

  1. 进入测试Activity
  2. 按HOME键返回Launcher
  3. 打开设置->时间和日期
  4. 关闭自动确认日期和时间, 关闭自动确定时区.
  5. 选择一个与当前不同的时区.
  6. 返回测试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);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章