如何获取日期的 UTC 日期?

How to get UTC date of a date?

下面是我的应用程序中的 Java POJO:

public class Appointment {

    private Date appointmentStartDatetime;

    private String timezone;

    //...
}

这 2 个属性的示例值是:

2021-10-06 05:30:00
"America/New_York"

appointmentStartDatetime 表示约会在其声明的时区中的开始时间 - 即约会在纽约的 5.30 开始。

我想将其转换为 UTC 日期。

为了这样做,以下是否正确?

 public static Date dateToUTC(Date date, String timezoneId){

        Calendar calendar = Calendar.getInstance();
        TimeZone timeZone = TimeZone.getTimeZone(timezoneId);
        calendar.setTimeZone(timeZone);

        return new Date(date.getTime() - calendar.getTimeZone().getOffset(date.getTime()));
    }

方法调用如下:

Date utcDate = dateToUTC(appointment.getEventStartDatetime(),appointment.getTimezone())

java.time

为避免混淆,请使用 java.time 中的 ZonedDateTime,现代 Java 日期和时间 API,作为带时区的日期和时间。

public class Appointment {

    private ZonedDateTime appointmentStartDateTime;
    
    // Constructor, etc.

    public Instant getUtcDateTime() {
        return appointmentStartDateTime.toInstant();
    }
    
}

试试看:

        Appointment myAppointment = new Appointment(
                ZonedDateTime.of(2021, 1, 10, 5, 30, 0, 0,
                        ZoneId.of("America/New_York")));
        
        System.out.println(myAppointment.getUtcDateTime());

输出为:

2021-01-10T10:30:00Z

A ZonedDateTime 是时区中的日期和时间。所以您只需要这一个字段,而不是您拥有的两个字段 appointmentStartDatetimetimezoneInstant 是一个独立于时区的时间点。它以 UTC 格式打印,由上面输出的尾部 Z 表示。从 ZonedDateTimeInstant 的转换是一个简单的方法调用问题。

Link

Oracle tutorial: Date Time 解释如何使用 java.time.

java.util.Date 对象不像 modern date-time types 那样是真正的日期时间对象;相反,它表示自称为“纪元”的标准基准时间以来的毫秒数,即 January 1, 1970, 00:00:00 GMT(或 UTC)。当您打印 java.util.Date 的对象时,其 toString 方法 returns JVM 时区中的日期时间,根据该毫秒值计算得出。如果您需要在不同时区打印日期时间,您需要将时区设置为 SimpleDateFormat 并从中获取格式化字符串。

请注意 java.util 的日期时间 API 及其格式 API、SimpleDateFormat 已过时且容易出错。建议完全停止使用它们并切换到 modern date-time API.

  • 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它向后移植了大部分 java.time Java 6 和 7 的功能。
  • 如果您正在为 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring and

使用现代日期时间 API:

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

class Appointment {
    private LocalDateTime appointmentStartDatetime;
    private String timezone;

    public Appointment(LocalDateTime appointmentStartDatetime, String timezone) {
        this.appointmentStartDatetime = appointmentStartDatetime;
        this.timezone = timezone;
    }

    public LocalDateTime getAppointmentInLocalDateTime() {
        return appointmentStartDatetime;
    }

    public Instant getAppointmentInUTC() {
        return appointmentStartDatetime.toInstant(ZoneOffset.UTC);
    }

    public ZonedDateTime getAppointmentInZonedDateTime() {
        return appointmentStartDatetime.atZone(ZoneId.of(timezone));
    }

    public ZonedDateTime getAppointmentInZdtAnotherTimeZone(String timezone) {
        return getAppointmentInZonedDateTime().withZoneSameInstant(ZoneId.of(timezone));
    }
    // ...
}

public class Main {
    public static void main(String[] args) {
        Appointment appointment = new Appointment(
                LocalDateTime.of(LocalDate.of(2020, Month.FEBRUARY, 15), LocalTime.of(10, 30)), "America/New_York");

        System.out.println(appointment.getAppointmentInLocalDateTime());
        System.out.println(appointment.getAppointmentInUTC());
        System.out.println(appointment.getAppointmentInZonedDateTime());
        System.out.println(appointment.getAppointmentInZdtAnotherTimeZone("Asia/Calcutta"));
    }
}

输出:

2020-02-15T10:30
2020-02-15T10:30:00Z
2020-02-15T10:30-05:00[America/New_York]
2020-02-15T21:00+05:30[Asia/Calcutta]
  1. 一个Instant表示时间线上的一个瞬间点。
  2. A ZonedDateTime holds state equivalent to three separate objects, a LocalDateTime, a ZoneId and the resolved ZoneOffset. The function, ZonedDateTime#withZoneSameInstant returns 具有不同时区的此日期时间的副本,保留瞬间。

下面给出的是 overview of the Java SE 8 date-time types:

Trail: Date Time.

了解有关现代日期时间 API 的更多信息