我试图将输入日期字符串“2018-09-31”转换为日期。我希望它是“2018-09-30”或至少是“2018-09-30T00:00:00Z”。但出人意料的是,结果是不同的。有人可以解释为什么会这样吗?以及如何仅匹配输入日期?
import org.apache.commons.lang3.time.FastDateFormat;
private static final FastDateFormat dateOnlyFormat = FastDateFormat.getInstance("yyyy-MM-dd");
@Test
public void getSQLDateWithOnlyDate() {
java.util.Date date = null;
try {
String dateString = "2018-09-31";
date = dateOnlyFormat.parse(dateString);
System.out.println("input date : " + dateString);
System.out.println("date.toInstant() : " + date.toInstant());
System.out.println("date.toString() : " + date.toString());
} catch (ParseException e) {
e.printStackTrace();
}
}
input date : 2018-09-31
date.toInstant() : 2018-09-30T14:00:00Z
date.toString() : Mon Oct 01 00:00:00 AEST 2018
OH GOD SPIDERS 已经在评论中解释了其中的一些内容。九月有30天。您的格式化程序推断:9 月 31 日表示 9 月 30 日之后的第二天,即 10 月 1 日。
但是一天中的时间,14:00:00
? 这是一个时区问题。您的格式化程序在未被告知时使用您的 JVM 时区设置。例如,这可能是澳大利亚/悉尼,至少您Date
将其呈现为AEST
,我将其视为澳大利亚东部标准时间。因此,您的字符串被解析为 10 月 1 日的 00:00:00,与 UTC 的偏移量 +10:00。这与 UTC 时间 9 月 30 日 14:00:00 处于同一时间点。由于Instant.toString()
在 UTC 中呈现时间点(由Z
后缀表示),您将获得2018-09-30T14:00:00Z
.
当他们试图在你的程序上耍花招时,我建议你真的要反对。我知道你只想约会,而不是一天中的某个时间。
String dateString = "2018-09-31";
try {
LocalDate.parse(dateString);
} catch (DateTimeParseException dtpe) {
System.out.println(dtpe);
}
这打印:
java.time.format.DateTimeParseException:无法解析文本“2018-09-31”:无效日期“SEPTEMBER 31”
如果您确实想要观察到的外推行为:
DateTimeFormatter dateFormatter = DateTimeFormatter.ISO_LOCAL_DATE
.withResolverStyle(ResolverStyle.LENIENT);
System.out.println(LocalDate.parse(dateString, dateFormatter));
2018-10-01
你说你已经预料到了2018-09-30
,但我知道没有直接的方法可以给你。我的第一个建议是你再想一想,问问你是否真的需要这个。
在我的代码中,我使用的java.time
是现代 Java 日期和时间 API。我推荐它。ALocalDate
是没有时间的日期。在我看来,这两者都非常适合您的要求,并且从一开始就可以防止您的时区问题。
您的方法名称 ,getSQLDateWithOnlyDate
可能暗示您打算将日期与 SQL 数据库一起使用?LocalDate
(和其他java.time
类型)的一个优点是您可以将它直接传递给您PreparedStatement
的setObject
方法,前提是您至少使用 Java 8 和至少 JDBC 4.2。您的 JPA 实现也应该乐于接受一个LocalDate
对象。
链接: Oracle 教程:解释如何使用java.time
.
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句