问题描述
这是一个非常令人困惑的情况,我在NSDateFormatter上阅读了许多文档,但似乎无法设置本地化的日期格式模板。使用dateFormat
属性有效,但是使用setLocalizedDateFormatFromTemplate
无效,基本上我在swift 5.3中具有以下代码:
import Foundation // takes a few secs
var ftt = DateFormatter()
ftt.locale = Locale(identifier: "en_US")
ftt.setLocalizedDateFormatFromTemplate("'Deliver on' MMMM d 'at' h:mm a 'sharp'")
运行后,我得到以下输出:
ftt: DateFormatter = {
baseNSFormatter@0 = {
baseNSObject@0 = {
isa = NSDateFormatter
}
}
_attributes = 3 key/value pairs {
[0] = {
key = "locale"
value =
}
[1] = {
key = "formatterBehavior"
value = Int64(1040)
}
[2] = {
key = "dateFormat"
value = "MMMM d,h:mm a"
}
}
_formatter = {}
_counter = 0
_cacheGeneration = 3
_behavior = 0
}
从输出中可以看到,locale
或dateFormat
都没有被存储。格式化日期将导致以下结果:
14> ftt.string(from: Date())
$R1: String = "October 21,8:19 PM"
我确保locale identifier是正确的,我遵循了有关DateFormatter的一些教程,例如:
- https://learnappmaking.com/swift-date-datecomponents-dateformatter-how-to/#string-to-date-parsing-dates-timezones
- https://nsdateformatter.com
并检查setLocalizedDateFormatFromTemplate
和Apple's documentation的用法,并确保在设置locale
后调用它。
如果我直接分配dateFormat
属性,我将得到期望的结果:
17> ftt.dateFormat = "'Deliver on' MMMM d 'at' h:mm a 'sharp'"
ftt: DateFormatter = {
baseNSFormatter@0 = {
baseNSObject@0 = {
isa = NSDateFormatter
}
}
_attributes = 3 key/value pairs {
[0] = {
key = "locale"
value =
}
[1] = {
key = "formatterBehavior"
value = Int64(1040)
}
[2] = {
key = "dateFormat"
value = "\'Deliver on\' MMMM d \'at\' h:mm a \'sharp\'"
}
}
_formatter =
_counter = 0
_cacheGeneration = 2
_behavior = 0
}
18> ftt.string(from: Date())
$R2: String = "Deliver on October 21 at 8:25 PM sharp"
这是怎么回事?!我缺少明显的东西吗?我想了解这种行为。
谢谢!
解决方法
这里的问题是模板中日期组件的顺序没有区别。您只是假设要传递组件,并且如何显示它们取决于语言环境。
let ftt = DateFormatter()
ftt.locale = Locale(identifier: "en_US")
ftt.setLocalizedDateFormatFromTemplate("dMMMMhm")
ftt.dateFormat // "MMMM d,h:mm a"
ftt.string(from: Date()) // "October 22,12:45 AM"
ftt.locale = Locale(identifier: "pt_BR")
ftt.setLocalizedDateFormatFromTemplate("MMMMdysmH")
ftt.dateFormat // "d 'de' MMMM 'de' y HH:mm:ss"
ftt.string(from: Date()) // "22 de outubro de 2020 00:45:36"
,
我认为您误解了setLocalizedDateFormatFromTemplate
的功能。 Its documentation说:
调用此方法等效于(但不一定实现为)将
dateFormat
属性设置为调用dateFormat(fromTemplate:options:locale:)
方法的结果,不传递任何选项和语言环境属性值。
现在dateFormat(fromTemplate:options:locale:)
会做什么?让我们看看:
返回值
本地化的日期格式字符串,代表模板中给定的日期格式组件,并根据语言环境指定的语言环境进行适当排列。
返回的字符串可能不完全包含模板中给定的那些组件,但是(例如)可能已应用了特定于语言环境的调整。
因此,dateFormat(fromTemplate:options:locale:)
尝试将模板本地化到指定的语言环境。如果未指定语言环境,则使用Locale.current
。例如:
// this produces "MM/dd/yyyy"
DateFormatter.dateFormat(fromTemplate: "yyyy dd MM",options: 0,locale: Locale(identifier: "en-US"))
这说明了为什么它删除格式中所有带引号的字符串的原因,因为本地化引擎无法识别您的带引号的字符串,因此要生成日期格式的“本地化”版本,最好的办法是删除它们。就其而言,引用的字符串可以使用其他语言!
所以并不是setLocalizedDateFormatFromTemplate
并没有改变dateFormat
。它 did 将其更改为"MMMM d,h:mm a"
,这是iOS认为是格式最好的“本地化”版本
"'Deliver on' MMMM d 'at' h:mm a 'sharp'"
在这种情况下,您应该直接设置dateFormat
,而不要设置setLocalizedDateFormatFromTemplate
,因为您不希望使用本地化的日期格式。