繁体   English   中英

如何使用 Java 以正确的方式从数据库中检索日期?

[英]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:002022-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 有一个名为ofInstantstatic方法,它将执行此操作。 您需要为您的时区传递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

不要使用类型smalldatetimedatetimedatetime2 这些缺少时区或与 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后,您可以根据需要提取InstantInstant instant = myOffsetDateTime.toInstant(); .

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM