将字符串解析为 java.util.Date
parsing String into java.util.Date
我试图将输入日期字符串“2018-09-31”转换为 date.I 期望它是“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 已经在评论中解释了其中的一些内容。 9月有30天。您的格式化程序推断:9 月 31 日是指 9 月 30 日之后的一天,即 10 月 1 日。
但是一天中的时间,14:00:00
?这是一个时区问题。如果没有另行通知,您的格式化程序会使用 JVM 的时区设置。例如,这可能是 Australia/Sydney,至少您的 Date
将其呈现为 AEST
,我认为这是澳大利亚东部标准时间。因此,您的字符串被解析为 10 月 1 日的 00:00:00,与 UTC 的偏移量 +10:00。这与世界标准时间 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: Text '2018-09-31' could not
be parsed: Invalid date '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。我推荐它。 LocalDate
是没有时间的日期。在我看来,这既符合您的要求,又从一开始就防止了您的时区问题。
您的方法名称 getSQLDateWithOnlyDate
可能暗示您打算将日期与 SQL 数据库一起使用? LocalDate
(以及其他 java.time
类型)的一个优点是您可以将其直接传递给 PreparedStatement
的 setObject
方法,前提是您至少使用 Java 8 且至少 JDBC 4.2。您的 JPA 实现也应该乐于接受 LocalDate
对象。
Link: Oracle tutorial: Date Time 解释如何使用 java.time
.
我试图将输入日期字符串“2018-09-31”转换为 date.I 期望它是“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 已经在评论中解释了其中的一些内容。 9月有30天。您的格式化程序推断:9 月 31 日是指 9 月 30 日之后的一天,即 10 月 1 日。
但是一天中的时间,14:00:00
?这是一个时区问题。如果没有另行通知,您的格式化程序会使用 JVM 的时区设置。例如,这可能是 Australia/Sydney,至少您的 Date
将其呈现为 AEST
,我认为这是澳大利亚东部标准时间。因此,您的字符串被解析为 10 月 1 日的 00:00:00,与 UTC 的偏移量 +10:00。这与世界标准时间 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: Text '2018-09-31' could not be parsed: Invalid date '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。我推荐它。 LocalDate
是没有时间的日期。在我看来,这既符合您的要求,又从一开始就防止了您的时区问题。
您的方法名称 getSQLDateWithOnlyDate
可能暗示您打算将日期与 SQL 数据库一起使用? LocalDate
(以及其他 java.time
类型)的一个优点是您可以将其直接传递给 PreparedStatement
的 setObject
方法,前提是您至少使用 Java 8 且至少 JDBC 4.2。您的 JPA 实现也应该乐于接受 LocalDate
对象。
Link: Oracle tutorial: Date Time 解释如何使用 java.time
.