[英]How to retrieve the date from the database in a proper way using Java?
我正在尝试从我的数据库中检索日期时间值,并且我已将 upload_date_time 声明为 Instant,这就是该值在数据库中的存储方式。
但是,当我尝试从数据库中检索值时,它给了我“2022-03-01T14:00:00Z”。
上传订单表
@NotNull
@Column(name = "upload_date_time", nullable = false)
private Instant uploadDateTime;
public Instant getUploadDateTime() {
return uploadDateTime;
}
public UploadOrder uploadDateTime(Instant uploadDateTime) {
this.uploadDateTime= uploadDateTime;
return this;
}
public void setUploadDateTime(Instant uploadDateTime) {
this.uploadDateTime= uploadDateTime;
}
服务
public PrePickOrderOverPickEmailDTO generateOverPickEmails() {
log.debug("Request to retrieve Upload data : {}");
List<UploadOrder> uploadOrders = uploadPickRepository.findAllByEmailSent(false);
String data = "";
for (UploadOrder order : uploadOrders) {
data = data +
"Upload Date: " + order.getUploadDateTime() +"\n" +
// do others
}
}
很想知道我在这里做错了什么。 任何帮助都会很棒。 谢谢
由于您评论说您的数据库时区是 UTC+10:00,那么您所看到的是正确的。
2022-03-02T00:00+10:00
与2022-03-01T14:00:00Z
是同一日期,Z 是 UTC(+0),所以它们都代表相同的日期值,只是用不同的时区表示。
您可以通过以下方式验证这一点:
jshell> java.time.OffsetDateTime.parse("2022-03-02T00:00+10:00").toInstant()
$4 ==> 2022-03-01T14:00:00Z
要将 UTC 即时本地化到不同的区域,您可以使用Instant::atZone()
或Instant::atOffset()
。
Instant
是一个时刻,没有指定任何时区。 您实际存储的Instant
是 UTC 时间 3 月 1 日下午 2 点,与 AEST 时间 3 月 2 日午夜相同。
当您通过 SQL 客户端查看此值时,SQL 客户端会将其转换为您的本地时间,因此您看到的是 3 月 2 日午夜。
当您使用 Java 程序检索它时,您在显示它时没有指定时区或时间偏移量。 当您对Instant
执行此操作时,您会在 UTC 中看到它。
您真正想要做的是在显示之前将Instant
转换为LocalDateTime
- 这样,您就可以在 AEST 或您当地的时区中看到它。 LocalDateTime
class 有一个名为ofInstant
的static
方法,它将执行此操作。 您需要为您的时区传递ZoneId
,就像这样。
LocalDateTime timeInBrisbane = LocalDateTime.ofInstant(uploadDateTime, ZoneId.of("Australia/Brisbane"));
甚至像这样,获取系统默认时区。
LocalDateTime timeInDefaultZone = LocalDateTime.ofInstant(uploadDateTime, ZoneId.systemDefault());
您问题上的标签表明您正在使用Microsoft SQL Server作为您的数据库引擎。
根据文档,您应该将列定义为数据类型datetimeoffset
。 该类型类似于存储时刻的 SQL 标准类型TIMESTAMP WITH TIME ZONE
。
不要使用类型smalldatetime
、 datetime
或datetime2
。 这些缺少时区或与 UTC 的偏移量的上下文。 所以这些不能代表一个时刻,时间线上的一个特定点。
鉴于您的代码片段使用名称uploadDateTime
,您的业务逻辑需要跟踪片刻。 所以你的表列必须是datetimeoffset
类型。
你的第一句话说:
我正在尝试检索日期时间值
如果您的意思是 Microsoft SQL Server 中的datetime
时间类型,则您使用的列类型错误。 这会给你带来困惑和麻烦。
OffsetDateTime
虽然您忽略了使用@Column
注释提及您使用的框架库。 所以我不能肯定地说,但我可以猜测Instant
在这里使用是错误的 Java class 。
JDBC JDBC 4.2 及更高版本的规范要求JDBC 驱动程序支持java.time类。 该规范将 SQL 标准类型TIMESTAMP WITH TIME ZONE
的值映射到 Java class java.time.OffsetDateTime
。 Java class Instant
在 JDBC 中根本没有映射。
检索OffsetDateTime
后,您可以根据需要提取Instant
: Instant instant = myOffsetDateTime.toInstant();
.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.