Swift 4 : 设置不同的日期和时间

Swift 4 : Set Different Date and Time

我知道如何获取本地日期和时间,但我想做的是从不同地方获取日期和时间。例如,我想知道纽约的时间和日期。我该如何解决这个简单的问题?

这是我的本地日期和时间代码:

let date = NSDate()
let calendar = Calendar.current

let components = calendar.dateComponents([.hour, .minute, .month, .year, .day, .second, .weekOfMonth], from: date as Date)

let currentDate = calendar.date(from: components) 

我在这里搜索过,但没有找到我想要的,我仍在寻找日期库。如果您知道任何来源或样本可以重定向我,我真的很感激。

如果您只想将日期格式化为字符串,请考虑改用 DateFormatter

let date = Date()
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "America/New_York")
formatter.dateStyle = .long
formatter.timeStyle = .long
formatter.string(from: date)

如果要获取日期组件并进行处理,请使用dateComponents(in:from:)方法。

let components = Calendar.current.dateComponents(in: TimeZone(identifier: "America/New_York")!, from: date)

如果您不知道要搜索的地点的时区,可以使用 CoreLocation 的 CLGeocoder 并搜索地址字符串。然后您可以获得该地点的时区并将其转换为您要查找的时间:

let geocoder = CLGeocoder()
geocoder.geocodeAddressString("New York, New York") { (placemarks, error) in
    guard error == nil else {
        print("Error")
        print(error!.localizedDescription)
        return
    }
    guard let placemarks = placemarks,
        let place = placemarks.first else {
        print("No results")
        return
    }

    if let timeZone = place.timeZone {
        print("TimeZone: \(timeZone.identifier)")
        // TimeZone: America/New_York

        //Ignore the time zone offset from this one, it will be the difference between the current time and the new york time
        let dateInNewYork = Date().addingTimeInterval(TimeInterval.init(timeZone.secondsFromGMT()))
        print(dateInNewYork)
        // 2017-11-13 15:03:05 +0000

        //Or
        let formatter = DateFormatter()
        formatter.timeZone = TimeZone(identifier: timeZone.identifier)
        formatter.dateStyle = .long
        formatter.timeStyle = .long
        let formattedDateInNewYork = formatter.string(from: Date())
        print(formattedDateInNewYork)
        // November 13, 2017 at 3:03:05 PM EST

        //Or
        let components = Calendar.current.dateComponents(in: TimeZone(identifier: timeZone.identifier)!, from: Date())
        print(components.date!)
        // 2017-11-13 20:03:05 +0000
    }

}

这里涉及几个不同的概念,我们需要理解(几乎)所有这些概念才能正确理解...

1) a DateNSDate 原样,在 Swift 中)是一个绝对时间点 - 它的命名有点错误,因为它与实际日期,如 2017 年 11 月 13 日,因为要达到这一点,我们需要定义 ...

2) a Calendar,因为西公历 2017 年 11 月 13 日也可能是伊斯兰历的 23 日 Safar 1439,或希伯来历的 Heshvan 5778 的 24 日,或其他一些东西iOS 和 MacOS 支持的许多其他日历;

3) 反过来 Calendar 不仅改变了我们必须用来将 Date + Calendar 解压成天的 DateComponents 中返回的值,月、年和纪元(例如 BC/AD),甚至周数等...,而且 一些日历的组成部分可能与其他日历不同;

4) 一天中的时间(如您所知)取决于 TimeZone,因此相同的 绝对 时间可以是许多不同时间之一 "o'clock" 取决于你在哪里。它还可能(如您在下面的示例中所见)更改 date 以及 "o'clock"。这当然可以是自动的(你在哪里)或由程序员设置;

5) 此外,我们有 DateFormatter(这是包裹 DateComponents 的便利),因为 2017 年 11 月 13 日 可以 表示为 13 /11/17 或 11/13/17 取决于您是英国人还是美国人。我们可能还希望选择我们是使用文本还是数字月份,如果显示时间,我们是否需要 12 小时或 24 小时格式 - 所有这些都包含在 DateFormatter 但是 如果你是法国人,文本表示可能是“13e Novembre 2017”,这引入了

的概念

6) Locale,可以像 TimeZone 一样设置为默认值(在设置设备时选择)或由程序员指定。

您发布的代码将不起作用,因为它所做的只是接受一个 Date,通过 Calendar 将其转换为 DateComponents(到目前为止一切正常),但是然后从组件中重新创建一个 Date - 你将得到的只是原始的 Date - 相同的绝对时间点。

根据问题和您对评论中问题的回答,我认为您想要一个需要绝对时间(例如 "now")又名 Date 的函数并将其显示在具体TimeZone。这有效:

func timeComponents(date: Date, timeZone: TimeZone) -> DateComponents {
    var calendar = Calendar.current
    calendar.timeZone = timeZone
    return calendar.dateComponents([.hour, .minute, .month, .year, .day, .second, .weekOfMonth], from: date)
}

let absTime: Date = Date() // Now
let edinburgh = TimeZone(abbreviation: "GMT")!
let newYork = TimeZone(abbreviation: "EST")!
let ec = timeComponents(date: absTime, timeZone: edinburgh)
let nycc = timeComponents(date: absTime, timeZone: newYork)
print(ec)// year: 2017 month: 11 day: 14 hour: 0 minute: 44 second: 10 weekOfMonth: 3 isLeapMonth: false 
print(nycc) // year: 2017 month: 11 day: 13 hour: 19 minute: 44 second: 10 weekOfMonth: 3 isLeapMonth: false 

... 我认为这至少回答了你的问题,但为了巧妙地解决它,我们需要从 DateComponents 移动到 DateFormatter

func timeString(date: Date, timeZone: TimeZone, timeStyle: DateFormatter.Style) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.timeZone = timeZone
    dateFormatter.dateStyle = .none
    dateFormatter.timeStyle = timeStyle
    return dateFormatter.string(from: date)
}

let es = timeString(date: absTime, timeZone: edinburgh, timeStyle: .full)
let nycs = timeString(date: absTime, timeZone: newYork, timeStyle: .full)
print(es) // 12:44:10 AM Greenwich Mean Time
print(nycs) // 7:44:10 PM Eastern Standard Time

如果您想使您的应用程序国际化,您可以继续并开始使用 Locale,但我将其留作练习!

p.s。这些是不是所有概念 - 请参阅here

p.p.s。另见 this answer and (均不重复)