java.text.ParseException:无法解析的日期

Sti*_*n.V 9 java android date parseexception

我收到以下错误:'java.text.ParseException:Unparseable date:"Aug 31 09:53:19 2011"'使用以下格式: new SimpleDateFormat("MMM dd HH:mm:ss yyyy");

有谁看到这个问题?

aio*_*obe 26

确保您使用的是正确的区域设置.(SimpleDateFormat(String)构造函数使用 系统默认语言环境,可能不是您要使用的语言环境.)

这在我的机器上工作正常:

String input = "Aug 31 09:53:19 2011";
DateFormat df = new SimpleDateFormat("MMM dd HH:mm:ss yyyy", Locale.US);
System.out.println(df.parseObject(input));
Run Code Online (Sandbox Code Playgroud)

(Locale.FRENCH例如,使用时,会产生一个ParseException.)


Jes*_*per 7

您输入的输入格式本身就可以.但是,如果您的默认语言环境设置为"Aug"不是月份名称的有效缩写,则可能会出现此错误.尝试使用例如Locale.US,您将看到它将工作:

DateFormat df = new SimpleDateFormat("MMM dd HH:mm:ss yyyy", Locale.US);
Date date = df.parse("Aug 31 09:53:19 2011");
Run Code Online (Sandbox Code Playgroud)


Bas*_*que 5

TL;博士

  • 指定Locale,以确定翻译月份名称时使用的人类语言和文化规范.
  • 使用现代java.time类而不是那些麻烦的遗留类.

举例:

LocalDateTime.parse(                                       // Parse input text as a `LocalDateTime` lacking any concept of time zone or offset-from-UTC.
    "Aug 31 09:53:19 2011" , 
    DateTimeFormatter.ofPattern( "MMM dd HH:mm:ss yyyy" )  // Specify formatting pattern to match input string.
                     .withLocale( Locale.US )              // The `Locale` determines the human language and cultural norms used in translating the input text.
)                                                          // Returns a `LocalDateTime` object.
Run Code Online (Sandbox Code Playgroud)

细节

aioobeJesper的另外两个答案都是正确的:隐含地使用Locale与您输入文本的语言不匹配的人类语言.

本回答解释了一种新的工作方式.此外,其他答案没有解决时区的关键问题.

java.time

几年后从这篇文章快进,我们现在已经在Java 8及更高版本中内置了新的java.time包.这些新类取代了旧的java.util.Date/.Calendar和SimpleDateFormat类.事实证明,那些旧班级很麻烦,令人困惑,也有缺陷.

格式化程序模式

定义要解析的数据及其格式.

String input = "Aug 31 09:53:19 2011";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MMM dd HH:mm:ss uuuu" );
Run Code Online (Sandbox Code Playgroud)

如果未指定,DateTimeFormatter则为LocaleJVM 分配当前默认值.即使在运行时(!),该默认值也可随时更改.因此,请始终指定所需/预期Locale.

formatter = formatter.withLocale( Locale.US );  // Or Locale.UK, Locale.CANADA_FRENCH, etc.
Run Code Online (Sandbox Code Playgroud)

鉴于输入缺少任何时区或从UTC信息偏移,请解析为LocalDateTime.

LocalDateTime ldt = LocalDateTime.parse( input , formatter );
Run Code Online (Sandbox Code Playgroud)

如果从上下文中您知道了该UTC日期时间值的预期偏移量或时区,请进行分配.

如果是UTC,请使用ZoneOffset.UTC常量来获取OffsetDateTime对象.

OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );
Run Code Online (Sandbox Code Playgroud)

时区是与UTC的偏移量加上一组用于处理诸如夏令时(DST)等异常的规则.使用正确的时区名称,从不使用3-4个字母的缩写.

ZoneId zoneId_Montreal = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId_Montreal );
Run Code Online (Sandbox Code Playgroud)

指定时区

这个人类语言元素是回答问题的关键缺失部分.指定与Locale输入字符串语言匹配的人类语言的正确解决了该问题.

但请注意,时区也很重要; 其他答案忽略了此问题,从而隐式使用JVM的当前默认时区.这是不可取的,因为它取决于主机操作系统作为初始默认值(因此可能会有所不同),而且JVM中任何应用程序的任何线程中的任何代码都可以运行时更改JVM的当前默认时区.最好指定期望/预期的时区,而不是默认依赖.

不可变对象

请注意语法.这些类设计为不可变的.因此,不是修改(变异)对象,而是基于旧对象的值创建新的新对象.这意味着我们不会影响DateTimeFormatter上面定义的对象并保存在formatter变量(对象引用)中.我们在这行代码中创建,使用和丢弃新的DateTimeFormatter对象(实际上是两个新对象).

方法参考

文档建议解析字符串的另一种方法是调用parse,你传递的方法方法引用从类你的愿望(因为那种结果的(在Java中8个新)TemporalQuery): ,ZonedDateTime::from,LocalDateTime::from,LocalDate::from等等.

ZonedDateTime zdt = formatter.withZone( zoneId_Montreal ).withLocale( Locale.ENGLISH ).parse( input, ZonedDateTime :: from );
Run Code Online (Sandbox Code Playgroud)

为了演示,让我们转而创建一个该ZonedDateTime值的String表示,但在QuébécoisFrench中.

String output = formatter.withLocale( Locale.CANADA_FRENCH ).format( zdt );
Run Code Online (Sandbox Code Playgroud)

更好的是,让我们本地化而不是硬编码特定的格式.

String outputLocalized = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ).format( zdt );
Run Code Online (Sandbox Code Playgroud)

转储到控制台.

System.out.println( "input: " + input );
System.out.println( "formatter: " + formatter );
System.out.println( "zdt: " + zdt );
System.out.println( "output: " + output );
System.out.println( "outputLocalized: " + outputLocalized );
Run Code Online (Sandbox Code Playgroud)

跑步时

input: Aug 31 09:53:19 2011
formatter: Text(MonthOfYear,SHORT)' 'Value(DayOfMonth,2)' 'Value(HourOfDay,2)':'Value(MinuteOfHour,2)':'Value(SecondOfMinute,2)' 'Value(YearOfEra,4,19,EXCEEDS_PAD)
zdt: 2011-08-31T09:53:19-04:00[America/Montreal]
output: août 31 09:53:19 2011
outputLocalized: mercredi 31 août 2011 9 h 53 EDT
Run Code Online (Sandbox Code Playgroud)

关于java.time

java.time框架是建立在Java 8和更高版本.这些类取代麻烦的老传统日期时间类,如java.util.Date,Calendar,和SimpleDateFormat.

现在处于维护模式Joda-Time项目建议迁移到java.time类.

要了解更多信息,请参阅Oracle教程.并搜索Stack Overflow以获取许多示例和解释.规范是JSR 310.

您可以直接与数据库交换java.time对象.使用符合JDBC 4.2或更高版本的JDBC驱动程序.不需要字符串,不需要课程.java.sql.*

从哪里获取java.time类?