130

我正在尝试在我的数据库中设置与服务器无关的日期时间,我相信这样做的最佳做法是设置 UTC DateTime。我的数据库服务器是 Cassandra,Java 的数据库驱动程序只理解 Date 类型。

因此,假设在我的代码中,我现在使用新的 Java 8 ZonedDateTime 来获取 UTC(ZonedDateTime.now(ZoneOffset.UTC)),我该如何将此 ZonedDateTime 实例转换为“旧版” Date 类?

4

9 回答 9

213

您可以将 ZonedDateTime 转换为可以直接与 Date 一起使用的瞬间。

Date.from(java.time.ZonedDateTime.now().toInstant());
于 2015-08-28T15:33:55.063 回答
89
于 2015-08-28T23:07:12.773 回答
5

如果您正在使用适用于 Android 的ThreeTen backport并且不能使用较新的版本Date.from(Instant instant)(至少需要 API 26),您可以使用:

ZonedDateTime zdt = ZonedDateTime.now();
Date date = new Date(zdt.toInstant().toEpochMilli());

或者:

Date date = DateTimeUtils.toDate(zdt.toInstant());

另请阅读Basil Bourque 回答中的建议

于 2017-10-28T07:58:45.153 回答
4

这是一个将当前系统时间转换为 UTC 的示例。它涉及将 ZonedDateTime 格式化为字符串,然后使用 java.text DateFormat 将字符串对象解析为日期对象。

    ZonedDateTime zdt = ZonedDateTime.now(ZoneOffset.UTC);
    final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");
    final DateFormat FORMATTER_YYYYMMDD_HH_MM_SS = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
    String dateStr = zdt.format(DATETIME_FORMATTER);

    Date utcDate = null;
    try {
        utcDate = FORMATTER_YYYYMMDD_HH_MM_SS.parse(dateStr);
    }catch (ParseException ex){
        ex.printStackTrace();
    }
于 2015-11-23T08:58:09.833 回答
3

接受的答案对我不起作用。返回的日期始终是本地日期,而不是原始时区的日期。我住在UTC+2。

//This did not work for me
Date.from(java.time.ZonedDateTime.now().toInstant()); 

我想出了两种从 ZonedDateTime 获取正确日期的替代方法。

假设您有夏威夷的 ZonedDateTime

LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ldt.atZone(ZoneId.of("US/Hawaii"); // UTC-10

或最初要求的UTC

Instant zulu = Instant.now(); // GMT, UTC+0
ZonedDateTime zdt = zulu.atZone(ZoneId.of("UTC"));

备选方案 1

我们可以使用 java.sql.Timestamp。这很简单,但它可能也会影响您的编程完整性

Date date1 = Timestamp.valueOf(zdt.toLocalDateTime());

备选方案 2

我们从毫秒创建日期(之前已在此处回答)。请注意,本地 ZoneOffset 是必须的。

ZoneOffset localOffset = ZoneOffset.systemDefault().getRules().getOffset(LocalDateTime.now());
long zonedMillis = 1000L * zdt.toLocalDateTime().toEpochSecond(localOffset) + zdt.toLocalDateTime().getNano() / 1000000L;
Date date2 = new Date(zonedMillis);
于 2019-09-25T12:11:23.740 回答
2

对于像 beehuang 评论的 docker 应用程序,您应该设置您的时区。

或者,您可以使用withZoneSameLocal。例如:

2014-07-01T00:00+02:00 [GMT+02:00] 转换为

Date.from(zonedDateTime.withZoneSameLocal(ZoneId.systemDefault()).toInstant())

2014 年 7 月 1 日星期二 00:00:00 CEST及至

Date.from(zonedDateTime.toInstant())

2014 年 6 月 30 日星期一 22:00:00 UTC

于 2018-07-11T13:17:46.270 回答
1

我用这个。

public class TimeTools {

    public static Date getTaipeiNowDate() {
        Instant now = Instant.now();
        ZoneId zoneId = ZoneId.of("Asia/Taipei");
        ZonedDateTime dateAndTimeInTai = ZonedDateTime.ofInstant(now, zoneId);
        try {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateAndTimeInTai.toString().substring(0, 19).replace("T", " "));
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

因为 Date.from(java.time.ZonedDateTime.ofInstant(now, zoneId).toInstant()); 没用!!!如果你在你的电脑上运行你的应用程序,那没问题。但是如果你在 AWS 或 Docker 或 GCP 的任何区域运行,就会产生问题。因为计算机不是您在云上的时区。您应该在代码中设置正确的时区。例如,亚洲/台北。然后它将在 AWS 或 Docker 或 GCP 中更正。

public class App {
    public static void main(String[] args) {
        Instant now = Instant.now();
        ZoneId zoneId = ZoneId.of("Australia/Sydney");
        ZonedDateTime dateAndTimeInLA = ZonedDateTime.ofInstant(now, zoneId);
        try {
            Date ans = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateAndTimeInLA.toString().substring(0, 19).replace("T", " "));
            System.out.println("ans="+ans);
        } catch (ParseException e) {
        }
        Date wrongAns = Date.from(java.time.ZonedDateTime.ofInstant(now, zoneId).toInstant());
        System.out.println("wrongAns="+wrongAns);
    }
}
于 2018-06-16T05:03:04.677 回答
1

您可以使用Java 8 及更高版本中内置的java.time类来执行此操作。

ZonedDateTime temporal = ...
long epochSecond = temporal.getLong(INSTANT_SECONDS);
int nanoOfSecond = temporal.get(NANO_OF_SECOND);
Date date = new Date(epochSecond * 1000 + nanoOfSecond / 1000000);
于 2015-08-28T15:29:03.457 回答
-1

如果您只对现在感兴趣,那么只需使用:

Date d = new Date();
于 2015-08-28T15:33:47.380 回答