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

时间:2017-02-11 13:48:02

标签: ios swift nsdate nsdatecomponents

我有两个NSDate,它们是从UTC日期开始的。 让我们打电话给他们(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 String" Asia / Shanghai" secondTimeZone String" America / Los_Angeles"

所以日差是-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

3 个答案:

答案 0 :(得分:3)

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

我做了一些游戏,并提出了适用于同年的日期的代码:

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)

我正在使用纽约和新西兰的Aukland作为我的时区,因为截至撰写本文时,这些区域位于不同的日期。

截至目前(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)

为新西兰和纽约市提供相同的价值。我不确定为什么。

编辑:

好的,我做了一些实验并得到了有效的代码。我所做的是使用每次设置为本地时区的日历将两个日期转换为月/日/年日期组件。然后我使用方法dateComponents(_:from:to:)计算这两个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

在撰写本文时,给出了1天的差异1.由于我们使用的是dateComponents(_:from:to:)函数,因此需要花费数学来计算2个月/日/年之间的天数差异{{ 1}}。

答案 1 :(得分:1)

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

如果您有日期,请记下它们之间的天数。不要担心时区。

一般:

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

应该足够了。

答案 2 :(得分:0)

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