Swift中的绝对UTC偏移量

时间:2019-11-06 08:53:03

标签: swift timezone utc timezone-offset

我的任务是在夏令时和夏令时创建一个包含UTC偏移量的字符串(例如:UTC+1UTC+2UTC+1UTC+1,如果某个地区没有DST)。我的函数如下所示:

extension TimeZone {
    public func utcOffset(for date: Date = Date()) -> String {
        var currentTimeOffest = self.secondsFromGMT(for: date)
        if isDaylightSavingTime() {
            currentTimeOffest -= Int(daylightSavingTimeOffset(for: date))
        }
        let currentInHours = Int(currentTimeOffest / 3_600)
        let hoursSymbol: String = currentInHours > 0 ? "+" : ""

        let daylightOffset = TimeInterval(currentTimeOffest) + self.daylightSavingTimeOffset(for: date)
        let daylightInHours = Int(daylightOffset / 3_600)
        let daylightSymbol: String = daylightInHours > 0 ? "+" : ""

        return "UTC\(hoursSymbol)\(currentInHours)UTC\(daylightSymbol)\(daylightInHours)"
    }
}

它运行良好,我已经为此进行了测试。一切都很好,但是在多个国家/地区最近更改夏令时之后,即使我通过了一个特定的日期来计算以下项的偏移量,测试也开始失败:

    func testUtcOffset() {
        let date: Date = Date(timeIntervalSince1970: 1_557_482_400) //May 10, 2019 10:00:00 AM

        let warsaw = TimeZone.init(identifier: "Europe/Warsaw")! //eastern hemisphere, with DST
        XCTAssertEqual(warsaw.utcOffset(for: date), "UTC+2UTC+3")

        let shanghai = TimeZone.init(identifier: "Asia/Shanghai")! //eastern hemisphere, without DST
        XCTAssertEqual(shanghai.utcOffset(for: date), "UTC+8UTC+8")

        let barbados = TimeZone.init(identifier: "America/Barbados")! //western hemisphere, without DST
        XCTAssertEqual(barbados.utcOffset(for: date), "UTC-4UTC-4")

        let bermuda = TimeZone.init(identifier: "Atlantic/Bermuda")! //western hemisphere, with DST
        XCTAssertEqual(bermuda.utcOffset(for: date), "UTC-4UTC-3")

        let gmt = TimeZone.init(identifier: "GMT")! //GMT, without DST
        XCTAssertEqual(gmt.utcOffset(for: date), "UTC0UTC0")

        let lisbon = TimeZone.init(identifier: "Europe/Lisbon")! //GMT, with DST
        XCTAssertEqual(lisbon.utcOffset(for: date), "UTC+1UTC+2")
    }

2周前,warsawlisbon时区开始失败,今天bermuda。任何想法可能有什么问题吗?

1 个答案:

答案 0 :(得分:1)

几件事:

  • 在您的测试中,您可以将华沙和里斯本的偏移量减少一个小时。华沙在标准时间是UTC + 1,在夏时制是UTC + 2。里斯本在标准时间是UTC + 0,在白天是UTC + 1。

  • 从您的评论看来,您正在寻找标准偏移量和日光偏移量。但是,标准偏移量不一定与 current 偏移量相同。当前偏移量可能包括夏令时,也可能不包括。

  • 根据these docssecondsFromGMT函数会返回差值包括(如果有效)。因此,您不应该自己为此进行调整。

  • 在不适用夏令时的情况下,向daylightSavingTimeOffset函数询问某个日期的偏移量似乎没有任何意义。仅使用secondsFromGMT表示当年的两个不同日期,您可能会得到更好的结果。一种常见的方法是获取1月1日和7月1日的补偿。标准时间是较小的时间,其他时间是白天的时间。请记住,如果不使用DST,它们可能是相同的,它们将在北半球和南半球时区之间反转。

    • 即使采用上述方法,这种算法也忽略了许多时区复杂性。考虑到某些时区在其历史上的不同时间点已更改了其标准时间。这种算法可能会误认为夏时制会改变。
  • 一个关注点:一旦生成了字符串,例如"UTC+1UTC+2",仅凭那便知道如何应用外部API的夏令时规则集?从daylight saving time starts and stops at different dates and times in different parts of the world开始,解释偏移量时可能会使用错误的日期。