簡體   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