如果 phone 时区已更改,则 SimpleDateFormat setTimeZone 不起作用
SimpleDateFormat setTimeZone not working if phone timezone has changed
我在使用 SimpleDateFormat 和时区时遇到了一个奇怪的问题。
基本上,我有这个代码片段:
String input = "2017-12-21 16:15:00";
String inputTZ = "America/Los_Angeles";
String phoneTZ = TimeZone.getDefault().getID();
SimpleDateFormat fmtInput = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
fmtInput.setTimeZone(TimeZone.getTimeZone(inputTZ));
SimpleDateFormat fmtOutputEventTZ = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
fmtOutputEventTZ.setTimeZone(TimeZone.getTimeZone(inputTZ));
SimpleDateFormat fmtOutputPhoneTZ = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
fmtOutputPhoneTZ.setTimeZone(TimeZone.getTimeZone(phoneTZ));
try {
LocalDateTime dt = new LocalDateTime(fmtInput.parse(input));
Log.d("DEBUG>>>>", "INPUT=" + input);
Log.d("DEBUG>>>>", "TZ_EVENT=" + inputTZ);
Log.d("DEBUG>>>>", "TZ_PHONE=" + phoneTZ);
Log.d("DEBUG>>>>", "DT=" + dt);
Log.d("DEBUG>>>>", "OUTPUT_EVENT=" + fmtOutputEventTZ.format(dt.toDate()));
Log.d("DEBUG>>>>", "OUTPUT_PHONE=" + fmtOutputPhoneTZ.format(dt.toDate()));
}
catch (Exception e) {
e.printStackTrace();
}
代码逻辑如下:
- 我有一个洛杉矶时区 (GMT-8) 的输入日期
- 我解析这个指定时区 (LA) 的日期
- 然后我使用原始时区 (LA) 和当前 phone 时区
格式化日期
我 运行 将我的 phone 时区设置为芝加哥 (GMT-6) 的代码并得到以下输出。
D/DEBUG>>>>: INPUT=2017-12-21 16:15:00
D/DEBUG>>>>: TZ_EVENT=America/Los_Angeles
D/DEBUG>>>>: TZ_PHONE=America/Chicago
D/DEBUG>>>>: DT=2017-12-21T18:15:00.000
D/DEBUG>>>>: OUTPUT_EVENT=2017-12-21 16:15:00
D/DEBUG>>>>: OUTPUT_PHONE=2017-12-21 18:15:00
基本上,结果是预期的。
但是,如果我将 phone 时区更改为纽约 (GMT-5) 时区而不重新启动应用程序,我会得到以下输出
D/DEBUG>>>>: INPUT=2017-12-21 16:15:00
D/DEBUG>>>>: TZ_EVENT=America/Los_Angeles
D/DEBUG>>>>: TZ_PHONE=America/New_York
D/DEBUG>>>>: DT=2017-12-21T18:15:00.000
D/DEBUG>>>>: OUTPUT_EVENT=2017-12-21 15:15:00
D/DEBUG>>>>: OUTPUT_PHONE=2017-12-21 18:15:00
注意 TimeZone.getDefault().getID()
返回的时区是正确的,但是在解析时,SimpleDateFormat 将其转换为好像 phone 时区仍然是芝加哥,从而返回错误的时间!
但是,如果我终止应用程序并重新启动它,相同的代码可以正常工作:
D/DEBUG>>>>: INPUT=2017-12-21 16:15:00
D/DEBUG>>>>: TZ_EVENT=America/Los_Angeles
D/DEBUG>>>>: TZ_PHONE=America/New_York
D/DEBUG>>>>: DT=2017-12-21T19:15:00.000
D/DEBUG>>>>: OUTPUT_EVENT=2017-12-21 16:15:00
D/DEBUG>>>>: OUTPUT_PHONE=2017-12-21 19:15:00
根据我的理解,SimpleDateFormat.parse
解析日期并将其存储为自 1970 年以来的秒数。使用 setTimeZone
应该使用时区来适当地偏移时间。
但是,似乎 phone 时区变化没有被 SimpleDateFormat 反映出来,而 TimeZone.getDefault().getID()
清楚地反映了变化。
有什么办法可以解决这个问题吗?
找到解决方案!
我一开始就叫了DateTimeZone.setDefault(DateTimeZone.forID(TimeZone.getDefault().getID()))
我想 DateTimeZone.setDefault
在应用程序启动时被调用,但之后不会被 joda-time 本身重置,即使用户的时区可能已经改变。
我在使用 SimpleDateFormat 和时区时遇到了一个奇怪的问题。
基本上,我有这个代码片段:
String input = "2017-12-21 16:15:00";
String inputTZ = "America/Los_Angeles";
String phoneTZ = TimeZone.getDefault().getID();
SimpleDateFormat fmtInput = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
fmtInput.setTimeZone(TimeZone.getTimeZone(inputTZ));
SimpleDateFormat fmtOutputEventTZ = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
fmtOutputEventTZ.setTimeZone(TimeZone.getTimeZone(inputTZ));
SimpleDateFormat fmtOutputPhoneTZ = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
fmtOutputPhoneTZ.setTimeZone(TimeZone.getTimeZone(phoneTZ));
try {
LocalDateTime dt = new LocalDateTime(fmtInput.parse(input));
Log.d("DEBUG>>>>", "INPUT=" + input);
Log.d("DEBUG>>>>", "TZ_EVENT=" + inputTZ);
Log.d("DEBUG>>>>", "TZ_PHONE=" + phoneTZ);
Log.d("DEBUG>>>>", "DT=" + dt);
Log.d("DEBUG>>>>", "OUTPUT_EVENT=" + fmtOutputEventTZ.format(dt.toDate()));
Log.d("DEBUG>>>>", "OUTPUT_PHONE=" + fmtOutputPhoneTZ.format(dt.toDate()));
}
catch (Exception e) {
e.printStackTrace();
}
代码逻辑如下:
- 我有一个洛杉矶时区 (GMT-8) 的输入日期
- 我解析这个指定时区 (LA) 的日期
- 然后我使用原始时区 (LA) 和当前 phone 时区 格式化日期
我 运行 将我的 phone 时区设置为芝加哥 (GMT-6) 的代码并得到以下输出。
D/DEBUG>>>>: INPUT=2017-12-21 16:15:00
D/DEBUG>>>>: TZ_EVENT=America/Los_Angeles
D/DEBUG>>>>: TZ_PHONE=America/Chicago
D/DEBUG>>>>: DT=2017-12-21T18:15:00.000
D/DEBUG>>>>: OUTPUT_EVENT=2017-12-21 16:15:00
D/DEBUG>>>>: OUTPUT_PHONE=2017-12-21 18:15:00
基本上,结果是预期的。
但是,如果我将 phone 时区更改为纽约 (GMT-5) 时区而不重新启动应用程序,我会得到以下输出
D/DEBUG>>>>: INPUT=2017-12-21 16:15:00
D/DEBUG>>>>: TZ_EVENT=America/Los_Angeles
D/DEBUG>>>>: TZ_PHONE=America/New_York
D/DEBUG>>>>: DT=2017-12-21T18:15:00.000
D/DEBUG>>>>: OUTPUT_EVENT=2017-12-21 15:15:00
D/DEBUG>>>>: OUTPUT_PHONE=2017-12-21 18:15:00
注意 TimeZone.getDefault().getID()
返回的时区是正确的,但是在解析时,SimpleDateFormat 将其转换为好像 phone 时区仍然是芝加哥,从而返回错误的时间!
但是,如果我终止应用程序并重新启动它,相同的代码可以正常工作:
D/DEBUG>>>>: INPUT=2017-12-21 16:15:00
D/DEBUG>>>>: TZ_EVENT=America/Los_Angeles
D/DEBUG>>>>: TZ_PHONE=America/New_York
D/DEBUG>>>>: DT=2017-12-21T19:15:00.000
D/DEBUG>>>>: OUTPUT_EVENT=2017-12-21 16:15:00
D/DEBUG>>>>: OUTPUT_PHONE=2017-12-21 19:15:00
根据我的理解,SimpleDateFormat.parse
解析日期并将其存储为自 1970 年以来的秒数。使用 setTimeZone
应该使用时区来适当地偏移时间。
但是,似乎 phone 时区变化没有被 SimpleDateFormat 反映出来,而 TimeZone.getDefault().getID()
清楚地反映了变化。
有什么办法可以解决这个问题吗?
找到解决方案!
我一开始就叫了DateTimeZone.setDefault(DateTimeZone.forID(TimeZone.getDefault().getID()))
我想 DateTimeZone.setDefault
在应用程序启动时被调用,但之后不会被 joda-time 本身重置,即使用户的时区可能已经改变。