2

最近,我尝试将我们的一个旧代码库从 移植Calendarjava.time,因为我们需要相当多的算术功能,而这些功能只能在java.time.

如果我们Calendar在当前的代码库中使用,我们需要在代码中间执行大量的来回转换(From Calendarto Instant, From Instantback to Calendar)。

为了避免这种繁琐的转换,我们决定取消使用Calendar,并将它们移植到等效的java.time代码中。

我对我的端口有点怀疑。与日历代码相比,它似乎

  • 在 while 循环中创建更多临时对象实例。
  • 需要更多的代码语句。

日历代码

// reminderCal is Calendar object.

long startTimestamp = getStartTimestamp();
reminderCal.setTimeInMillis(startTimestamp);

while (startTimestamp <= maxTimestamp) {
    resultList.add(startTimestamp);

    reminderCal.add(Calendar.DAY_OF_MONTH, 1);

    startTimestamp = reminderCal.getTimeInMillis();
}

return resultList;

java.time 代码

// Epoch timestamp loopTs as initial input.

long startTimestamp = getStartTimestamp();
final ZoneId zoneId = ZoneId.systemDefault();

while (startTimestamp <= maxTimestamp) {
    resultList.add(startTimestamp);

    // More code, more temporary instances required compared
    // with Calendar's version. Not sure we're doing the right
    // way.
    Instant instant = Instant.ofEpochMilli(startTimestamp);
    LocalDateTime time = LocalDateTime.ofInstant(instant, zoneId);
    time = time.plus(1, ChronoUnit.DAYS);

    startTimestamp = time.atZone(zoneId).toInstant().toEpochMilli();
}

return resultList;

对于上面的代码,我想知道,我们是否正确地进行了移植并进行了优化?我们java.time的港口有什么可以改进的地方吗?

4

1 回答 1

4

由于您希望在给定时区的时间之间进行日期操作,因此不应使用毫秒或 LocalDateTime,而应使用 ZonedDateTime。我认为你的 List 应该包含 Instants 而不是 longs,但现在让我们保持这种方式:

long startTimestamp = getStartTimestamp();
ZoneId zoneId = ZoneId.systemDefault();

ZonedDateTime maxDateTime = Instant.ofEpochMilli(maxTimestamp).atZone(zoneId);
ZonedDateTime loopDateTime = Instant.ofEpochMilli(loopTs).atZone(zoneId);

while (!loopDateTime.isAfter(maxDateTime)) {
    tsList.add(loopDateTime.toInstant().toEpochMilli());
    loopDateTime = loopDateTime.plusDays(1);
}

这更简洁,但也更具可读性。如果您使用 Instants 而不是 longs,则不需要所有的Instant.ofEpochMilli()and调用。toEpochMilli()

于 2018-10-25T06:14:47.553 回答