我正在从Active Directory获取日期值(createWhen),并将其转换为Java日期,以获取在两个日期之间创建的帐户列表。一切都工作正常,除了一种方法:从AD日期到Java日期的方法。该方法如下所示:
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月份放置某种原因。
现在,我确定我的错误是一个非常简单的错误,但我已经重新检查了我的格式十次,而我正处于我再也看不到的地步。第二双眼睛是否可以查看我的代码,并指出我出错的地方让这个月变得非常不正确?
感谢。
答案 0 :(得分:50)
将模式字符串从“yyyy / MM / DD”更改为“yyyy / MM / dd”
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
答案 1 :(得分:5)
确保不使用'mm'代替'MM'或'MMM'。小m代表分钟,大写M代表月份。
答案 2 :(得分:1)
LocalDate parsedDate = OffsetDateTime
.parse("20050912190509.0Z", DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SX"))
.toLocalDate();
这会产生LocalDate
2005-09-12
。
我正在贡献现代答案。 Suhas Phartale’s answer是正确的,并且在7年前编写时是一个很好的答案。现在,臭名昭着的SimpleDateFormat
类已经过时了,我们在java.time
,现代Java日期和时间API方面做得更好。我强烈建议你使用它而不是旧的日期时间类。
从您的代码中可以看出,在解析之前,您需要从AD重新格式化字符串。没有必要,AD的字符串可以直接解析。我们可能已将其直接解析为LocalDate
,但我建议将其解析为OffsetDateTime
以从字符串中获取时间和偏移量;如您所见,之后可以直接将其转换为LocalDate
。 LocalDate
是一个没有时间的日期,因此它似乎比旧的Date
类更符合您的要求。
字符串采用UTC格式(最后用Z
表示)。上面给出了字符串中的日期,即UTC中的日期。如果你想要它在当地时区的日期,那就是9月12日19:05 UTC:
LocalDate parsedDate = OffsetDateTime.parse(givenString, adDateTimeFormatter)
.atZoneSameInstant(ZoneId.of("America/Coral_Harbour"))
.toLocalDate();
我假设我们已经将格式化程序声明为静态字段:
private static final DateTimeFormatter adDateTimeFormatter
= DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SX");
在这种情况下,结果是相同的,对于其他时区,它不会。请用您自己想要的时区代替America / Coral_Harbour。要使用JVM的时区设置,请指定ZoneId.systemDefault()
。但是,请注意,程序的其他部分或在同一JVM中运行的其他程序可能会更改该设置,因此这很脆弱。
Suhas Phartale的答案中的观点在java.time
也是有效的:格式模式字符串区分大小写,我需要在月中使用小写dd
。
详细了解the Oracle tutorial中的java.time
和/或在网上搜索其他资源。
答案 3 :(得分:0)
我之所以发布此答案,是因为我从here被重定向,并且上述解决方案无法解决我的问题
对于我来说,情况是,在解析此日期“ 2020-03-01T07:00:00 + 0530”后,我得到的结果为1/2 [dd / MM],这是我想要的格式,但是结果包含错误的月份,因为日期字符串清楚地表明月份为3 [MARCH]
。
因此,基本上cal.get(Calendar.DAY_OF_MONTH)返回2而不是实际3。
并且按照“ MONTH”部分中的docs
“公历和朱利安历法中的一年的第一个月是 一月是0;最后取决于一个月中的月数 年。”
所以我们只需要添加+1,我们就会得到实际的月份。猜猜这种现象是否有可能从month数组中返回month的名称? [一月,二月等。]
以下是我的实现示例(字符串中的日期格式为“ yyyy-MM-dd'T'HH:mm:ssZ”):
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(Constant.DATE_FORMAT_WITH_TIMEZONE,Locale.ENGLISH);
try {
cal.setTime(Objects.requireNonNull(sdf.parse(forecastList.get(listPosition).fcst_valid_local)));
} catch (ParseException e) {
e.printStackTrace();
}
String s = "%s/%d";
String output = String.format(s,cal.get(Calendar.DAY_OF_MONTH),(cal.get(Calendar.MONTH)+1)));
希望这对某些人有帮助。