[英]java.text.ParseException: Unparseable date
我收到以下错误:´java.text.ParseException:无法解析的日期:“ 2011年8月31日09:53:19”´,格式为: new SimpleDateFormat("MMM dd HH:mm:ss yyyy");
有人看到这个问题吗?
确保您使用的语言环境正确。 ( 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));
(例如,使用Locale.FRENCH
,将导致ParseException
。)
输入的格式本身可以。 但是,如果您的默认语言环境设置为“ 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");
Locale
,以确定翻译月份名称时使用的人类语言和文化规范。 人为的例子:
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.
其他两个答案通过aioobe并通过加斯帕都是正确的:隐式使用Locale
与人类的语言不匹配你的输入文本的语言。
这个答案解释了一种新的工作方式。 另外,其他答案也没有解决时区这一关键问题。
从这篇文章发布几年后,我们已经快进了,现在我们在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" );
如果未指定,则为DateTimeFormatter
分配Locale
,该Locale
当前是JVM中的默认Locale
。 即使在运行时(!)期间,该默认值也可以随时更改。 因此,请始终指定所需/期望的Locale
。
formatter = formatter.withLocale( Locale.US ); // Or Locale.UK, Locale.CANADA_FRENCH, etc.
假设输入缺少任何时区或UTC偏移信息,则将其解析为LocalDateTime
。
LocalDateTime ldt = LocalDateTime.parse( input , formatter );
如果从上下文中您知道该日期时间值的预期UTC偏移量或时区,请对其进行分配。
如果是UTC,则使用ZoneOffset.UTC
常量获取OffsetDateTime
对象。
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );
时区是从UTC偏移的时间, 再加上一组用于处理异常的规则,例如夏令时(DST)。 请使用正确的时区名称 ,不要使用3-4个字母的缩写 。
ZoneId zoneId_Montreal = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId_Montreal );
这种人类语言元素是回答该问题的关键要素。 为与输入字符串的语言匹配的人类语言指定正确的Locale
可以解决该问题。
但是请注意,时区也很关键。 其他答案忽略了此问题,从而隐式使用了JVM的当前默认时区。 这是不可取的,因为它取决于主机操作系统作为初始默认值(可能有所不同),此外,JVM内任何应用程序的任何线程中的任何代码都可以在运行时更改JVM的当前默认时区。 比隐式依赖默认值更好地指定期望/期望的时区。
注意语法。 这些类被设计为不可变的 。 因此,不是修改(变异)对象,而是根据旧对象的值创建一个新的新对象。 这意味着我们不会影响上面定义并保存在formatter
变量(对象引用)中的DateTimeFormatter
对象。 我们正在此代码行中创建,使用和丢弃新的DateTimeFormatter对象(实际上是两个新对象)。
该文档建议一种解析字符串的替代方法是调用parse
方法,在该方法中,您从所需的结果类型(如TemporalQuery
)类中传递方法引用 (Java 8中的新增功能): ZonedDateTime::from
, LocalDateTime::from
, LocalDate::from
等等。
ZonedDateTime zdt = formatter.withZone( zoneId_Montreal ).withLocale( Locale.ENGLISH ).parse( input, ZonedDateTime :: from );
为了演示,让我们来回过头来创建该ZonedDateTime
值的字符串表示形式,但使用魁北克法语。
String output = formatter.withLocale( Locale.CANADA_FRENCH ).format( zdt );
更好的是,让我们本地化而不是硬编码特定格式。
String outputLocalized = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ).format( zdt );
转储到控制台。
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 );
运行时。
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
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类?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.