【问题标题】:How can I ignore time zones in Swift Dates?如何忽略 Swift Dates 中的时区?
【发布时间】:2021-03-29 20:40:58
【问题描述】:

我希望使用 Swift 5 创建一个 Date 对象,其中包含我传递的日期、月份和年份。问题是 DateFormatter 有自己的想法,并且似乎将我的 Date 对象视为 UTC,即使我将 <formatter>.timeZone = ... 设置为。

假设我想要日期对象为 4 月 1 日。

private func firstOfApril() -> String {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    return "\(formatter.date(from: "2021-04-01")!)"
}

如果我在这里的上午 (GMT + 13) 执行此操作,我会收到 2021-03-31 11:00:00 +0000。我期待:2021-04-01 00:00:00

我尝试了什么:

enum TZType{
    case None
    case Current
    case Auto
    case Nil
    case Default
}
private func firstOfApril(none_current:TZType) -> String {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    switch none_current {
    case .None:
        formatter.timeZone = .none
    case .Current:
        formatter.timeZone = .current
    case .Nil:
        formatter.timeZone = nil
    case .Auto:
        formatter.timeZone = .autoupdatingCurrent
    case .Default:
        break
    }
    return "\(formatter.date(from: "2021-04-01")!)"
}
        print(firstOfApril(none_current: .None))
        print(firstOfApril(none_current: .Current))
        print(firstOfApril(none_current: .Auto))
        print(firstOfApril(none_current: .Nil))
        print(firstOfApril(none_current: .Default))

输出

2021-03-31 11:00:00 +0000
2021-03-31 11:00:00 +0000
2021-03-31 11:00:00 +0000
2021-03-31 11:00:00 +0000

我的应用程序中没有时区的概念。我认为应该有,但我被否决了。所有时间都是“本地时间”,如挂钟时间,而不是本地时区。

【问题讨论】:

  • 问题是在将日期转换为字符串时也需要使用日期格式化程序。当您打印(或使用字符串插值)您的日期时,它将始终打印 UTC 时区 (+0000)
  • private func firstOfApril() -> String { let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd" let date = formatter.date(from: "2021-04-01")! return formatter.string(from: date) } // "2021-04-01"

标签: swift datetime timezone


【解决方案1】:

里奥明白了。

该函数的最后几行应该是:

    let retDate = formatter.date(from: "2021-04-01")!
    return formatter.string(from: retDate)

总共:

private func firstOfApril(none_current:TZType) -> String {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    switch none_current {
    case .None:
        formatter.timeZone = .none
    case .Current:
        formatter.timeZone = .current
    case .Nil:
        formatter.timeZone = nil
    case .Auto:
        formatter.timeZone = .autoupdatingCurrent
    case .Default:
        break
    }
    let retDate = formatter.date(from: "2021-04-01")!
    return formatter.string(from: retDate)
}

【讨论】:

    【解决方案2】:

    您获得了一些不错但不完整的信息。

    Date 对象捕捉地球上任何地方的某个时刻。它没有时区。 (在内部,它记录自 iOS/MacOS“纪元日期”或“零日期”以来的秒数。零日期是 UTC。)

    日期对象没有时区,但它们也没有固定的时间或日期。同一时刻将在不同时区的不同时间出现,甚至可能是不同的日期(例如,在美国东部夏令时时区,3 月 29 日星期一大约是晚上 7 点。大约是 30 日星期二午夜三月在伦敦。)

    如果您创建一个日期格式化程序并为其提供月/日/年,它将默认使用您当地的时区创建一个 Date 对象。具有时区的不是 Date 对象,而是日期格式化程序。

    您可以使用已创建的日期格式化程序将日期转换回字符串(使用 DateFormatter 函数 string(from:),或者您可以使用名为 localizedString(from:dateStyle:timeStyle: 的 DateFormatter 类函数。该函数需要一个日期并显示它在您当地的时区,使用您的语言环境的约定,并允许您指定短、中或长格式日期。

    如果你写

    let date = Date()
    print(DateFormatter.localizedString(from: date, dateStyle: .medium, timeStyle: .medium))
    

    你会得到这样的东西:

    Mar 29, 2021 at 7:07:13 PM
    

    这是用我的当地时区表示的,使用美国日期和时间格式。

    (但使用您运行它的日期和时间,并使用您所在区域设置的日期和时间格式约定。)

    接下来,就是显示日期的方式。如果你写代码

    print(Date())
    

    您将看到运行代码时的日期,但以 UTC 表示。对我来说,这将比我现在的时间早 4 小时,因此它会声称大约是 1 月 30 日的 23:00。

    2021-03-29 23:00:48 +0000
    

    如果您在中国,而我在美国,我们的手机时钟都完全同步,并且我们在同一时刻使用Date() 捕获当前日期,我们将获得完全相同的 Date 值。如果我们都用 UTC 表示,它将显示相同的日期和时间。 (Date 对象没有时间

    【讨论】:

    • 重点是我将哪个时区提供给格式化程序以更改我传入的值。
    猜你喜欢
    • 2016-01-20
    • 1970-01-01
    • 2020-08-28
    • 2011-10-04
    • 2014-02-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2012-06-24
    相关资源
    最近更新 更多