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中的Date
和Calendar
类来达到同样的效果。现在,让我们深入了解一下在实践中如何使用它们。
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上找到。