平台
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);