简体   繁体   English

将 ZonedDateTime 转换为 java.util.Date

[英]Convert ZonedDateTime to java.util.Date

How do i convert ZonedDateTime to java.util.Date without changing the timezone.如何在不更改时区的情况下将 ZonedDateTime 转换为 java.util.Date。

In my below method when i call Date.from(datetime.toInstant()) it convert it to local time zone in my case SGT.在我下面的方法中,当我调用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");
}

Output输出

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

You can add offset millis by yourself.您可以自己添加偏移毫秒。 See the example using java.util.Date :请参阅使用java.util.Date的示例:

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

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. java.util Date-Time API 及其格式化 API SimpleDateFormat已过时且容易出错。 It is recommended to stop using them completely and switch to the modern Date-Time API * .建议完全停止使用它们并切换到现代 Date-Time API * However, for any reason, if you want to change java.time.ZonedDateTime to java.util.Date , I recommend you avoid any kind of manual calculations when you already have an inbuilt API to meet the requirement.但是,无论出于何种原因,如果您想将java.time.ZonedDateTime更改为java.util.Date ,我建议您在已经拥有满足要求的内置 API 时避免任何类型的手动计算。

All you need to do is to add the offset to the input datetime which you can do by using ZonedDateTime#plusSeconds as shown below:您需要做的就是将偏移量添加到输入datetime ,您可以使用ZonedDateTime#plusSeconds ,如下所示:

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

Demo:演示:

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));
    }
}

Output:输出:

2021-10-03T05:11:57

ONLINE DEMO在线演示

Learn more about the modern Date-Time API * from Trail: Date Time .Trail: Date Time 中了解有关现代日期时间 API * 的更多信息。


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project . * 出于任何原因,如果您必须坚持使用 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

I would do as ETO states on his answer with the exception of using TimeUnit for getting the seconds converted into milliseconds:除了使用 TimeUnit 将秒转换为毫秒之外,我会按照 ETO 在他的回答中的说明进行操作:

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

or the other option would be:或者另一种选择是:

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));

Stick to ZonedDateTime坚持 ZonedDateTime

To preserve the time zone simply preserve your ZonedDateTime .要保留时区,只需保留您的ZonedDateTime It can be formatted directly to the output your require.它可以直接格式化为您需要的输出。 Don't involve the outdated and poorly designed Date class.不要涉及过时且设计不佳的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");
}

Try it out:试试看:

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

Output:输出:

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

Your conversion is not changing the time zone您的转化并未改变时区

A Date falsely pretends to have a time zone. Date错误地假装有一个时区。 It hasn't got any.它没有任何。 So there is no change of time zone going on.所以时区没有变化。 toInstant() discards the time zone because an Instant hasn't got a time zone either. toInstant()丢弃时区,因为Instant也没有时区。 Date.from() performs the conversion withut any regard to time zone. Date.from()执行转换而不考虑时区。 System.out.println() implicitly calls Date.toString() . System.out.println()隐式调用Date.toString() The toString() method uses the JVM's default time zone for rendering the string. toString()方法使用JVM 的默认时区来呈现字符串。 It's pretty confusing alright.这很混乱好吧。

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

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