通过SimpleDateFormat解析时间字符串得到错误的日期。 (1小时偏移)[Android / Java]

时间:2015-02-27 04:00:13

标签: java android timezone locale simpledateformat

首先,我想说清楚它不是夏令时问题。

其次,在努力之后,它似乎与SimpleDateFormat中使用的语言环境有关。

第三,似乎只发生在PST / PDT时区。 UTC还可以。


这是测试代码。

使用US和ENGLISH语言环境来解析相同的日期。

    try {
        Date date = new Date();
        SimpleDateFormat US_format = new SimpleDateFormat("MMM d HH:mm:ss z", Locale.US);
        SimpleDateFormat EN_format = new SimpleDateFormat("MMM d HH:mm:ss z", Locale.ENGLISH);

        US_format.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); //Set PST Timezone
        String US_str =  US_format.format(date);
        Log.i("DEBUG", "US_str: " + US_str);
        Log.i("DEBUG", "US_str: " + US_format.format(US_format.parse(US_str)));

        EN_format.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); //Set PST Timezone
        String EN_str =  EN_format.format(date);
        Log.i("DEBUG", "EN_str: " + EN_str);
        Log.i("DEBUG", "EN_str: " + EN_format.format(EN_format.parse(EN_str)));
    } catch (ParseException e) {
        Log.i("DEBUG", "Parsing Error");
    }

结果是

  

02-26 19:42:42.863 I / DEBUG:US_str:Feb 26 19:42:42 PST

     

02-26 19:42:42.865 I / DEBUG:US_str:2月26日 18:42:42 PST

     

02-26 19:42:42.865 I / DEBUG:EN_str:Feb 26 19:42:42 PST

     

02-26 19:42:42.866 I / DEBUG:EN_str:Feb 26 19:42:42 PST

这是一个错误吗? 为什么Locate.US会有一小时的差异?

====================================

更新: 它似乎只发生在Android 5.0设备上。 其他环境似乎还可以。

在Android问题跟踪器上发布了一个错误。 (问题158265

2 个答案:

答案 0 :(得分:0)

我认为错误可能来自Logger。它与语言环境无关。

    Date date = new Date();
    SimpleDateFormat US_format = new SimpleDateFormat("MMM d HH:mm:ss z", Locale.US);
    SimpleDateFormat EN_format = new SimpleDateFormat("MMM d HH:mm:ss z", Locale.ENGLISH);

    String US_str =  US_format.format(date);
    System.out.println( "US_str: " + US_str);
    System.out.println( "US_str: " + US_format.format(US_format.parse(US_str)));

    String EN_str =  EN_format.format(date);
    System.out.println( "EN_str: " + EN_str);
    System.out.println( "EN_str: " + EN_format.format(EN_format.parse(EN_str)));

这是在我的电脑中获得的输出:

US_str:2月27日12:18:26 IST

US_str:2月27日12:18:26 IST

EN_str:2月27日12:18:26 IST

EN_str:2月27日12:18:26 IST

希望这有助于你。

答案 1 :(得分:0)

来自Android问题问题158265

Google工程师回复了以下答案。

  

Nexus 5似乎无法更新RTC时钟硬件。当用户(或OS)更改时钟时,它不会永久保存到设备硬件。下次设备重新启动时,它会从RTC硬件读取值并将其设置为系统时钟。就我而言,我试过的两台设备将RTC设置为1971年。

     

系统时钟(用户看到的内容)最初是从RTC设置的,但是是独立的。如果用户已将设备设置为从网络源同步系统时钟,则在设备完成引导时,将正确设置系统时钟。如果没有回写它的能力,RTC仍然是错误的。

     

不幸的是,用于解析PST等区域信息的信息在zygote进程的引导期间被缓存,而时钟仍然是错误的。在我的例子中,它正在查看1971年的时区名称,但之后使用偏移信息。这意味着我们错误地选择Dawson_Creek作为PST的代理,但今天Dawson_Creek 的偏移实际上是MST / MDT的偏移量。

     

查看某些区域设置而不是其他区域设置问题的原因是,zygote缓存在启动后最多包含3个条目:

     

1)Locale.ROOT 2)Locale.US 3)

     

使用ENGLISH(en)被识别为与US(en_US)不同的区域设置   所以它不使用引导期间缓存的数据,因此当前   (正确)使用系统时钟时间。

简而言之,此问题仅发生在具有 BAD RTC硬件的Android设备上。

zygote进程在启动序列开始时使用 BAD 时间生成时区缓存。所以使用默认的Locale.US解析时区是错误的。

使用与默认值不同的Locale进行解析的结果是正确的,因为它生成的时区数据的时间已经过校正/与网络时间同步。

要避免此问题,只需使用默认值以外的语言环境来解析时区。