【问题标题】:LocalTime() difference between two timesLocalTime() 两次之间的差异
【发布时间】:2019-04-14 17:17:10
【问题描述】:

我有一个航班行程计划,我需要了解出发和到达时间之间的差异。我从数据中得到这些指定的时间作为字符串。这是我的问题:

import static java.time.temporal.ChronoUnit.MINUTES;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class test2 {
public static void main(String[] args) {

    DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("HHmm");
    LocalTime departure = LocalTime.parse("1139", dateFormat);
    LocalTime arrival = LocalTime.parse("1435", dateFormat);
    LocalTime a = LocalTime.parse("0906", dateFormat);
    System.out.println(MINUTES.between(departure, arrival));
    System.out.println(MINUTES.between(arrival, a));
}
}

输出:

176
-329

第一次返回 11:39 和 14:35 之间的差异就好了。但是第二个差异只有5个小时,而应该是19个小时。我该如何解决这个问题,我在这里做错了什么?

任何帮助将不胜感激。

编辑:我正在使用图表来存储我的数据。两个机场之间最短路线的示例如下:

Route for Edinburgh to Sydney
1 Edinburgh, 1139, TK3245, Istanbul, 1435
2 Istanbul, 0906, TK4557, Singapore, 1937
3 Singapore, 0804, QF1721, Sydney, 1521

这些是我们从 EDI 到 SYD 的 3 个航班。上面输出的格式是(城市、出发时间、航班号、目的地、到达时间)。

【问题讨论】:

  • 您知道,时间的问题只是从凌晨到午夜的这段时间,它不知道在这些界限之外存在什么。相反,您应该使用LocalDateTime,它允许从一天过渡到另一天
  • 虽然您的示例可能很简单,但我建议您查看ZonedDateTime,因为您可能在不同时区之间传递,使得计算相当……奇怪:P(并非闻所未闻在你离开之前到达????)
  • 我没有看到这个问题。你得到的结果是正确的。为什么 09:05 到 14:35 之间的差应该是 19 小时?
  • @dorony 抱歉,我犯了一个错误,忘记在发布之前更改我的代码。差异应该是从 14:35 到 09:05。在这种情况下,正如 MadProgrammer 所提到的,日期正在更改,因此值会丢失或其他情况。我尝试了 MadProgrammer 建议的建议,但 LocalDateTime 仅在我提供日期时才有效(至少就我现在测试的情况而言)。我得到的数据没有给我提供日期,它只是两次。日期无关紧要。
  • 如果你得到的结果小于零,那么将它与 24*60 相加,你会得到正确的结果。

标签: java localtime time-format


【解决方案1】:

手头的主要问题是LocalTime 仅表示午夜 AM 到午夜 PM 之间的时间,它没有超出这些界限的任何范围的概念。

您真正需要的是与时间值相关联的日期值,这将允许您计算超过 24 小时的持续时间。

否则,您将需要自己“捏造”这些值。这意味着,当下一次小于上一次时,您将需要手动添加一个额外的时间段,可能是一天。

可能有几种方法可以做到这一点,这只是一种。

它需要一个ZonedDateTime(设置为当前日期)并将其用作“锚”日期。然后将计划的每个Time 应用于此。当它检测到最后到达时间早于下一次出发时间时,它会在值中增加一天。

import java.time.Duration;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

public class Test {

  public static void main(String[] args) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HHmm");

    List<Schedule> route = new ArrayList<>(4);
    route.add(new Schedule(LocalTime.parse("1139", formatter), LocalTime.parse("1435", formatter)));
    route.add(new Schedule(LocalTime.parse("0906", formatter), LocalTime.parse("1937", formatter)));
    route.add(new Schedule(LocalTime.parse("0804", formatter), LocalTime.parse("1521", formatter)));

    // Anchor time...
    ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("UTC"));
    ZonedDateTime lastArrival = null;
    Duration totalDuration = Duration.ZERO;
    for (Schedule schedule : route) {
      ZonedDateTime depart = zdt.with(schedule.getDepart());
      ZonedDateTime arrive = zdt.with(schedule.getArrive());

      if (lastArrival != null) {
        if (lastArrival.isAfter(depart)) {
          // Most likely, we've shifted to a new day...
          // Updat the anchor and target values
          zdt = zdt.plusDays(1);
          depart = depart.plusDays(1);
          arrive = arrive.plusDays(1);
        }
        Duration duration = Duration.between(lastArrival, depart);
        totalDuration = totalDuration.plus(duration);
        System.out.println("...Wait for " + duration.toHoursPart() + "h " + duration.toMinutesPart() + "m");
      }

      Duration duration = Duration.between(depart, arrive);
      System.out.println(duration.toHoursPart() + "h " + duration.toMinutesPart() + "m");
      totalDuration = totalDuration.plus(duration);

      lastArrival = arrive;
    }
    System.out.println("Total duration of " + totalDuration.toHoursPart() + "d " + totalDuration.toHoursPart() + "h " + totalDuration.toMinutesPart() + "m");

  }

  public static class Schedule {

    private LocalTime depart;
    private LocalTime arrive;

    public Schedule(LocalTime depart, LocalTime arrive) {
      this.depart = depart;
      this.arrive = arrive;
    }

    public LocalTime getDepart() {
      return depart;
    }

    public LocalTime getArrive() {
      return arrive;
    }

  }
}

哪个会输出...

2h 56m
...Wait for 18h 31m
10h 31m
...Wait for 12h 27m
7h 17m
Total duration of 3d 3h 42m

但是为什么要这样做呢?因为日期/时间操作完全是一团糟,有闰秒、年份和其他愚蠢的规则,旨在阻止它陷入混乱(这就是为什么12:00 :/ 没有航班)......和不要让我开始夏令时...

Java 日期/时间 API 为我们处理所有这些。

我选择在单个工作单元(即 UTC)中维护日期/时间信息,这允许所有值具有某种有用的含义。您可以轻松地使用不同的锚点时间以及转换为不同的时区以用于演示 - 因此您可以在目的地以当地时间显示时间,但计算将继续针对单个事实点进行。

【讨论】:

  • 要挑剔,主要问题是,恕我直言,我们在输入数据中没有日期信息 - 从逻辑上讲,假设 正常航班,如果到达时间早于一号出发,我们可以假设它必须在一天后...但如果是乘船旅行,可能会在几天后...(大多数航班计划{我知道}都有类似+1表示它是第二天)
  • @CarlosHeuberger 我的“首选”解决方案将在单个时区中同时包含日期和时间的值,因此您最终不会遇到太多奇怪的事情,但是在物理上仍然可以即使在那种情况下,也要在您离开之前到达。我正在“尝试”做的是让人们“停止”对日期/时间值进行数学操作,因为这更糟糕(IMO)
  • 我会考虑在我的程序完成后实现它,现在我需要专注于完成它。非常感谢您!
【解决方案2】:

24 小时内的总分钟数为 1440。因此,当差值低于零(但您需要一个正数)时,您应该在结果中添加一整天:

int diff = MINUTES.between(arrival, a);
if (diff < 0) {
    diff += 1440;
}

你可以用这个来达到同样的目的:

int diff = (MINUTES.between(arrival, a) + 1440) % 1440;

【讨论】:

  • 非常感谢!这解决了它。你能解释一下它是如何工作的吗?
  • @NaeemKhan 很高兴它有帮助。检查更新。如果您想要更详细的解释,请阅读modular addition/substraction
  • 我理解那部分。那天晚上我是凌晨 5 点,所以我的大脑无法正常运作。我没有意识到 1440 是一天中的分钟数。谢谢你的解释。
猜你喜欢
  • 2023-03-30
  • 2015-02-22
  • 1970-01-01
  • 2012-08-16
  • 1970-01-01
  • 2022-11-07
  • 2013-09-25
  • 2011-06-01
  • 2016-04-01
相关资源
最近更新 更多