【问题标题】:How to save datetime with timezone in iOS?如何在 iOS 中使用时区保存日期时间?
【发布时间】:2017-10-28 22:45:04
【问题描述】:

我是 iOS 开发的新手,作为一名 Android 开发人员,我习惯使用一个对象来保存具有给定时区的日期时间(来自 Joda-Time 库)。

在阅读了有关日期和时间的 iOS 文档 (https://developer.apple.com/documentation/foundation/dates_and_times) 之后,我仍然对应该使用哪个类来保存日期时间存有疑问。给定Date/NSDate 类描述“一个特定的时间点,独立于任何日历或时区。”它似乎非常无用,因为它与时区无关,没有时区的时间没有任何意义,因为它没有任何上下文。

我真正的问题(TL;DR)

我有一个数据库,其中日期时间以 UTC 格式存储,例如 "yyyy-MM-dd hh:mm:ss"。我想用某种 DateFormatter(格式为“yyyy-MM-dd hh:mm:ss”的字符串)加上一个时区(UTC)来初始化一个对象,以便轻松转换为我想要的任何时区(显示给用户的默认时区时间)。如何在 iOS 中完成此操作?

编辑:假设我有一个带有标题和开始时间的类事件。标题是String,应该是什么开始时间?

【问题讨论】:

  • 您声明“没有时区的时间没有任何意义”。那是完全错误的。当然,这是有道理的。 Date 是一个时间点。如果我说“现在”,那是世界上每个人都一样的时间点。时区是无关紧要的,直到有人想知道“我的时区中的‘现在’是什么时候?”。然后,您只需将 Date 格式化为具有给定时区的 String
  • @rmaddy 我可能不得不不同意你的观点。想象一下,有人给你这个时间注释“1970-12-12 11:40:30”。你不知道它是什么时候开始的,它是不确定的。您所描述的是事件发生后经过的秒数,这对于所有上下文都是相同的。您必须给出一些起点,这就是时区的作用。
  • 但是字符串“1970-12-12 11:40:30”不是Date。这是一个字符串。您将根据特定时区将该字符串转换为Date。一旦你有了Date,你就可以存储它。稍后您检索它,您可以将 Date 再次转换为您想要的任何时区的字符串。这才是重点。 Date 对象没有特定的时区,也不需要。
  • @Exprove 不,不要认为Date 是UTC。这不是任何时区。这只是一个时间点。期间。
  • @LeoDabus 在内部,Date 表示为自某个纪元以来的时间间隔,这并不意味着 Date 可以被认为是 UTC 时间。

标签: ios swift nsdate swift4


【解决方案1】:

您为此使用DateFormatter

let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.timeZone = TimeZone(secondsFromGMT: 0)

formatter.locale 设置用户的当前语言环境,formatter.dateFormat 设置所需的日期格式。在你的情况下yyyy-MM-dd HH:mm:ss

简单来说:

let utcDateFromServer = "2017-01-01 22:10:10"
let date = formatter.date(from: utcDateFromServer)

【讨论】:

  • 我认为 dateformatter 不能解决我的问题(至少是“模型”部分)。我可能不是很清楚。想象一下,我有一个带有标题和开始时间的类 Event。标题是一个字符串,开始时间应该是什么(我几乎可以肯定它不是一个日期格式化程序)?
  • @Exprove,查看更新后的帖子,它更详细地描述了您想要做什么。
【解决方案2】:

Date 是一个时间点,如其他 cmets 和文档中所述。

如果要将 UTC 时间转换为本地时间,则需要先使用 DateFormatter 将数据库中的 String "yyyy-MM-dd hh:mm:ss" 转换为 Date

let dateStringUTC = "2018-01-01 00:00:00"

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss"
//Set the input timezone (if you don't set anything, the default is user's local time)
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
let date : Date = dateFormatter.date(from: dateStringUTC)! 

然后将Date 转换回String,使用DateFormatter 和相应的TimeZone

let outputDateFormatter = DateFormatter()
outputDateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss"
//Set the output timezone (if you don't set anything, the default is user's local time)
//outputDateFormatter.timeZone = someTimeZone
let dateString = outputDateFormatter.string(from: date)

print(dateString)

输出:2017-12-31 17:00:00

你可以改变输入和输出时区来做相反的事情。

【讨论】:

  • 在将原始字符串转换为Date 时,您不太可能将格式化程序的时区设置为“GMT”。您很可能需要用户的时区,因为它可能是您正在解析的本地时间。
  • @rmaddy 我已经编辑了答案以提供更多信息。我的意思是当原始日期字符串为 UTC 时,因为提问者可能希望将 UTC/GMT 日期从数据库转换为本地时区
  • @LWJ 想象一下,我有一个带有标题和开始时间的类 Event。标题是一个字符串,应该是什么开始时间?
  • @Exprove 您应该使用 Date 作为开始时间。只有当您向最终用户显示日期时,您才能使用DateFormatterDate 转换为String
猜你喜欢
  • 2020-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-19
  • 1970-01-01
相关资源
最近更新 更多