我正在尝试解析一个日期,但我奇怪地得到一个例外。
这是代码:
import java.util.Date;
String strDate = "Wed, 09 Feb 2011 12:34:27";
Date date;
SimpleDateFormat FORMATTER = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
try {
date = FORMATTER.parse(strDate.trim());
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
例外是:
java.text.ParseException:Unparseable 日期:“星期三,2011年2月9日12:34:27” java.text.DateFormat.parse(DateFormat.java:337) 在DateTest.main(DateTest.java:17)
我已阅读documentation,我认为我的模式是正确的。所以我不明白......
有什么想法吗?
谢谢!
答案 0 :(得分:37)
这可能是因为您计算机上的默认语言环境不是英语。
您应该使用:
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss", Locale.ENGLISH);
代替。
答案 1 :(得分:3)
java.util.Date.from (
LocalDateTime.parse(
"Wed, 09 Feb 2011 12:34:27" ,
DateTimeFormatter.ofPattern( "EEE, dd MMM uuuu HH:mm:ss" , Locale.US )
).atZone( ZoneId.of( "America/Montreal" ) )
.toInstant()
)
问题和其他答案都使用过时的麻烦的旧日期时间类,这些类现在是遗留的,由java.time类取代。
输入字符串缺少任何时区或UTC偏移的指示。所以我们解析为OffsetDateTime
。
指定Locale
以确定(a)用于翻译日期名称,月份名称等的人类语言,以及(b)决定缩写,大小写,标点符号,分隔符等问题的文化规范,等等。
String input = "Wed, 09 Feb 2011 12:34:27" ;
Locale l = Locale.US ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEE, dd MMM uuuu HH:mm:ss" , l ) ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
ldt.toString():2011-02-09T12:34:27
问题和其他答案都忽略了时区的关键问题。
输入字符串缺少时区或偏移量。我们在时间轴上解析为LocalDateTime
not ,只关注可能的时刻。就像说“圣诞节从2017年12月25日午夜开始”,直到你把它放在特定时区的背景下才有意义。新西兰奥克兰的圣诞节比法国巴黎早得多,而后来仍然在蒙特利尔魁北克。
如果您知道预期的时区,请指定ZoneId
以生成ZonedDateTime
。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ldt.atZone( z ); // Assigning a time zone to determine an actual moment on the timeline.
最好避免麻烦的旧遗留日期时间类。但是,如果必须与尚未更新为java.time类型的旧代码进行交互,则可以在遗留类和java.time之间进行转换。查看添加到旧类的新方法。
java.util.Date
是UTC时间轴上的一个时刻。因此,我们需要从Instant
中提取ZonedDateTime
。 Instant
类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。
Instant instant = zdt.toInstant() ;
java.util.Date d = java.util.Date.from( instant ) ; // Convert from java.time to legacy class.
走向另一个方向。
Instant instant = d.toInstant() ; // Convert from legacy class to java.time class.
ZonedDateTime zdt = instant.atZone( z ) ; // Adjust from UTC into a particular time zone.
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类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 2 :(得分:1)
SimpleDateFormat
的情况下使用 DateTimeFormatter
或 Locale
由于给定的日期时间是英文的,您应该将 Locale.ENGLISH
与您的日期时间解析器一起使用;否则解析将在使用非英语类型区域设置的系统(计算机、电话等)中失败。
另外,请注意 java.util
的日期时间 API 及其格式 API SimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到 modern date-time API。
演示:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
final String strDateTime = "Wed, 09 Feb 2011 12:34:27";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE, dd MMM uuuu HH:mm:ss", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
System.out.println(ldt);
}
}
输出:
2011-02-09T12:34:27
默认情况下,DateTimeFormatter#ofPattern
使用 JVM 在启动时根据宿主环境设置的 default FORMAT locale。 SimpleDateFormat
的情况也是如此。我试图通过以下演示来说明问题:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
final String strDateTime = "Wed, 09 Feb 2011 12:34:27";
DateTimeFormatter dtfWithDefaultLocale = null;
System.out.println("JVM's Locale: " + Locale.getDefault());
// Using DateTimeFormatter with the default Locale
dtfWithDefaultLocale = DateTimeFormatter.ofPattern("EEE, dd MMM uuuu HH:mm:ss");
System.out.println("DateTimeFormatter's Locale: " + dtfWithDefaultLocale.getLocale());
System.out
.println("Parsed with JVM's default locale: " + LocalDateTime.parse(strDateTime, dtfWithDefaultLocale));
// Setting the JVM's default locale to Locale.FRANCE
Locale.setDefault(Locale.FRANCE);
// Using DateTimeFormatter with Locale.ENGLISH explicitly (recommended)
DateTimeFormatter dtfWithEnglishLocale = DateTimeFormatter.ofPattern("EEE, dd MMM uuuu HH:mm:ss",
Locale.ENGLISH);
System.out.println("JVM's Locale: " + Locale.getDefault());
System.out.println("DateTimeFormatter's Locale: " + dtfWithEnglishLocale.getLocale());
LocalDateTime zdt = LocalDateTime.parse(strDateTime, dtfWithEnglishLocale);
System.out.println("Parsed with Locale.ENGLISH: " + zdt);
System.out.println("JVM's Locale: " + Locale.getDefault());
// Using DateTimeFormatter with the default Locale
dtfWithDefaultLocale = DateTimeFormatter.ofPattern("EEE, dd MMM uuuu HH:mm:ss");
System.out.println("DateTimeFormatter's Locale: " + dtfWithDefaultLocale.getLocale());
System.out
.println("Parsed with JVM's default locale: " + LocalDateTime.parse(strDateTime, dtfWithDefaultLocale));
}
}
输出:
JVM's Locale: en_GB
DateTimeFormatter's Locale: en_GB
Parsed with JVM's default locale: 2011-02-09T12:34:27
JVM's Locale: fr_FR
DateTimeFormatter's Locale: en
Parsed with Locale.ENGLISH: 2011-02-09T12:34:27
JVM's Locale: fr_FR
DateTimeFormatter's Locale: fr_FR
Exception in thread "main" java.time.format.DateTimeParseException: Text 'Wed, 09 Feb 2011 12:34:27' could not be parsed at index 0
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
at Main.main(Main.java:33)
以下使用 SimpleDateFormat
的演示只是为了完整起见:
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 {
final String strDateTime = "Wed, 09 Feb 2011 12:34:27";
SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss", Locale.ENGLISH);
Date date = sdf.parse(strDateTime);
System.out.println(date);
}
}
输出:
Wed Feb 09 12:34:27 GMT 2011