1. 概述

在这个教程中,我们将探讨在Java中获取当前时间戳值并用作文件名的不同方法。我们将利用Java日期时间API(包括Java 8的类)和第三方库,如Joda-Time来实现目标。

2. 初始设置

在后续章节中,我们将构建一系列测试用例,展示每种获取当前时间戳并将其用于文件名的方法。首先,我们需要指定时间戳格式,并使用它定义格式化类:

static final String TIMESTAMP_FORMAT = "yyyyMMddHHmmss";
static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT);
static final SimpleDateFormat SIMPLEDATE_FORMAT = new SimpleDateFormat(TIMESTAMP_FORMAT);

接下来,我们将编写一个方法,将当前时间转换为有效的文件名。这个方法的示例输出可能是“20231209122307.txt”:

String getFileName(String currentTime) {
    return MessageFormat.format("{0}.txt", currentTime);
}

由于我们在编写测试用例,还需要创建另一个方法来检查输出文件名是否包含具有正确格式的时间戳:

boolean verifyFileName(String fileName) {
    return Pattern
      .compile("[0-9]{14}+\\.txt", Pattern.CASE_INSENSITIVE)
      .matcher(fileName)
      .matches();
}

在这种情况下,我们的文件名由表示时间戳的数字组成。建议确保文件名格式避免使用操作系统特定的禁止字符。

3. 使用Java日期时间API获取当前时间

Java提供了一些过时的类,如CalendarDate来处理日期和时间信息。然而,由于设计问题,Java 8引入了新的日期时间API类。DateCalendarSimpleDateFormatter类是可变的且不线程安全。

我们将首先通过使用Calendar.getInstance()方法获取默认时区和语言环境的Calendar实例,然后通过getTime()方法获取时间值:

@Test
public void whenUsingCalender_thenGetCurrentTime() {
    String currentTime = SIMPLEDATE_FORMAT.format(Calendar.getInstance().getTime());
    String fileName = getFileName(currentTime);
  
    assertTrue(verifyFileName(fileName));
}

接着,我们使用SimpleDateFormatter类将时间值转换为适当的字符串格式。

3.1. 使用Calendar

最基础的方法是使用Calendar.getInstance(),它返回一个Calendar实例,该实例使用默认时区和本地化。然后,我们可以使用getTime()方法获取以毫秒为单位的时间值:

3.2. 使用Date

类似地,我们可以创建一个Date对象,表示对象创建时间的毫秒数。然后,使用SimpleDateFormatter将毫秒时间值转换为所需的字符串模式:

对于新Java程序,推荐使用接下来章节中介绍的Java 8类。

3.3. 使用Instant

在Java中,Instant类代表UTC时间线上的单一时刻:

@Test
public void whenUsingInstant_thenGetCurrentTime() {
    String currentTime = Instant
      .now()
      .truncatedTo(ChronoUnit.SECONDS)
      .toString()
      .replaceAll("[:TZ-]", "");
    String fileName = getFileName(currentTime);

    assertTrue(verifyFileName(fileName));
}

Instant.now()方法询问系统时钟获取当前的瞬间。我们可以使用truncatedTo()方法将值四舍五入到最近的秒。然后,可以将秒值转换为字符串,替换时间戳中的任何不希望出现的时区信息。

3.4. 使用LocalDateTime

LocalDateTime表示ISO-8601日历系统中的日期和时间,但不包括时区:

@Test
public void whenUsingLocalDateTime_thenGetCurrentTime() {
    String currentTime = LocalDateTime.now().format(DATETIME_FORMATTER);
    String fileName = getFileName(currentTime);

    assertTrue(verifyFileName(fileName));
}

LocalDateTime.now()方法从默认系统时钟获取日期时间信息。随后,我们可以传递一个DateTimeFormatter来格式化时间戳为字符串。

3.5. 使用ZonedDateTime

ZonedDateTime是一个带有时区的不可变日期时间表示:

@Test
public void whenUsingZonedDateTime_thenGetCurrentTime() {
    String currentTime = ZonedDateTime
      .now(ZoneId.of("Europe/Paris"))
      .format(DATETIME_FORMATTER);
    String fileName = getFileName(currentTime);

    assertTrue(verifyFileName(fileName));
}

时区标识符能够唯一标识地球上的特定地理位置,例如“Europe/Paris"。使用这个标识,我们可以获取ZoneId,它决定了将Instant转换为LocalDateTime时使用的时区。

ZonedDateTime自动处理全年的时间夏令时调整。

3.6. 使用OffsetDateTime

OffsetDateTimeZonedDateTime的简化版本,忽略了时区。世界不同地区的时间偏移量各不相同。例如,“*+2:00*"表示比UTC早两小时的时间。我们可以使用偏移值与ZoneOffSet一起更改UTC时间的默认值:

@Test
public void whenUsingOffsetDateTime_thenGetCurrentTime() {
    String currentTime = OffsetDateTime
      .of(LocalDateTime.now(), ZoneOffset.of("+02:00"))
      .format(DATETIME_FORMATTER);
    String fileName = getFileName(currentTime);

    assertTrue(verifyFileName(fileName));
}

ZonedDateTimeOffsetDateTime都存储时间线上的瞬间,精确到纳秒。了解它们之间的差异有助于我们在两者之间做出选择。

4. 使用Joda-Time获取当前时间

Joda-Time是一个流行的日期和时间处理库,因其易于使用而受到开发者青睐,作为替代棘手的旧Java类的选择。它使用不可变类处理日期和时间值。

请在pom.xml中添加Joda-Time的Maven依赖:

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

4.1. 使用Joda的DateTime

DateTime.now()方法获取一个使用默认时区的DateTime实例,该实例设置为当前系统的毫秒级时间。然后,我们可以将其转换为具有定义的字符串格式的String

4.2. 使用Joda的Instant

Joda-Time库还提供了Instant类来捕获当前时间线上的时刻。我们可以使用DateTimeFormat将时间戳转换为所需的字符串模式:

5. 总结

在这篇文章中,我们探索了在Java程序中获取当前时间戳的各种方法,并演示了如何将其用于生成文件名。我们通过使用Java日期时间API和Joda-Time库的不同类实现了这一点。

完整的代码可以在GitHub上找到。