无法解释的日期:“2011-12-08T02:01:02 + 01:00”

时间:2013-12-05 14:37:16

标签: java date

以下代码在尝试从字符串中解析时抛出异常(2011-12-08T02:01:02 + 01:00):

image.setLastUpdated(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz")
    .parse(imageElement.getAttribute("lastUpdate")))

我也尝试过以下格式:

image.setLastUpdated(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
    .parse(imageElement.getAttribute("lastUpdate")));

但我得到了同样的例外:

java.text.ParseException: Unparseable date: "2011-12-08T02:01:02+01:00"
at java.text.DateFormat.parse(DateFormat.java:357)
at com.discavo.ImportManagerGiata.parseImageXML(ImportManagerGiata.java:204)

3 个答案:

答案 0 :(得分:5)

根据SimpleDateFormat documentation,您需要X作为UTC偏移的说明符,因为它是ISO-8601格式。

new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX")

答案 1 :(得分:1)

java.time

java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用它们并切换到 modern Date-Time API*

另外,下面引用的是来自 home page of Joda-Time 的通知:

<块引用>

请注意,从 Java SE 8 开始,要求用户迁移到 java.time (JSR-310) - JDK 的核心部分,取代了该项目。

使用 java.time(现代日期时间 API)的解决方案:

现代日期时间 API 基于 ISO 8601,只要日期时间字符串符合 ISO 8601 标准,就不需要明确使用 DateTimeFormatter 对象。您的日期时间字符串符合 ISO 8601 格式。

演示:

import java.time.Instant;
import java.time.OffsetDateTime;

public class Main {
    public static void main(String[] args) {
        OffsetDateTime odt = OffsetDateTime.parse("2011-12-08T02:01:02+01:00");
        System.out.println(odt);

        // ########### In case you need Instant ###########
        Instant instant = odt.toInstant();
        System.out.println(instant);
        
        // Java-12 onwards, you can parse the ISO-8601 compliant Date-Time with timezone
        // information directly into Instant
        instant = Instant.parse("2011-12-08T02:01:02+01:00");
        System.out.println(instant);
    }
}

输出:

2011-12-08T02:01:02+01:00
2011-12-08T01:01:02Z
2011-12-08T01:01:02Z

ONLINE DEMO

Instant 表示 UTC 中时间线上的一个瞬时点。输出中的 Z 是零时区偏移的 timezone designator。它代表祖鲁语并指定 Etc/UTC 时区(时区偏移为 +00:00 小时)。

注意:无论出于何种原因,如果您需要将 Instant 的这个对象转换为 java.util.Date 的对象,您可以这样做:

Date date = Date.from(instant);

Trail: Date Time 了解有关现代 Date-Time API 的更多信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

答案 2 :(得分:0)

answer by Jon Skeet是正确的。但是,仅供参考......

Joda-Time

没问题

如果使用Joda-Time而不是与Java捆绑的java.util.Date/Calendar类混乱,则此问题所呈现的问题不存在。

Joda-Time 2.3有各种内置解析器,因此在这种情况下无需指定格式。使用ISODateTimeFormat类上的方法检索各种格式设计器,用于解析ISO 8601格式化字符串的变体。

该问题未能考虑时区。所以我展示了所有三种可能性:

  • 您希望时间转换为特定时区。在此示例中为 Denver
  • 您希望时间调整为 UTC ,无时间偏移。
    常用于存储或进一步的日期工作。
  • 您希望使用其偏移量来保留此日期时间。
    通常不是一个好主意,因为您既没有UTC的好处(没有偏移也没有必要担心Daylight)节省时间DST或其他问题),以及具有处理DST或其他问题的规则的命名时区的好处。

对于所需时区

// For desired time zone. Arbitrarily using 'Denver' as named time zone for this example.
DateTimeZone denverTimeZone = DateTimeZone.forID( "America/Denver" );
org.joda.time.DateTime dateTimeInDenver = org.joda.time.format.ISODateTimeFormat.dateTimeNoMillis().withZone(denverTimeZone).parseDateTime( "2011-12-08T02:01:02+01:00" );
System.out.println( "dateTimeInDenver: " + dateTimeInDenver );

跑步时......

dateTimeInDenver: 2011-12-07T18:01:02.000-07:00

对于UTC

// For UTC (no offset).
org.joda.time.DateTime dateTimeInUTC = org.joda.time.format.ISODateTimeFormat.dateTimeNoMillis().withZoneUTC().parseDateTime( "2011-12-08T02:01:02+01:00" );
System.out.println( dateTimeInUTC );

跑步时......

2011-12-08T01:01:02.000Z

对于Offset as Parsed

// For offset as parsed. 
// Least beneficial, as no rules for Daylight Saving Time (DST) or other anomalies can be applied.
org.joda.time.DateTime dateTimeWithOffsetParsed = org.joda.time.format.ISODateTimeFormat.dateTimeNoMillis().withOffsetParsed().parseDateTime( "2011-12-08T02:01:02+01:00" );
System.out.println( "dateTimeWithOffsetParsed: " + dateTimeWithOffsetParsed );

跑步时......

dateTimeWithOffsetParsed: 2011-12-08T02:01:02.000+01:00