Swift 3时区问题

16

看起来NSTimeZone中的setDefaultTimeZone方法已不再可用。有人知道替代方法吗?

在我的AppDelegate.swift文件中,我有以下代码:

NSTimeZone.default = TimeZone(abbreviation: "BST")!

我猜原本的意图应该是如愿以偿的,因为在其他所有文件中,我得到的 NSTimeZone 值都被设置成了这个值。

现在,在我的 Utils 中,我有这个方法:

static func getDate(_ dateStr: String) -> Date {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd"
    // dateFormatter.timeZone = TimeZone(abbreviation: "GMT")
    let date =  dateFormatter.date(from: dateStr)!
    return date
}

假设我输入 2016-10-07,它会返回 2016-10-06 23:00。为什么?如果您取消注释上面代码中的行,就可以修复它。但我不想在每个地方都使用这行代码。

例如,在我的项目的其他部分中,我使用了CVCalendar。它提供了一个获取转换日期的函数,如下所示:

func didSelectDayView(_ dayView: DayView, animationDidFinish: Bool) {
    selectedDay = dayView
    selectedDate = dayView.date.convertedDate()!
}

这里发生了与之前相同的情况...也就是我点击了 2016-10-08selectedDate 变成了 2016-10-07 23:00

NSTimeZone.Default 在任何地方都打印出 Europe/London

有人知道为什么会这样吗?


你能展示一下你尝试过的代码吗? - Anbu.Karthik
请参考此文档:https://developer.apple.com/reference/foundation/nstimezone/ - Himanshu Moradiya
@AmrataB 你应该这样初始化时区,让locale等于NSTimeZone.init(abbreviation: "BST")。 - Jitendra Modi
@Anbu.Karthik,没有更多的代码了。我曾经调用它一次,它就可以工作了。 - AmrataB
@AmrataB 你试过像我这样的解决方案吗? - Nirav D
显示剩余6条评论
3个回答

14

试着这样做。

TimeZone.ReferenceType.default = TimeZone(abbreviation: "BST")!

编辑:我已经使用了这个TimeZoneDateFormatter,并且得到了正确的带有日期的BST时间。

TimeZone.ReferenceType.default = TimeZone(abbreviation: "BST")!
let formatter = DateFormatter()
formatter.timeZone = TimeZone.ReferenceType.default
formatter.dateFormat = "yyyy-MM-dd HH:mm"
let strDate = formatter.string(from: Date())
print(strDate)

如果你想为NSTimeZone对象设置defaultTimeZone,那么在Swift 3中你可以像这样设置。

NSTimeZone.default = TimeZone(abbreviation: "BST")!

通过设置 NSTimeZone.default = TimeZone(abbreviation: "BST")!,您只是设置了默认时区而没有使用它。当您使用 dateFormatter 时,请使用特定的时区,否则它可能会使用您的系统或本地时区。 - Nirav D
您不必为DateFormatter单独指定TimeZone。它会选择您在NSTimeZone默认值或TimeZone默认值上设置的值。我的问题是,在Swift 3之前,它考虑了夏令时,也就是说,如果您打印时区,它会给出Europe/London (GMT+1)偏移量3600(夏令时),所以一切都对我起作用。但现在,它开始返回Europe/London或UTC减去一个小时。这破坏了一切。因此,我现在将默认值设置为UTC,这样它在一个月后不会再次中断。 - AmrataB
@AmrataB,我不确定你所说的是否正确,因为我首先尝试在playground中设置默认时区为BST,然后尝试获取当前时间,但它并不是BST,而是我的当前时区。在使用dateFormatter设置时区后,我才能够获取当前的BST时间。也许你误解了,请再仔细检查一遍。 - Nirav D
@AmrataB 我已经在 IBM Swift Sandbox 上发布了相同的代码,请您先检查此链接并尝试运行代码,然后取消注释指定日期格式化程序时区的那一行,您将会看到不同之处。请查看此链接 https://swiftlang.ng.bluemix.net/#/repl/57f885c0ed27cb2723a1cb52 首先,您将获得 IBM 沙盒服务器当前时间,如果您取消注释,则会获得当前 BST 时间。 - Nirav D
我不明白为什么这个可以工作:TimeZone.ReferenceType.default = TimeZone(abbreviation: "UTC")! dateFormatter.timeZone = TimeZone.ReferenceType.default而这个会失败: dateFormatter.timeZone = TimeZone(abbreviation: "UTC")以产生Z时区的日期时间。 - James Y
显示剩余2条评论

10
let locale = NSTimeZone.init(abbreviation: "BST")
NSTimeZone.default = locale as! TimeZone

试试这个


4
不需要先创建NSTimeZone实例再将其转换为TimeZone,你可以直接使用TimeZone(abbreviation:)创建对象,就像我的回答那样。 - Nirav D
2
我知道,但是它有点容易理解。 - Jitendra Modi

2
如果您正在使用日历,则需要执行以下操作:
// 创建日历对象
var calendar = NSCalendar.current

//* 定义要使用的日历组件以及时区到UTC的转换 *

let unitFlags = Set<Calendar.Component>([.hour, .year, .minute])
calendar.timeZone = TimeZone(identifier: "UTC")!
/// Returns a time zone initialized with a given identifier.
///
/// An example identifier is "America/Los_Angeles".
///
/// If `identifier` is an unknown identifier, then returns `nil`.
public init?(identifier: String)

The geopolitical region identifier that identifies the time zone.

public var identifier: String { get }

注意:如果你想设置日期格式化的时区,可以按照上述方法进行操作:

dateFormatter.timeZone = TimeZone(identifier: "UTC")!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接