将字符串解析为日期时间不会返回正确的时间

时间:2018-09-03 15:33:21

标签: java android datetime hour datetime-parsing

在Android系统中,由于以下代码超时,我预计下午3:12,但下午4:12。解析此日期时间格式的正确方法是什么?

String dt = "2018-09-02T19:12:00-0400";
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");

try {
    Date date = dateFormat.parse(dt);
    System.out.println(date);
} catch (ParseException e) {
    e.printStackTrace();
}

1 个答案:

答案 0 :(得分:0)

时区

最好明确指定要在哪个时区输出

    DateTimeFormatter inputFormatter 
            = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXX");
    DateTimeFormatter displayFormatter = DateTimeFormatter
            .ofLocalizedDateTime(FormatStyle.LONG)
            .withLocale(Locale.ENGLISH);
    ZoneId displayZone = ZoneId.of("Pacific/Pitcairn");

    String dt = "2018-09-02T19:12:00-0400";
    OffsetDateTime dateTime = OffsetDateTime.parse(dt, inputFormatter);
    String displayDateTime = dateTime.atZoneSameInstant(displayZone)
            .format(displayFormatter);
    System.out.println(displayDateTime);

此打印:

  

2018年9月2日,太平洋标准时间下午3:12:00

我在代码中使用了太平洋/皮特凯恩时区,但是您更了解自己想要的时区。

我还使用了现代Java日期和时间API java.time。您正在使用的日期时间类SimpleDateFormatDate被认为已经过时了,并且java.time更好用。

您的代码出了什么问题?

您解析日期字符串的方法是正确的,并产生正确的Date

打印Date时,将隐式调用toString。过时的Date类具有一种特殊且令人困惑的toString方法:它获取JVM的时区设置并将其用于生成字符串。因此,根据您的默认时区,您可以获得一天中的任何时间。因此,看来您的JVM的时区设置与您期望的不符。

由于您期望从19:12:00-0400的输入中获得3:12 PM,所以我认为您想要的时区与9月的UTC偏移-08:00。例如,如果您的默认时区为America / Los_Angeles,其标准时间为-08:00,则您会得到Sun Sep 02 16:12:00 PDT 2018,因为夏季时间(夏令时)在9月在加利福尼亚生效,因此偏移量是-07:00。

依赖JVM的默认时区始终很脆弱,因为该程序的其他部分或运行在同一JVM中的其他程序可能随时更改设置。

问题:我可以在Android上使用java.time吗?

是的,java.time在较新的Android设备上都能很好地工作。它只需要至少Java 6

  • 在Java 8和更高版本以及较新的Android设备上(我被告知,从API级别26开始),内置了现代API。
  • 在Java 6和7中,获得ThreeTen Backport,即新类的backport(JSR 310的ThreeTen;请参见底部的链接)。
  • 在(较旧的)Android上,使用Android版本的ThreeTen Backport。叫做ThreeTenABP。并确保您使用子包从org.threeten.bp导入日期和时间类。

链接