2017-10-04 6 views
7

Je dois calculer le temps total de vol entre l'aéroport de départ et l'aéroport d'arrivée.Erreur de calcul du décalage horaire

Ce travail est fait par cet extrait de code:

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

Voici le problème:

Quand je veux calculer la durée de vol future avec ces paramètres:

depLocalTime = 2017-11-06T14:50 
arrLocalTime = 2017-11-06T16:45 
depZoneOffset = +03:00 
arrZoneOffset = +02:00 

comme résultat de ces paramètres, l'objet flightDuration est:

flightDuration = PT2H55M 

Tout semble correct, n'est-ce pas? Mais ce n'est pas OK en fait. Laisse-moi expliquer;

Le code de l'aéroport de départ est IST (Turquie) et à l'arrivée code de l'aéroport est AMS (Pays-Bas) et voici la clé:

Après 29.10.2017 (avant le temps que je calculé), le temps AMS sera soutenu par 1 heure, et son décalage sera +01: 00, et le décalage d'IST reste toujours +03: 00. Donc l'objet de durée correcte doit être:

flightDuration = PT3H55M 

Comment puis-je résoudre ce problème? C'est vraiment agaçant. Merci pour votre aide.

Modifier après les commentaires ZonedDateTime:

Les gars, j'ai aussi essayé avec un objet ZonedDateTime, sur des calculs. Voici le code avec l'objet ZonedDateTime utilisé, cela ne fait aucune différence sur le résultat.

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

Après la réponse du C @ Joe, j'ai changé à nouveau le code et je pense que cela est la façon dont je devrais aller:

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

MAIS: Java suppose que Istanbul changer aussi son fuseau horaire décalage à +02: 00, mais il ne se passera pas. Je pense que j'ai aussi besoin de mettre à jour mon Java. Voici le résultat après le changement de code:

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 durée de vol reste le même:

flightDuration = PT2H55M 

Merci pour les gars réponses. Maintenant, je dois corriger le changement de fuseau horaire d'Istanbul.

+0

Indice - vous devez utiliser 'ZonedDateTime' au lieu de' OffsetDateTime'. J'espère que c'est assez d'informations pour vous aider à le résoudre. Je vais écrire une réponse complète si j'ai le temps plus tard. –

+0

Salut @Jesper, c'est parce que la différence doit être PT3H55M à 2017-11-06. À cette date, le décalage de l'AMS sera +01: 00. –

+0

Mais le vol ne sera pas soudainement une heure de plus juste parce que AMS est passé à l'heure d'hiver? – Jesper

Répondre

6

OffsetDateTime suppose un décalage commun pour toute l'année (par exemple UTC + 2). Il ne couvre rien du genre de l'heure d'été.

Si vous souhaitez prendre en compte l'heure d'été, vous devez utiliser un ZonedDateTime à la place, avec un ZoneId. Dans le cas de Europe/Amsterdam, il sélectionnera UTC + 1 ou UTC + 2 en fonction de la période de l'année.

ZonedDateTime zonedDepTime = ZonedDateTime.of(depLocalTime, ZoneId.of("Asia/Istanbul")); 
ZonedDateTime zonedArrTime = ZonedDateTime.of(arrLocalTime, ZoneId.of("Europe/Amsterdam"));