简体   繁体   English

LocalTime()两次之间的差异

[英]LocalTime() difference between two times

I have a flight itinerary program where I need to get difference between departure and arrival time. 我有一个航班行程计划,我需要在出发和到达时间之间取得差异。 I get these specified times as String from the data. 我从数据中将这些指定的时间作为String。 Here is my problem: 这是我的问题:

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));
}
}

Output: 输出:

176
-329

The first time returns the difference between 11:39 and 14:35 just fine. 第一次返回11:39和14:35之间的差异就好了。 But the second difference is only 5 hours while it should be 19 hours. 但第二个差异只有5个小时,而应该是19个小时。 How can I fix this, what am I doing wrong here? 我怎么能解决这个问题,我在这里做错了什么?

Any help would be greatly appreciated. 任何帮助将不胜感激。

EDIT: I am using graphs to store my data in. An example of a shortest route between two airports is like this: 编辑:我使用图表来存储我的数据。两个机场之间最短路线的例子是这样的:

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

These are the 3 flights that takes us from EDI to SYD. 这是我们从EDI到SYD的3个航班。 The format of the output above is (City, Departure Time, Flight No., Destination, Arrival Time). 上面输出的格式是(城市,出发时间,航班号,目的地,到达时间)。

The total number of minutes in 24 hours is 1440. So when the difference is below zero (but you need a positive one) then you should add a whole day to your result: 24小时内的总分钟数为1440.因此,如果差异低于零(但您需要一个正数),那么您应该在结果中添加一整天:

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

You can achieve the same thing using this: 你可以用这个来实现同样的目的:

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

The primary issue at hand is LocalTime is only a representation of time between midnight AM to midnight PM, it has no concept of any range beyond those bounds. 手头的主要问题是LocalTime只是午夜到午夜PM之间的时间表示,它没有超出这些范围的任何范围的概念。

What you really need is a date value, associated with the time value, this would then allow you to calculate durations beyond a 24 hour period. 您真正需要的是与时间值相关联的日期值,这样您就可以计算超过24小时的持续时间。

Failing that, you will need to "fudge" the values yourself. 如果做不到这一点,你需要自己“捏造”这些价值观。 This means, that when the next time is less than previous time, you will need to manually add an additional period, maybe a day. 这意味着,当下一次小于上一次时,您需要手动添加一个额外的时间段,可能是一天。

There are probably a few ways to do this, this is just one. 可能有几种方法可以做到这一点,这只是一种方法。

It takes a ZonedDateTime (set to the current date) and uses it as a "anchor" date. 它需要ZonedDateTime (设置为当前日期)并将其用作“锚点”日期。 Each Time of the schedule is then applied to this. 每个Time则安排的是应用于此。 When it detects that last arrival time is before the next departure time, it adds a day to the values. 当它检测到最后到达时间在下一个出发时间之前时,它会为这些值增加一天。

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;
    }

  }
}

Which will output... 哪个会输出......

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

But why do this? 但为什么这样呢? Because date/time manipulation is a complete mess, with leap seconds, years and other stupid rules which are meant to stop it from all falling apart into chaos (this is why there are no flights at 12:00 :/) ... and don't get me started on daylight savings... 因为日期/时间操纵是一个完整的混乱,闰秒,年和其他愚蠢的规则,旨在阻止它们分崩离析(这就是为什么在12:00没有航班:/)...和不要让我开始夏令时......

The Java date/time API takes care of all of this for us. Java日期/时间API为我们处理所有这些。

I've chosen to maintain the date/time information in a single unit of work, ie UTC, which allows all the values to have some kind of useful meaning. 我选择将日期/时间信息保存在单个工作单元中,即UTC,它允许所有值具有某种有用的含义。 You could easily use a different anchor time as well as convert to a different time zone for use in presentation - so you could display the times in local time at the destination, but the calculations would continue to be done against a single point of truth. 您可以轻松地使用不同的锚定时间以及转换为不同的时区以用于演示 - 因此您可以在目的地的当地时间显示时间,但计算将继续针对单一事实进行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM