Java SimpleDateFormat总是返回1月份的月份

我正在努力从Active Directory获取日期值(createWhen),并将其转换为Java日期,以获取在两个日期之间创建的帐户列表。 一切正常,除了一种方法:从AD Date到Java date的方法。 该方法如下所示:

private Date getParsedDate(String givenString) { System.out.println("Value from AD is: " + givenString); Date parsedDate = null; String formattedString = this.formatDateString(givenString); System.out.println("Formatted String is: " + formattedString); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/DD"); try { parsedDate = sdf.parse(formattedString); System.out.println("Final date string is: " + parsedDate.toString()); } catch (ParseException ex) { ex.printStackTrace(); } return parsedDate; } 

并且,对于来自AD的单个任意数据:

Value from AD is: 20050912190509.0Z

Formatted String is: 2005/09/12

Final date string is: Wed Jan 12 00:00:00 EST 2005

显然,它正确地提取了日期和年份(如果我选择包括小时/分钟/秒,它也包括正确的那些),但是由于某种原因, 每个日期都放在1月份。

现在,我确定我的错误是一个非常简单的错误,但我已经重新检查了我的格式十次,而我正处于我再也看不到的地步。 希望第二双眼睛可以查看我的代码并指出我错误的地方让这个月变得非常不正确吗?

谢谢。

将模式字符串从“yyyy / MM / DD”更改为“yyyy / MM / dd”

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); 

确保不要使用’mm’而不是’MM’或’MMM’。 小m代表分钟,大写M代表月份。

TL; DR

  LocalDate parsedDate = OffsetDateTime .parse("20050912190509.0Z", DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SX")) .toLocalDate(); 

这产生了2005-09-12LocalDate

java.time

我正在贡献现代答案。 Suhas Phartale的答案是正确的,并且在7年前编写时是一个很好的答案。 现在,臭名昭着的麻烦的SimpleDateFormat类已经过时了,我们在java.time ,现代Java日期和时间API方面做得更好。 我热烈建议你使用它而不是旧的日期时间类。

细节

从您的代码中可以看出,在解析之前,您需要从AD重新格式化字符串。 没有必要,AD中的字符串可以直接解析。 我们可能已经将它直接解析为LocalDate ,但我建议将其解析为OffsetDateTime以从字符串中获取时间和偏移量; 如您所见,之后可以直接将其转换为LocalDateLocalDate是一个没有时间的日期,因此它似乎比旧的Date类更符合您的要求。

字符串是UTC(最后用Z表示)。 上面给出了字符串中的日期,即UTC中的日期。 如果您想要在UTC时间9月12日19:05的当地时区的日期:

  LocalDate parsedDate = OffsetDateTime.parse(givenString, adDateTimeFormatter) .atZoneSameInstant(ZoneId.of("America/Coral_Harbour")) .toLocalDate(); 

我假设我们已经将formatter声明为静态字段:

 private static final DateTimeFormatter adDateTimeFormatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SX"); 

在这种情况下,结果是相同的,对于其他时区,它不会。 请用您自己想要的时区代替America / Coral_Harbour。 要使用JVM的时区设置,请指定ZoneId.systemDefault() 。 但请注意,程序的其他部分或在同一JVM中运行的其他程序可能会更改该设置,因此这很脆弱。

Suhas Phartale的回答在java.time也是有效的:格式模式字符串区分大小写,我需要使用小写dd表示日期。

教程

在Oracle教程中了解有关java.time更多信息和/或在网上搜索其他资源。