SWIFT: 如何将小时添加到 NSDate 对象

SWIFT: How do I add hours to NSDate object

我从字符串生成一个 NSDate 对象。

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT")
let stringToDate = dateFormatter.dateFromString(dateFromService) // 2015-07-20 12:00:43 +0000

我从网络服务器得到这个字符串值。我需要修改个人设备时区。想添加小时这个 stringToDate 对象但不起作用

var addHours : Int = 2 // 2 hours will be added
var newDate = stringToDate.dateByAddingTimeInterval(addHours)

如果您经常这样做,请查看名为 SwiftMoment 的库(受同一个 .js 库启发),它允许您执行以下操作(以及更多!):

// Create date using moment library
let myDate = moment(myString)

// Add one hour
let dateWithAddedHour = myDate + 1.hours

Moment 是 NSDate 实例的包装器,而 Duration(这是您从 Int.hours、Int.minutes 等获得的)包装了 NSTimeInterval 值。

实施这个只需要一点时间! (双关语)。

使用NSCalendarComponents:

let calendar = NSCalendar.currentCalendar()
let newDate = calendar.dateByAddingUnit(
    .CalendarUnitHour, // adding hours
    value: 2, // adding two hours
    toDate: oldDate,
    options: .allZeros
)

使用 NSCalendar 将考虑闰秒、闰时等因素

但正如 指出的那样,简单地增加小时数绝对是错误的方法。两个时区并不总是相隔相同的时间。同样,当我们考虑夏令时时,情况尤其如此。 (例如,美国不会 start/end 与欧洲在同一天实行夏令时,而亚利桑那州甚至 也不 夏令时)。

你问错问题了。这就是所谓的 "XY Problem"。 你应该问 "How do I display a date string I get from a web server in the user's local time zone."

NSDate 表示不包含时区的抽象形式的 date/time。您将其转换为特定时区以供显示。不要尝试 add/subtract 小时到 NSDate 来偏移时区。这是错误的做法。

正确答案很简单。创建第二个日期格式化程序,不要将其时区设置为 GMT。它默认为用户的本地时区。

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT")
let date = dateFormatter.dateFromString(dateFromService) 

let outputDatedateFormatter = NSDateFormatter()
outputDatedateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
//leave the time zone at the default (user's time zone)
let displayString = outputDateFormatter.stringFromDate(date)
println("Date in local time zone = \(displayString)")

对于Swift3你可以使用这个函数:

//get next date by adding hours func  

getNewDateAfterAddingHours(hoursToAdd:NSInteger, oldDate:Date) -> Int64 {
    let calendar = Calendar.current
    let newDate = calendar.date(byAdding: .hour, value: hoursToAdd, to: oldDate)
    return Int64((newDate?.timeIntervalSince1970)!)
}