簡體   English   中英

將 ZonedDateTime 轉換為 java.util.Date

[英]Convert ZonedDateTime to java.util.Date

如何在不更改時區的情況下將 ZonedDateTime 轉換為 java.util.Date。

在我下面的方法中,當我調用Date.from(datetime.toInstant()) ,它在我的案例 SGT 中將其轉換為本地時區。

public static void printDate(ZonedDateTime datetime) {
    System.out.println("---> " + datetime.format(DateTimeFormatter.ofPattern(API_TIME_STAMP_PATTERN)));
    System.out.println(Date.from(datetime.toInstant()));
    System.out.println("\n");
}

輸出

---> 2019-03-13_08:46:26.593
Wed Mar 13 16:46:26 SGT 2019

您可以自己添加偏移毫秒。 請參閱使用java.util.Date的示例:

long offsetMillis = ZoneOffset.from(dateTime).getTotalSeconds() * 1000;
long isoMillis = dateTime.toInstant().toEpochMilli();
Date date = new Date(isoMillis + offsetMillis);

java.util Date-Time API 及其格式化 API SimpleDateFormat已過時且容易出錯。 建議完全停止使用它們並切換到現代 Date-Time API * 但是,無論出於何種原因,如果您想將java.time.ZonedDateTime更改為java.util.Date ,我建議您在已經擁有滿足要求的內置 API 時避免任何類型的手動計算。

您需要做的就是將偏移量添加到輸入datetime ,您可以使用ZonedDateTime#plusSeconds ,如下所示:

datetime = datetime.plusSeconds(datetime.getOffset().getTotalSeconds());
Date date = Date.from(datetime.toInstant());

演示:

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) {
        // Test
        printDate(ZonedDateTime.now(ZoneId.of("Asia/Singapore")));
    }

    public static void printDate(ZonedDateTime datetime) {
        datetime = datetime.plusSeconds(datetime.getOffset().getTotalSeconds());
        Date date = Date.from(datetime.toInstant());

        // Showing date-time in Singapore timezone
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Singapore"));
        System.out.println(sdf.format(date));
    }
}

輸出:

2021-10-03T05:11:57

在線演示

Trail: Date Time 中了解有關現代日期時間 API * 的更多信息。


* 出於任何原因,如果您必須堅持使用 Java 6 或 Java 7,您可以使用ThreeTen-Backport,它將大部分java.time功能向后移植到 Java 6 和 7。如果您正在為 Android 項目和您的 Android API 工作級別仍然不符合 Java-8,請檢查 通過 desugaringHow to use ThreeTenABP in Android Project 可用的 Java 8+ APIs

除了使用 TimeUnit 將秒轉換為毫秒之外,我會按照 ETO 在他的回答中的說明進行操作:

long offsetMillis = TimeUnit.SECONDS.toMillis(ZoneOffset.from(dateTime).getTotalSeconds());
long isoMillis = dateTime.toInstant().toEpochMilli();
Date date = new Date(isoMillis + offsetMillis);

或者另一種選擇是:

var localDate = LocalDateTime.now();
final long offSetHours = ChronoUnit.HOURS.between(localDate.atZone(ZoneId.of("YOUR_TIME_ZONE_ID")),
  localDate.atZone(ZoneId.of("UTC")));
return Date.from(Instant.parse(dateAsStringISO8601).plus(offSetHours, ChronoUnit.HOURS));

堅持 ZonedDateTime

要保留時區,只需保留您的ZonedDateTime 它可以直接格式化為您需要的輸出。 不要涉及過時且設計不佳的Date類。

private static final String API_TIME_STAMP_PATTERN = "yyyy-MM-dd_HH:mm:ss.SSS";

private static final DateTimeFormatter FORMATTER
        = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz y", Locale.ROOT);

public static void printDate(ZonedDateTime datetime) {
    System.out.println("---> " + datetime.format(DateTimeFormatter.ofPattern(API_TIME_STAMP_PATTERN)));
    System.out.println(datetime.format(FORMATTER));
    System.out.println("\n");
}

試試看:

    ZonedDateTime zdt = ZonedDateTime.of(
            2019, 3, 13, 8, 46, 26, 593_000_000, ZoneId.of("Etc/UTC"));
    printDate(zdt);

輸出:

 ---> 2019-03-13_08:46:26.593 Wed Mar 13 08:46:26 UTC 2019

您的轉化並未改變時區

Date錯誤地假裝有一個時區。 它沒有任何。 所以時區沒有變化。 toInstant()丟棄時區,因為Instant也沒有時區。 Date.from()執行轉換而不考慮時區。 System.out.println()隱式調用Date.toString() toString()方法使用JVM 的默認時區來呈現字符串。 這很混亂好吧。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM