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)!)
}
我从字符串生成一个 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
将考虑闰秒、闰时等因素
但正如
你问错问题了。这就是所谓的 "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)!)
}