Java - 无法解析的日期

时间:2011-05-27 15:56:26

标签: java simpledateformat

我正在尝试解析一个日期,但我奇怪地得到一个例外。

这是代码:

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,我认为我的模式是正确的。所以我不明白......

有什么想法吗?

谢谢!

3 个答案:

答案 0 :(得分:37)

这可能是因为您计算机上的默认语言环境不是英语。

您应该使用:

new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss", Locale.ENGLISH);

代替。

答案 1 :(得分:3)

TL;博士

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类取代。

使用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中提取ZonedDateTimeInstant类代表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.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance 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的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 2 :(得分:1)

切勿在没有 SimpleDateFormat 的情况下使用 DateTimeFormatterLocale

由于给定的日期时间是英文的,您应该将 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 localeSimpleDateFormat 的情况也是如此。我试图通过以下演示来说明问题:

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