当我在英国地区将字符串转换为日期并且时区是马斯喀特时,DateFormatter 给了我不正确的结果

Posted

技术标签:

【中文标题】当我在英国地区将字符串转换为日期并且时区是马斯喀特时,DateFormatter 给了我不正确的结果【英文标题】:DateFormatter giving me incorrect result while I am converting String into Date in UK region and Timezone is Muscat 【发布时间】:2020-04-07 10:35:09 【问题描述】:

我想要"yyyy-MM-dd HH:mm:ss",时间为 24 小时格式,但由于我的手机中有 12 小时日期格式设置并且时区设置为马斯喀特,我得到的日期始终是 12 小时格式,而我与英国地区核对。我可以将 Date() 更改为 24 小时格式的字符串,但是当我将 24 小时字符串更改为 24 小时日期时,它总是给我 12 小时日期格式

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
let dateToString = dateFormatter.string(from: Date()) //2020-04-06 15:47:16
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
let dateFromString = dateFormatter.date(from: dateToString)
print(dateFromString) // 2020-04-06 1:47:25 pm +0000

【问题讨论】:

那是哪种编程语言?请相应地标记您的问题。 【参考方案1】:

Date 对象仅代表一个时间点。 Date 对象不知道“我应该以 12 小时制还是 24 小时制显示”。这是由DateFormatter 生成(或使用)的字符串的一个特性。

所以,有一些想法:

日期格式化程序的dateFormat(及其locale)决定了当您调用string(from:) 时字符串的外观。 (当你调用date(from:) 时,它还会指示如何解释字符串并创建Date 对象,但这与这里无关。)

因此,如果您要查找使用 24 小时制的日期的字符串表示形式,请查看日期格式化程序的 string(from:) 方法生成的字符串。这是您示例中的 dateToString 字符串。

但是,如果您随后从格式化程序的 date(from:) 方法生成 Date 对象,则生成的 Date 将无法捕获是否使用 12 小时制还是 24 小时制。如果您 print 这个 Date 对象,它不会反映您的 12/24 小时时钟偏好。

底线,在查看由DateFormatter 生成(或传递给)DateFormatterString 对象时,只关心上午/下午与 24 小时制。打印 Date 对象时不要担心输出格式,因为这仅用于调试目的,不会捕获上午/下午与 24 小时时钟维度。

你说:

最后的声明是“2020-04-09 4:23:27 am +0000”格式。

如果您看到 +0000,则表明您正在打印 Date 对象本身。 DateFormatterdateFormatlocale 只控制string(from:) 生成的字符串的格式(以及如何解析字符串)。

所以,打印由DateFormatter 生成的字符串,而不是Date 对象。 Date 对象的打印将始终采用此预定义格式。在应用程序中,如果您需要给定格式的输出,请使用由DateFormatter 生成的String,而不是Date 对象。


考虑一个更明显的问题示例,其中DateFormatter 用于以非常不同的格式创建字符串:

let now = Date()
print(now)                                   // 2020-04-07 11:54:58 +0000

let formatter = DateFormatter()
formatter.dateStyle = .long
formatter.timeStyle = .long
let string = formatter.string(from: Date())
print(string)                                // April 7, 2020 at 4:54:58 AM PDT

if let date = formatter.date(from: string) 
    print(date)                              // 2020-04-07 11:54:58 +0000

因此,即使格式化程序成功地将 Date 转换为 String,然后返回,最后的 print 语句使用与第一个 print 语句相同的固定格式,因为我只是在打印Date 对象。我不担心最后一个print 声明不符合我的DateFormatter 的配置。我没想到会这样。当我打印Date 时,它总是采用固定的预定义格式。我只关心DateFormatter(第二条print语句)生成的字符串的格式。


顺便说一句,还有关于您的"yyyy-MM-dd HH:mm:ss" 格式的次要问题。这代表什么时区?你当地的时区?您的服务器的时区? GMT/UTC/祖鲁?我们经常使用 ISO8601/RFC3339 日期字符串(如2020-04-07T11:54:58Z)来消除这种歧义。你应该首先解决你最初的问题,但是当你把它抛在脑后时,你会想认真看看为什么要以这种格式存储它,以及你想如何正确处理时区。但首先要做的事情。

【讨论】:

嗨@Rob 非常感谢您的帮助。最后的声明是给我“2020-04-09 4:23:27 am +0000”格式。我需要 24 小时格式,我的整个项目取决于 24 小时。此格式问题仅在英国地区产生。

以上是关于当我在英国地区将字符串转换为日期并且时区是马斯喀特时,DateFormatter 给了我不正确的结果的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中使用 tz.localize 将 UTC 日期时间转换为英国日期时间

将iso日期格式的字符串转换为毫秒。 ISO日期格式包含(“ yyyy-MM-dd”),并且没有时区

Django 自动将日期时间字符串转换为本地时区

Python 字符串到 Django 时区(知道日期时间)

如何将日期字符串转换为没有时区的日期对象

将英国格式日期转换为日期时间