我有一个json格式的响应日期到控制器,就像这样:
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "America/Chicago")
private Date date;
所以当我进行post call时,它看起来像:
"date": "2021-08-20 14:17:43"
所以响应字符串看起来像这样{"date":"2021-05-21 14:23:44"}
。在JUnit中,我手动创建一个响应对象并设置Date
对象,这样我就可以使用Gson将其转换为字符串,然后断言两者是相等的。我试图在我的SpringMVC JUnit测试用例中匹配这一点,试图这样做:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
String formattedDate = sdf.format(new Date());
LocalDate localDate = LocalDate.parse(formattedDate);
Date date = Date.from(localDate.atStartOfDay(ZoneId.of("America/Chicago")).toInstant());
但是由于yyyy-MM-dd
和HH:mm:ss
之间的空格,解析错误:
java.time.format.DateTimeParseException: Text '2021-08-20 14:23:44' could not be parsed, unparsed text found at index 10
我想我可能这样做效率低下,所以我想知道是否有一个更简单的方法来制作一个Date
对象,将匹配@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "America/Chicago")
的格式
我正在尝试匹配响应体,以便它通过mockito传递。
不要混合使用现代和旧的日期时间API
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDate = "2021-08-20 14:17:43";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(strDate, dtf);
System.out.println(ldt);
// Get the required Instant
ZonedDateTime zdtUtc = ldt.atZone(ZoneOffset.UTC);
ZonedDateTime zdtChicago = zdtUtc.withZoneSameInstant(ZoneId.of("America/Chicago"));
Instant instant = zdtChicago.toInstant();
System.out.println(instant);
}
}
输出:
2021-08-20T14:17:43
2021-08-20T14:17:43Z
<<p>在线演示/kbd>java.time
java.util
日期-时间API和它们的格式化API,SimpleDateFormat
是过时的和容易出错的。建议完全停止使用它们并切换到现代的Date-Time API*。然而,无论出于何种原因,如果您需要将Instant
的对象转换为java.util.Date
的对象,您可以这样做:
Date date = Date.from(instant);
从Trail: Date Time了解更多关于现代Date-Time API的信息.
*无论什么原因,如果你必须坚持Java 6或Java 7,你可以使用ThreeTen-Backport支持大部分java。time功能到Java 6 &7. 如果你正在为一个Android项目工作,而你的Android API级别仍然不符合Java-8,请检查Java 8+ API,通过desugaring和如何在Android项目中使用ThreeTenABP。
您可能缺少日期反序列化器
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
发布这篇文章只是为了满足你想要实现的目标。但是你应该关注@Arvind的答案:
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.TimeZone;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
String formattedDate = sdf.format(new Date());
// Updated the lines below
LocalDateTime localDateTime = LocalDateTime.parse(formattedDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
Date date = Date.from(localDateTime.atZone(ZoneId.of("America/Chicago")).toInstant());
最好是完全跳过Date
类,在您的响应中使用java中的Instant
或ZonedDateTime
。time,现代Java日期和时间API
如果无法避免使用过时的Date类
…我想知道是否有一种更简单的方法来制作
的格式Date
对象匹配@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "America/Chicago")
基本编辑:这在很大程度上取决于您对的定义是否匹配格式。Date
既不能有格式也不能有时区。JSON中的字符串具有上述格式。Date
没有,因为这是不可能的。时区America/Chicago在JSON和Date
中都不存在。它仅用于两者之间的转换。如果两个Date
对象表示同一时间点,则它们是相等的,没有别的了。当您询问如何格式化Date
以匹配@JsonFormat
时,这必然意味着将格式化为字符串。
要将像2021-08-20 14:23:44
这样的字符串转换为老式的Date
对象,我首先要静态地定义格式和时区:
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ROOT);
private static final ZoneId ZONE = ZoneId.of("America/Chicago");
然后做:
String responseDateString = "2021-08-20 14:23:44";
Instant inst = LocalDateTime.parse(responseDateString, FORMATTER)
.atZone(ZONE)
.toInstant();
Date oldfashionedDate = Date.from(inst);
System.out.println(oldfashionedDate);
我所在时区的输出是:
星期五Aug 20 21:23:44 CEST 2021
如果我在运行之前将时区设置为美国/芝加哥,则更容易看到结果是正确的:
8月20日星期五14:23:44 CDT 2021
你的代码出了什么问题?
首先,您是正确的,将Date
格式化为字符串只是为了解析它是过于复杂的事情。其次,您注意到异常来自这一行:
LocalDate localDate = LocalDate.parse(formattedDate);
LocalDate
是没有时间的日期。所以它的一个参数parse
方法只期望字符串中的2021-08-20
,仅此而已。它在抱怨空格,不是因为它是一个空格,而是因为在预期的字符之后有更多的字符。