【问题标题】:Swift - Timezone off by one hour / secondsFromGMT incorrectSwift - 时区关闭一小时/秒FromGMT不正确
【发布时间】:2017-03-13 10:16:20
【问题描述】:

这应该是一个非常简单的问题,但我似乎无法理解它。

鉴于我的时区是 EDT (GMT-4),为什么 GMT 的 04:00 变成 23:00 而不是 00:00?

// The offset is -4 hours
let offsetFromGMT = Calendar.current.timeZone.secondsFromGMT() / 60 / 60

// 2017-03-12 04:00
var destinationComponents = DateComponents()
destinationComponents.timeZone = TimeZone(secondsFromGMT: 0)
destinationComponents.year = 2017
destinationComponents.month = 03
destinationComponents.day = 12
destinationComponents.hour = -offsetFromGMT // 4 hours

// Why is this 2017-03-11 23:00 and not 2017-03-12 00:00?
let date = Calendar.current.date(from: destinationComponents)!
// Outputs 23
Calendar.current.dateComponents([.hour], from: date).hour

【问题讨论】:

  • print(date) 应该显示2017-03-12 04:00:00 +0000。 – 根据您所在位置的该日期是否启用夏令时,在您当地的时区中可能是 2017-03-12 00:002017-03-11 23:00。 – Calendar.current.timeZone.identifier 打印什么?
  • 它打印“America/New_York”并且 print(date) 显示 2017-03-12 04:00:00 +0000。是的,但在这种情况下,为什么 secondsFromGMT() 中不包含夏令时?
  • secondsFromGMT() 是当前的 GMT 偏移量。还有另一个函数 secondsFromGMT(for: date) 返回指定日期的 GMT 偏移量,其中包括 DST。 – 你到底想达到什么目标?
  • 是的,我看过那个,但如果我执行 Calendar.current.timeZone.secondsFromGMT(for: Date()),它仍然是 -14400(-4 小时)。如果我传入日期而不是 Date() 则为 -18000,但这对我来说毫无意义。作为背景,我有一个适用于 GMT 日期的应用程序,但是从 EDT 到 GMT 的翻译在某个地方出错了。当我注意到这一点时,我正在尝试调试代码。上面的示例代码只是说明了问题。

标签: ios swift calendar timezone


【解决方案1】:
Calendar.current.timeZone.secondsFromGMT()

是您所在时区的当前 GMT 偏移量。在你的情况下 是 4 小时,因为纽约的当前时区是 EDT = GMT-4, 夏令时有效。

所以你的destinationComponentsdate 是四点钟 格林威治时间早上:

2017-03-12 04:00:00 +0000

那时,纽约的时区是 EST = GMT-5,并且 夏令时未激活。因此,该日期是您当地时区的2017-03-11 23:00


我会采取不同的方式,避免“secondsFromGMT”。

示例:“2017-03-12 00:00:00”纽约时间是“2017-03-12 05:00:00”格林威治标准时间。

var srcComponents = DateComponents()
srcComponents.timeZone = TimeZone(identifier: "America/New_York")!
srcComponents.year = 2017
srcComponents.month = 3
srcComponents.day = 12
srcComponents.hour = 0
srcComponents.minute = 0

let date = Calendar.current.date(from: srcComponents)!
print(date) // 2017-03-12 05:00:00 +0000

【讨论】:

  • 啊,我真的没有意识到夏令时刚刚改变。我的印象是今年晚些时候。谢谢。这就解释了一切。
  • @Robert:不客气! – 我添加了另一种可能有用的方法。
  • 有人会认为 secondsFromGMT,一种数学计算,比无类型字符串文字更安全,但事实并非如此,因为 secondsFromGMT 不考虑半小时时区(有 4 个)。我建议使用abbreviation 而不是identifier,因为缩写是一个“标准化”列表(也比标识符列表短得多)并且因为我在标识符列表中找不到印度或纽芬兰(4 个中的 2 个半-小时时区)即使我确定(我希望)它们被埋在那长长的列表中的某个地方。大约有 20 个印第安人和印第安人保留地,但没有印第安人。
  • 为了完整起见,也有 45 分钟的时区,但我还没有找到一种方法,或者坦率地说,我什至没有希望使用任何方法来定位它们。世界上大约有 35-40 个“公认的”UTC 时区名称,几乎没有人使用相同的列表。对于有 45 分钟时区的国家,我说对不起,你对我来说不存在。当我说 30 分钟和 45 分钟时,我指的是它们与 GMT 的偏移量,而不是时区本身的跨度。
  • @narddog:缩写真的标准化了吗?根据stackoverflow.com/a/18407231/1187415,它可能是不明确的:“例如,CST 可能是“Central Standard Time”(美国)、“China Standard Time”或“Cuba Standard Time”。”跨度>
猜你喜欢
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2021-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
相关资源
最近更新 更多