Java simpledateformat无法解析日期,即使格式看起来是正确的

时间:2015-06-05 15:45:13

标签: java date simpledateformat

我有一个愚蠢的问题,这是我的代码:

SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss zZ",Locale.US);
System.out.println(dateFormat.format(new Date()));
try {
    wou.setDateStart(dateFormat.parse(date));
    wou.setDateEnd(dateFormat.parse(date));
} catch (ParseException e) {
    System.out.println(e.getCause() + " " + e.getMessage());
    e.printStackTrace();
}

结果如下:

2015年6月5日星期五15:34:29 GMT + 0000

null无法解释日期:“2015年6月5日星期五17:30:00 GMT + 0000”

我的格式出了什么问题?它以与我想要解析的日期相同的格式输出当前日期,但一直告诉我日期是不可解析的......

我挣扎了一个多小时,我完全迷失了......

修改

我无法控制我需要解析的日期(如果我这样做,我会在源代码中将其更改为我可以使用的格式)

以下代码:

String date = request.getParameter("absencyDate");
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss z",Locale.US);
try {
    System.out.println(dateFormat.format(new Date()));
    System.out.println(date);
    System.out.println(dateFormat.parse(date));
} catch (ParseException e1) {

产生同样的错误:

2015年6月5日星期五16:09:15 GMT

2015年6月5日星期五12:30:00 GMT + 0000

java.text.ParseException:Unparseable date:“Fri Jun 05 2015 12:30:00 GMT + 0000”

2 个答案:

答案 0 :(得分:4)

问题是您在日期格式中使用zZ。它需要一个简单的基于名称的区域(z),然后是RFC-822区域(Z)。

如果默认区域(或格式中设置的区域)不是GMT,它运行良好,因为它只是解析到那一点(匹配z),然后它解析{{1 } {} +0000

但是当区域是GMT时,它实际上会尝试解析跟随它的部分(Z)作为+0000的一部分,因为" GMT + hh:mm"是z的有效区域,但失败了。

日期格式显示为欺骗性正确。但结合两种时区格式则不然。它应该是一个命名时区(包括" GMT + 00:00"),或RFC 822偏移(它不包括" GMT"指定)。

编辑OP编辑

因此,您从某处获得了z参数,并且他们使用非标准区域指定将其发送给您。 date既不匹配一般时区(应为GMT+0000GMT),也不符合RFC 822时区(GMT+00:00不应为+0000),也不符合ISO 8601时间区域(应为GMT+00+0000)。

如果您知道他们将在日期中始终使用+00:00,我认为您可以做的最好的事情是:

GMT

"EEE MMM dd yyyy HH:mm:ss 'GMT'Z" 部分作为文字字符串而不是时区指示符,然后从其后面的任何内容解释时区。

或者,如果生成该参数的源在您的控制之下,请修改其格式以使用与其中一个标准匹配的正确时区。

答案 1 :(得分:0)

java.time

旧的日期时间 API(java.util 日期时间类型及其格式 API,SimpleDateFormat)已经过时且容易出错。建议完全停止使用它们并切换到 java.timemodern date-time API*

使用现代日期时间 API 的演示:

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;

public class Main {
    public static void main(String args[]) {
        String dateStr = "Fri Jun 05 2015 17:30:00 GMT+0000";
        
        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                                .parseCaseInsensitive()
                                .appendPattern("EEE MMM d u H:m:s")
                                .appendLiteral(' ')
                                .appendZoneId()
                                .appendPattern("X")
                                .toFormatter(Locale.ENGLISH);
        
        ZonedDateTime zdt = ZonedDateTime.parse(dateStr, dtf);
        
        System.out.println(zdt);
    }
}

输出:

2015-06-05T17:30Z[GMT]

出于任何原因,如果您需要 java.util.Date 的这个对象中的 ZonedDateTime 对象,您可以如下:

Date date = Date.from(zdt.toInstant());

modern date-time API 中了解有关 Trail: Date Time* 的更多信息。


* 出于任何原因,如果您必须坚持使用 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