格式EEEE, MMMM d, YYYY h:mm:ss a z的解析器异常



我在试图解析字符串值时得到解析器异常:

"Thursday, July 27, 2006 10:10:02 PM PST" 

格式:

"EEEE, MMMM d, YYYY h:mm:ss a z"

程序示例:

DateTime.parse("Thursday, July 27, 2006 10:10:02 PM PDT", DateTimeFormat.forPattern("EEEE, MMMM d, yyyy h:mm:ss a z"));

下面是错误信息:

Invalid format: "Thursday, July 27, 2006 10:10:02 PM PDT" is malformed at "PDT"

这是我的示例程序

String str = "Thursday, July 27, 2006 10:10:02 PM PDT"; 
DateTimeFormatter formatterDateTime = DateTimeFormat.forPattern("EEEE, MMMM d, YYYY h:mm:ss a z");
try{
    DateTime dt = DateTime.parse(str, formatterDateTime);
}catch(Exception ex)
{
    System.out.println(ex.getMessage());
}

From JodaTime docs:

时区名称:无法解析时区名称('z')。

但是SimpleDateFormat支持时区解析。

SimpleDateFormat format = new SimpleDateFormat("EEEE, MMMM dd, YYYY h:mm:ss aa zzz");
Date date = format.parse("Thursday, July 27, 2006 10:10:02 PM PST");

根据marba的建议,这个错误很可能是由于在Java 6中使用Java 7特定的模式引起的。

解析日期的代码如下所示:
SimpleDateFormat df = new SimpleDateFormat("EEEE, MMMM dd, yyyy h:mm:ss aa zzz");
Date d = df.parse("Thursday, July 27, 2006 10:10:02 PM PST");

测试解析后的日期是否与提供的日期相同:

df.setTimeZone(TimeZone.getTimeZone("Pacific/Pitcairn"));
System.out.println(df.format(d));

打印:

Thursday, July 27, 2006 10:10:02 PM PST

参考Javadoc获取更多模式

您使用的语言环境是什么?我认为您必须明确地提供Locale.US作为SimpleDateFormat的第二个参数。

对于Joda-Time库,您可以使用以下代码来调整区域设置:

DateTimeFormat.forPattern("EEEE, MMMM d, YYYY h:mm:ss a z").withLocale(Locale.US);

更新:刚刚发现这个相关的SO问题,看起来你需要使用SimpleDateFormat代替。Joda-Time解析器不支持时区:

SimpleDateFormat df = new SimpleDateFormat("EEEE, MMMM d, YYYY h:mm:ss a z");
Date d = df.parse("Thursday, July 27, 2006 10:10:02 PM PDT");

你的代码有两个问题:

  1. 您使用了Y(指定周年)而不是y(指定)。查看文档以了解有关符号的更多信息。点击这里了解更多信息。
  2. 您的日期-时间字符串是英文的,因此如果您在具有非英文Locale的JVM上运行它,您的代码将无法以预期的方式工作。日期-时间解析/格式化类型是Locale敏感的。点击这里了解更多信息。

java.time

遗留的日期时间API (java.util日期时间类型和它们的格式化API, SimpleDateFormat)已经过时并且容易出错。建议完全停止使用它,并切换到java.time,现代日期时间API*

使用现代API的方案:

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEEE, MMMM d, u h:m:s a z", Locale.ENGLISH);
        ZonedDateTime zdt = ZonedDateTime.parse("Thursday, July 27, 2006 10:10:02 PM PST", dtf);
        System.out.println(zdt);
    }
}
输出:

2006-07-27T22:10:02-07:00[America/Los_Angeles]

如果您需要将ZonedDateTime的对象转换为java.util.Date的对象,您可以这样做:

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

了解更多关于现代日期时间API*Trail: Date Time.

使用旧API的解决方案:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("EEEE, MMMM d, y h:m:s a z", Locale.ENGLISH);
        Date date = sdf.parse("Thursday, July 27, 2006 10:10:02 PM PST");
        //...
    }
}

*出于任何原因,如果你必须坚持Java 6或Java 7,你可以使用ThreeTen-Backport,它支持大部分 Java。time功能到Java 6 &7. 如果你正在为一个Android项目工作,你的Android API级别仍然不符合Java-8,检查Java 8+可用的API,通过desugaring和如何在Android项目中使用ThreeTenABP。

最新更新