繁体   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