问题
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. 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. But the second difference is only 5 hours while it should be 19 hours. 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. The format of the output above is (City, Departure Time, Flight No., Destination, Arrival Time).
回答1:
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:
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;
回答2:
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.
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.
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. Each Time
of the schedule is then applied to this. 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...
The Java date/time API takes care of all of this for us.
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. 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.
来源:https://stackoverflow.com/questions/53254475/localtime-difference-between-two-times