1. 概述

在计算机科学中,Unix时间戳(也称为纪元时间)是一种标准的时间表示方式。它表示自1970年1月1日以来经过的秒数。

在这个教程中,我们将介绍如何将传统的日期转换为Unix时间戳。首先,我们将使用内置的JDK方法来探讨这个问题。然后,我们将展示如何使用外部库,如Joda-Time,来实现相同的目标。

2. 使用Java 8+日期时间API

Java 8引入了一个新的日期时间API,我们可以利用它来回答我们的核心问题。这个新API提供了一系列方法和类来操作日期。现在,让我们深入了解每个选项。

2.1. 使用Instant

简而言之,Instant类模型了一个时间线上的瞬间点。这个类提供了一个直接且简洁的方法,可以从给定日期获取Unix时间

让我们看一下它的用法:

@Test
void givenDate_whenUsingInstantClass_thenConvertToUnixTimeStamp() {
    Instant givenDate = Instant.parse("2020-09-08T12:16:40Z");

    assertEquals(1599567400L, givenDate.getEpochSecond());
}

如我们所见,Instant类提供了getEpochSecond()方法,从指定日期获取秒级的纪元时间戳。

2.2. 使用LocalDateTime

LocalDateTime是将日期转换为纪元时间的另一种选择。这个类表示日期和时间的组合,通常视为年、月、日、小时、分钟和秒。

通常情况下,这个类提供了toEpochSecond()方法,从指定日期时间获取秒级的纪元时间

@Test
void givenDate_whenUsingLocalDateTimeClass_thenConvertToUnixTimeStamp() {
    LocalDateTime givenDate = LocalDateTime.of(2023, 10, 19, 22, 45);

    assertEquals(1697755500L, givenDate.toEpochSecond(ZoneOffset.UTC));
}

如上所述,与其它方法不同,toEpochSecond()接受一个ZoneOffset对象,允许我们定义时区的固定偏移量,通常是UTC。

3. 使用旧版日期API

另一种选择是使用旧API中的DateCalendar类来达到同样的效果。现在,让我们深入了解一下在实践中如何使用它们。

3.1. 使用Date

在Java中,Date类代表具有毫秒精度的具体时间点。通过getTime()方法,它是将日期转换为Unix时间戳最简单的方式之一

@Test
void givenDate_whenUsingDateClass_thenConvertToUnixTimeStamp() throws ParseException {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date givenDate = dateFormat.parse("2023-10-15 22:00:00");

    assertEquals(1697407200L, givenDate.getTime() / 1000);
}

通常,这个方法返回传递日期的纪元时间戳的毫秒数。如我们所见,我们需要将结果除以1000来得到秒级的纪元时间。然而,这个类被认为是过时的,在处理日期时不应使用

3.2. 使用Calendar

同样,我们可以在java.util包中的Calendar类中使用它。这个类提供了许多设置和操作日期的方法。

通过Calendar,我们可以调用getTimeInMillis()来从指定日期获取Unix时间

@Test
void givenDate_whenUsingCalendarClass_thenConvertToUnixTimeStamp() throws ParseException {
    Calendar calendar = new GregorianCalendar(2023, Calendar.OCTOBER, 17);
    calendar.setTimeZone(TimeZone.getTimeZone("UTC"));

    assertEquals(1697500800L, calendar.getTimeInMillis() / 1000);
}

请注意,这个方法如其名称所示,返回的是毫秒级的时间戳。选择这个方法的缺点是Calendar实际上被视为事实上的遗留选项,因为它属于旧版API

4. 使用Joda-Time

另一个解决方案是使用Joda-Time库。在开始使用库之前,让我们将其依赖项添加到pom.xml

<dependency>
    <groupId>joda-time</groupId> 
    <artifactId>joda-time</artifactId> 
    <version>2.12.6</version> 
</dependency>

Joda-Time提供了其版本的Instant类,我们可以用来解决我们的挑战。让我们通过一个新的测试案例来说明如何使用这个类:

@Test
void givenDate_whenUsingJodaTimeInstantClass_thenConvertToUnixTimeStamp() {
    org.joda.time.Instant givenDate = org.joda.time.Instant.parse("2020-09-08T12:16:40Z");

    assertEquals(1599567400L, givenDate.getMillis() / 1000);
}

如图所示,Instant类提供了直接获取自纪元以来经过毫秒数的方式。

当使用Joda-Time时,DateTime类也是另一个要考虑的解决方案。它提供了getMillis()方法,用于从DateTime的瞬时值返回自纪元以来经过的毫秒数:

@Test
void givenDate_whenUsingJodaTimeDateTimeClass_thenConvertToUnixTimeStamp() {
    DateTime givenDate = new DateTime("2020-09-08T12:16:40Z");

    assertEquals(1599567400L, givenDate.getMillis() / 1000);
}

不出所料,测试案例成功通过。

5. 总结

在这篇短文中,我们探讨了将给定日期转换为Unix时间戳的不同方法。

首先,我们解释了如何使用核心的JDK方法和类。然后,我们展示了如何使用Joda-Time来实现相同的目标。

如往常一样,本文中使用的代码可以在GitHub上找到。


原始标题:Convert Date to Unix Timestamp in Java | Baeldung