我收到以下错误:
'java.text.ParseException:Unparseable date:“Aug 31 09:53:19 2011”'使用以下格式:new SimpleDateFormat("MMM dd HH:mm:ss yyyy");
有没有人看到这个问题?
答案 0 :(得分: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));
(例如,在使用Locale.FRENCH
时,会产生ParseException
。)
答案 1 :(得分:6)
格式本身对于您提供的输入是可以的。但是,如果您的默认语言环境设置为“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");
答案 2 :(得分:5)
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.
另外两个答案by aioobe和by Jesper都是正确的:隐式使用Locale
,其中的人类语言与输入文字的语言不匹配。
本答案解释了一种新的工作方式。此外,其他答案没有解决时区的关键问题。
几年后从这篇文章快进,我们现在将新的java.time package内置到Java 8及更高版本中。这些新类取代了旧的java.util.Date/.Calendar& SimpleDateFormat类。事实证明,那些旧班级很麻烦,令人困惑,也有缺陷。
定义要解析的数据及其格式。
String input = "Aug 31 09:53:19 2011";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MMM dd HH:mm:ss uuuu" );
如果未指定,则为DateTimeFormatter
分配当前在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)等异常的一组规则。使用proper time zone names,而不是3-4 letter abbreviations。
ZoneId zoneId_Montreal = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId_Montreal );
这个人类语言元素是回答问题的关键缺失部分。为符合输入字符串语言的人类语言指定正确的Locale
可以解决该问题。
但请注意,时区也很重要;其他答案忽略了此问题,从而隐式使用JVM的当前默认时区。这是不可取的,因为它取决于主机操作系统作为初始默认值(因此可能会有所不同),而且JVM中任何应用程序的任何线程中的任何代码都可以在期间更改JVM的当前默认时区 em>运行时。最好指定期望/预期的时区,而不是隐含地依赖默认值。
请注意语法。这些类设计为immutable。因此,不是修改(变异)对象,而是基于旧对象的值创建新的新对象。这意味着我们不影响上面定义的DateTimeFormatter
对象并保存在formatter
变量(对象引用)中。我们在这行代码中创建,使用和丢弃一个新的DateTimeFormatter对象(实际上是两个新对象)。
文档建议另一种解析字符串的方法是调用parse
方法,在那里从所需类型的类中传递method reference(Java 8中的新增内容)(如TemporalQuery
):ZonedDateTime::from
,LocalDateTime::from
,LocalDate::from
等。
ZonedDateTime zdt = formatter.withZone( zoneId_Montreal ).withLocale( Locale.ENGLISH ).parse( input, ZonedDateTime :: from );
为了演示,让我们转而创建一个ZonedDateTime
值的字符串表示形式,但在QuébécoisFrench中。
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及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?