如何计算不同时区的两个 NSDate 对象之间的天数差异?

How to calculate days difference between two NSDate objects in different time zones?

我有两个从 UTC 日期启动的 NSDate。 让我们称他们为 (A & B)

我知道A代表中国的一天,B代表美国的一天。 (我知道时区。)如何计算两者之间的天数差异...?

我一直在用下面的方法,明显不对

class func daysDifferenceIn(firstDate: NSDate, firstTimeZone: String, secondDate: NSDate, secondTimeZone: String) -> Int {
    objc_sync_enter(self)

    let firstDateComponents = NSCalendar.CommonCalendar.componentsInTimeZone(NSTimeZone(name: firstTimeZone)!, fromDate: firstDate)
    let secondDateComponents = NSCalendar.CommonCalendar.componentsInTimeZone(NSTimeZone(name: secondTimeZone)!, fromDate: secondDate)
    NSCalendar.CommonCalendar.timeZone = NSTimeZone(name: firstTimeZone)!
    let firstCalDate = NSCalendar.CommonCalendar.dateFromComponents(firstDateComponents)
    NSCalendar.CommonCalendar.timeZone = NSTimeZone(name: secondTimeZone)!
    let secondCalDate = NSCalendar.CommonCalendar.dateFromComponents(secondDateComponents)
    objc_sync_exit(self)

    return firstCalDate!.numberOfDaysUntilDateTime(secondCalDate!)
}

func numberOfDaysUntilDateTime(toDateTime: NSDate, inTimeZone timeZone: NSTimeZone? = nil) -> Int {
    let calendar = NSCalendar.CommonCalendar
    if let timeZone = timeZone {
        calendar.timeZone = timeZone
    }

    var fromDate: NSDate?, toDate: NSDate?

    calendar.rangeOfUnit(.Day, startDate: &fromDate, interval: nil, forDate: self)
    calendar.rangeOfUnit(.Day, startDate: &toDate, interval: nil, forDate: toDateTime)

    let difference = calendar.components(.Day, fromDate: fromDate!, toDate: toDate!, options: [])

    return difference.day
}

我可以手动从 firstDateComponentssecondDateComponents 中减去日期分量,但我不想这样做,因为我必须寻找 31 和 28 等的边缘情况。 任何帮助表示赞赏。谢谢。

更新

第一个日期是 2017-02-10 16:15:00 +0000 第二个日期是 2017-02-11 03:20:00 +0000 都是 UTC。

firstTimeZone 字符串 "Asia/Shanghai" secondTimeZone 字符串 "America/Los_Angeles"

所以天差是-1天。基本上,我正在执行航班状态,您可以看到以下内容 link,因为航班在起飞前 1 天降落。当它从西向东飞时。

https://www.google.co.in/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=ua+890

还有日期组件的描述。

Printing description of firstDateComponents:
<NSDateComponents: 0x600000142310>
    Calendar: <CFCalendar 0x60000088b6d0 [0x10c5d3df0]>{identifier = 'gregorian'}
    TimeZone: Asia/Shanghai (GMT+8) offset 28800
    Era: 1
    Calendar Year: 2017
    Month: 2
    Leap month: no
    Day: 11
    Hour: 0
    Minute: 15
    Second: 0
    Nanosecond: 0
    Quarter: 0
    Year for Week of Year: 2017
    Week of Year: 6
    Week of Month: 2
    Weekday: 7
    Weekday Ordinal: 2
Printing description of secondDateComponents:
<NSDateComponents: 0x60000014b8f0>
    Calendar: <CFCalendar 0x60000049b620 [0x10c5d3df0]>{identifier = 'gregorian'}
    TimeZone: America/Los_Angeles (PST) offset -28800
    Era: 1
    Calendar Year: 2017
    Month: 2
    Leap month: no
    Day: 10
    Hour: 19
    Minute: 20
    Second: 0
    Nanosecond: 0
    Quarter: 0
    Year for Week of Year: 2017
    Week of Year: 6
    Week of Month: 2
    Weekday: 6
    Weekday Ordinal: 2

您尝试过使用 let interval = laterDate.timeIntervalSinceDate(earlierDate) 吗?这将 return 以秒为单位的两个日期之间的差异。

一个NSDate代表一个时刻。它没有时区。只有日期的字符串表示具有时区信息。

如果您有日期,只需计算它们之间的天数即可。不用担心时区问题。

通常:

let difference = calendar.components(.Day, fromDate: self, toDate: toDate!, options: [])
return difference.day

应该够了。

这是一个奇怪的案例。当在特定时区评估这些日期时,您正在寻找两个日期之间的日历日期差异。

我玩了一把,想出了适用于同一年日期的代码:

let date = Date()

guard let nycTimeZone = TimeZone(abbreviation: "EST"),
  let nzTimeZone = TimeZone(abbreviation: "NZDT") else {
    fatalError()
}
var nycCalendar = Calendar(identifier: .gregorian)
nycCalendar.timeZone = nycTimeZone
var nzCalendar = Calendar(identifier: .gregorian)
nzCalendar.timeZone = nzTimeZone

let now = Date()

let nycDayOfYear = nycCalendar.ordinality(of: .day, in: .year, for: now)

var nzDayOfYear = nzCalendar.ordinality(of: .day, in: .year, for: now)

我使用纽约和新西兰奥克兰作为我的时区,因为在撰写本文时,这些时区的日期不同。

截至目前(2017 年 2 月 11 日下午 12:00,美国东部标准时间 (UTC - 5) 以上代码给出

nycDayOfYear = 42

nzDayOfYear = 43

需要做一些工作才能跨年度进行计算。

奇怪的是,下面的代码:

var nzDayOfEra = nzCalendar.ordinality(of: .day, in: .era, for: now)
let nycDayOfEra = nycCalendar.ordinality(of: .day, in: .era, for: now)

为 NZ 和 NYC 提供相同的值。我不知道为什么。

编辑:

好的,我做了一些试验并得到了有效的代码。我所做的是使用每次都设置为本地时区的日历将两个日期转换为 month/day/year 日期组件。然后我使用一种方法 dateComponents(_:from:to:) 来计算这 2 DateComponents 之间的差异,以天为单位:

import UIKit

let date = Date()

guard let nycTimeZone = TimeZone(abbreviation: "EST"),
  let nzTimeZone = TimeZone(abbreviation: "NZDT") else {
    fatalError()
}
var nycCalendar = Calendar(identifier: .gregorian)
nycCalendar.timeZone = nycTimeZone
var nzCalendar = Calendar(identifier: .gregorian)
nzCalendar.timeZone = nzTimeZone

let now = Date()


let nycDateComponents = nycCalendar.dateComponents([.month, .day, .year], from: now)
let nzDateComponents = nzCalendar.dateComponents([.month, .day, .year], from: now)

let difference = Calendar.current.dateComponents([.day],
  from: nycDateComponents,
    to: nzDateComponents)

let daysDifference = difference.days

在撰写本文时,daysDifference 为 1。由于我们使用的是 dateComponents(_:from:to:) 函数,因此它负责计算 2 month/day/year 之间的天数差异DateComponents.