Muszę obliczyć łączny czas przelotu między lotniskiem odlotu a lotniskiem przylotu.Błąd obliczania różnicy czasu
Ta praca jest wykonywana przez ten fragment kodu:
public int calculateFlightDuration(String departureDateTime, String depAirportCode, String arrivalDateTime,
String arrAirportCode) {
try {
LocalDateTime depLocalTime = LocalDateTime.parse(departureDateTime, formatter);
LocalDateTime arrLocalTime = LocalDateTime.parse(arrivalDateTime, formatter);
ZoneOffset depZoneOffset = getTimeZoneOffset(depAirportCode);
ZoneOffset arrZoneOffset = getTimeZoneOffset(arrAirportCode);
if (depZoneOffset != null && arrZoneOffset != null) {
OffsetDateTime offsetDepTime = OffsetDateTime.of(depLocalTime, depZoneOffset);
OffsetDateTime offsetArrTime = OffsetDateTime.of(arrLocalTime, arrZoneOffset);
Duration flightDuration = Duration.between(offsetArrTime, offsetDepTime).abs();
return (int) flightDuration.toMinutes();
}
} catch (Exception e) {
LOG.warn("::calculateFlightDuration depTime:{} dep.code:{} arrTime:{} arr.code:{}", departureDateTime,
depAirportCode, arrivalDateTime, arrAirportCode);
}
return 0;
}
Oto problem:
Kiedy chcę, aby obliczyć czas trwania przyszłego lotniczej z tymi parametrami:
depLocalTime = 2017-11-06T14:50
arrLocalTime = 2017-11-06T16:45
depZoneOffset = +03:00
arrZoneOffset = +02:00
jako w wyniku tych parametrów obiekt flightDuration:
flightDuration = PT2H55M
Wygląda na to, że wszystko jest w porządku, prawda? Ale to nie jest w porządku. Pozwól mi wyjaśnić;
kod lotniska wylotu jest IST (Turcja) i przyjazd kod lotniska jest AMS (Holandia) i tu jest klucz:
Po 29.10.2017 (przed czasem ja obliczonej), czas AMS będzie wspierane przez 1 godzinę, a jego przesunięcie będzie +01: 00, a przesunięcie IST nadal pozostanie +03: 00. Dlatego prawidłowym obiektem czasu trwania musi być:
flightDuration = PT3H55M
Jak mogę rozwiązać ten problem? To jest naprawdę denerwujące. Dzięki za pomoc.
Edit po ZonedDateTime komentarze:
Chłopaki, ja też próbowałem z obiektu ZonedDateTime na obliczeniach. Oto kod z użytym obiektem ZonedDateTime, nie ma to wpływu na wynik.
public int calculateFlightDuration(String departureDateTime, String depAirportCode, String arrivalDateTime,
String arrAirportCode) {
try {
LocalDateTime depLocalTime = LocalDateTime.parse(departureDateTime, formatter);
LocalDateTime arrLocalTime = LocalDateTime.parse(arrivalDateTime, formatter);
ZoneOffset depZoneOffset = getTimeZoneOffset(depAirportCode);
ZoneOffset arrZoneOffset = getTimeZoneOffset(arrAirportCode);
if (depZoneOffset != null && arrZoneOffset != null) {
ZonedDateTime zonedDepTime = ZonedDateTime.of(depLocalTime, depZoneOffset);
ZonedDateTime zonedArrTime = ZonedDateTime.of(arrLocalTime, arrZoneOffset);
// OffsetDateTime offsetDepTime = OffsetDateTime.of(depLocalTime, depZoneOffset);
// OffsetDateTime offsetArrTime = OffsetDateTime.of(arrLocalTime, arrZoneOffset);
Duration flightDuration = Duration.between(zonedDepTime, zonedArrTime).abs();
return (int) flightDuration.toMinutes();
}
} catch (Exception e) {
LOG.warn("::calculateFlightDuration depTime:{} dep.code:{} arrTime:{} arr.code:{}", departureDateTime,
depAirportCode, arrivalDateTime, arrAirportCode);
}
return 0;
}
Po odpowiedź @Joe C „s, zmieniłem ponownie kod i wierzę, że jest to sposób powinien iść:
public int calculateFlightDuration(String departureDateTime, String depAirportCode, String arrivalDateTime,
String arrAirportCode) {
try {
LocalDateTime depLocalTime = LocalDateTime.parse(departureDateTime, formatter);
LocalDateTime arrLocalTime = LocalDateTime.parse(arrivalDateTime, formatter);
ZoneId depZoneId = getTimeZoneId(depAirportCode);
ZoneId arrZoneId = getTimeZoneId(arrAirportCode);
if (depZoneId != null && arrZoneId != null) {
ZonedDateTime zonedDepTime = ZonedDateTime.of(depLocalTime, depZoneId);
ZonedDateTime zonedArrTime = ZonedDateTime.of(arrLocalTime, arrZoneId);
Duration flightDuration = Duration.between(zonedDepTime, zonedArrTime).abs();
return (int) flightDuration.toMinutes();
}
} catch (Exception e) {
LOG.warn("::calculateFlightDuration depTime:{} dep.code:{} arrTime:{} arr.code:{}", departureDateTime,
depAirportCode, arrivalDateTime, arrAirportCode);
}
return 0;
}
ALE: Java zakłada, że Stambuł również zmienić jego strefę czasową przesunięcie do +02: 00, ale TO NIE DZIAŁA. Myślę, że muszę również zaktualizować moją Javę. Oto wynik po zmianie kodu: czas trwania lotu
depZoneId = Europe/Istanbul
arrZoneId = Europe/Amsterdam
zonedDepTime = 2017-11-06T14:50+02:00[Europe/Istanbul] //damn it's really annoying!
zonedArrTime = 2017-11-06T16:45+01:00[Europe/Amsterdam]
aaand pozostaje taka sama:
flightDuration = PT2H55M
Dzięki za odpowiedzi facetów. Teraz muszę naprawić zmianę strefy czasowej w Stambule.
Wskazówka - należy użyć 'ZonedDateTime' zamiast' OffsetDateTime'. Mam nadzieję, że to wystarczająca ilość informacji, które pomogą ci to rozwiązać. Napiszę pełną odpowiedź, jeśli będę miał czas później. –
Witam @Jesper, to dlatego, że różnica musi być PT3H55M at 2017-11-06. W tym dniu przesunięcie AMS będzie wynosić +01: 00. –
Ale lot nie będzie nagle o 1 godzinę dłuższy, tylko dlatego, że AMS przełącza się na czas zimowy? – Jesper