【问题标题】:Time difference calculation error时差计算错误
【发布时间】:2018-03-15 12:47:37
【问题描述】:

我必须计算出发机场和到达机场之间的总飞行时间分钟。

这个工作是由这段代码sn-p完成的:

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

问题来了:

当我想用这些参数计算未来飞行的持续时间时:

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

由于这些参数,flightDuration 对象是:

flightDuration = PT2H55M

似乎一切正常,对吧?但实际上并不好。让我解释一下;

出发机场代码是 IST(土耳其),到达机场代码是 AMS(荷兰),这里是关键:

2017-10-29 之后(在我计算的时间之前),AMS 时间将后退 1 小时,其偏移量为 +01:00,IST 偏移量仍保持为 +03:00。所以正确的持续时间对象必须是:

flightDuration = PT3H55M

我该如何解决这个问题?这真的很烦人。 感谢您的帮助。

在 ZonedDateTime cmets 之后编辑:

伙计们,我还尝试使用 ZonedDateTime 对象进行计算。这是使用 ZonedDateTime 对象的代码,它对结果没有影响。

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

在@Joe C 的回答之后,我再次更改了代码,我相信这是我应该走的路:

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

但是:Java 假设伊斯坦布尔也将其时区偏移更改为 +02:00,但它不会发生。我想我还需要更新我的 Java。以下是代码更改后的结果:

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 飞行时长保持不变:

flightDuration = PT2H55M

感谢大家的回答。现在我必须修复伊斯坦布尔的时区变化。

【问题讨论】:

  • 提示 - 您需要使用 ZonedDateTime 而不是 OffsetDateTime。我希望这些信息足以帮助您解决问题。以后有时间我会写一个完整的答案。
  • 嗨@Jesper,那是因为差异必须是 2017-11-06 的 PT3H55M。在此日期,AMS 的偏移量将为 +01:00。
  • 但是飞行时间不会因为 AMS 切换到冬季时间而突然延长 1 小时?
  • 你绝对是对的 :) 这只是表示两个当地时间之间的差异,可能会造成混淆。

标签: java time duration timezone-offset datetimeoffset


【解决方案1】:

OffsetDateTime 假定全年有一个共同的偏移量(例如 UTC+2)。它不包括夏令时的任何内容。

如果您想考虑夏令时,您应该使用ZonedDateTime,而不是ZoneId。对于Europe/Amsterdam,它将根据一年中的时间选择UTC+1 或UTC+2。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-19
    • 1970-01-01
    • 2017-05-20
    相关资源
    最近更新 更多