【问题标题】:SimpleDateFormat setTimeZone not working if phone timezone has changed如果电话时区已更改,SimpleDateFormat setTimeZone 不起作用
【发布时间】:2018-06-05 12:41:17
【问题描述】:

我在使用 SimpleDateFormat 和时区时遇到了一个奇怪的问题。

基本上,我有这个代码sn-p:

    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) 和当前手机时区格式化日期

我将手机时区设置为芝加哥 (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

基本上,结果是预期的。

但是,如果我在不重新启动应用程序的情况下将手机时区更改为纽约 (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将其转换为手机时区仍然是芝加哥,从而返回错误的时间!

但是,如果我终止应用并重新启动它,相同的代码可以正常工作:

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 应该使用时区来适当地改变时间。

但是,SimpleDateFormat 似乎没有反映电话时区的变化,而 TimeZone.getDefault().getID() 清楚地反映了变化。

有没有办法解决这个问题?

【问题讨论】:

    标签: java android timezone jodatime


    【解决方案1】:

    找到了解决办法!

    一开始我打电话给DateTimeZone.setDefault(DateTimeZone.forID(TimeZone.getDefault().getID()))

    我猜DateTimeZone.setDefault 在应用程序启动时被调用,但之后不会被 joda-time 本身重置,即使用户的时区可能已经改变。

    【讨论】:

    • 您观察到的是预期的行为。 JVM 有自己的时区设置,可能与设备时区设置不同。如果您不做任何设置,它将在 JVM 启动时初始化为设备设置。之后它不会自动改变,但改变它的一种方法(也是一种好方法)是通过 Joda-Time(当已经使用这个库时)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多