在Swift中添加时间偏移量

16

我在数据库中有许多不同的演出时间,并希望通过创建偏移量,根据用户的时区显示正确的时间。

我首先从GMT转换为小时获取用户的时区偏移量。

NSTimeZone.localTimeZone().secondsFromGMT / 60 / 60

那么我需要找到一种方法将小时数添加到日期对象中.. 这就是我现在遇到困难的地方。

let formatter = NSDateFormatter()
    formatter.dateFormat = "HH:mm"

    let date = formatter.dateFromString(timeAsString)
    println("date: \(date!)")

然后我从日期创建一个字符串,用于标签,以便轻松阅读带有上午/下午的时间。

    formatter.dateFormat = "H:mm"
    formatter.timeStyle = .ShortStyle
    let formattedDateString = formatter.stringFromDate(date!)
    println("formattedDateString: \(formattedDateString)")

我似乎无法弄清如何添加/减去小时。我已经将字符串拆分了,但有时会出现负数,并且无法正常工作。也许我做错了什么。

感谢任何帮助。

Keith

3个回答

20

如果您想将以GMT格式存储的演出时间转换为用户本地时区并显示,您不应该手动调整NSDate/Date对象。您应该只是使用适当的时区和格式化程序。例如,在Swift 3中:

let gmtTimeString = "5:00 PM"

let formatter = DateFormatter()
formatter.dateFormat = "h:mm a"
formatter.timeZone = TimeZone(secondsFromGMT: 0)            // original string in GMT
guard let date = formatter.date(from: gmtTimeString) else {
    print("can't convert time string")
    return
}

formatter.timeZone = TimeZone.current                       // go back to user's timezone
let localTimeString = formatter.string(from: date)

或者在 Swift 2 中:

let formatter = NSDateFormatter()
formatter.dateFormat = "h:mm a"
formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)  // original string in GMT
let date = formatter.dateFromString(gmtTimeString)

formatter.timeZone = NSTimeZone.localTimeZone()        // go back to user's timezone
let localTimeString = formatter.stringFromDate(date!)

"你不应该手动调整NSDate对象" - Gold! - TruMan1

6
我会使用dateByAddingTimeInterval函数来添加和减去小时数。在dateFormat字符串中添加"a"以打印上午或下午。
var showTimeStr = "00:00 PM" //show time in GMT as String
let formatter = NSDateFormatter()
formatter.dateFormat = "hh:mm a"
let showTime = formatter.dateFromString(showTimeStr)
showTime.dateByAddingTimeInterval(3600) //Add number of hours in seconds, subtract to take away time
showTimeStr = formatter.stringFromDate(showTime)

1
谢谢你的回复。你所提供的代码基本可行,我只需添加可选项即可。现在我正在尝试将offset放置在你写的3600处,像这样:let offsetTime = NSTimeZone.localTimeZone().secondsFromGMT。但是我得到了“Int不可转换为NSTimeInterval”的提示,有没有一种强制类型转换的方法? - Keith
谢谢。如果它起作用,请点赞并选择为正确答案。转换代码:let offsetTime = Int(NSTimeZone.localTimeZome().secondsFromGMT)。这样做可以工作,但请注意它会截断时间间隔(即83.96748变成83而不是84)。如果您想四舍五入再转换,则此帖子的答案:https://dev59.com/CGgu5IYBdhLWcg3wuJWF 将对您有所帮助。 - Blake Morgan
实际上它只减去了7分钟,而且那个链接在Swift中并不真正起作用,除非我做错了什么。 - Keith
我错了。我误读了你的错误信息。这是正确的代码:let offsetTime = NSTimeZone.localTimeZone().secondsFromGMT showTime!.dateByAddingTimeInterval(NSTimeInterval(offsetTime))。你需要将offsetTime强制转换为NSTimeInterval类型。 - Blake Morgan

1

这是我的最终代码,结合了b.Morgans的答案。我相信现在一切都正常工作了。

let offsetTime = NSTimeInterval(NSTimeZone.localTimeZone().secondsFromGMT)

var showTimeStr = "05:00 PM" //show time in GMT as String
let formatter = NSDateFormatter()
formatter.dateFormat = "h:mm a"
let showTime = formatter.dateFromString(showTimeStr)
let finalTime = showTime?.dateByAddingTimeInterval(offsetTime) //Add number of hours in seconds, subtract to take away time
showTimeStr = formatter.stringFromDate(finalTime!)

1
这种方法通常可以得到正确的结果,但它掩盖了对NSDate对象的基本误解。例如,使用此代码,showTime变量不是格林威治标准时间下的下午5点,而是您所在时区下的下午5点(对于我来说,在纽约,下午5点是格林威治标准时间下的晚上10点)。当然,在finalTime中,您会纠正这个错误,将晚上10点的格林威治标准时间替换为下午5点的格林威治标准时间,然后再次使用格式化程序将其显示为字符串,就可以在您所在的时区正确地显示下午5点的格林威治标准时间(即纽约的中午12点)。这是不必要的混淆(如果您开始使用完整的日期字符串,有时会相差24小时)。 - Rob
非常感谢你,Rob。这很有道理,我想以正确的方式进行操作,避免混淆。 - Keith
是的,实际上我也在使用日期。我基本上在数据库中有一个单独的时间字段和一个单独的日期字段,例如2014-01-01。但也许我应该同时使用两者,并且我正在设置数据库内容,以便在需要之前可以调整格式。所以,基本上任何最好的方法都可以,最终我需要在应用程序中将日期作为一个标签,时间作为另一个标签。谢谢。 - Keith
是的,我应该更加深入地思考一下,最初我只考虑了美国时间。我想现在涉及到日期,这将是完全不同的问题。 - Keith
让我们在聊天中继续这个讨论。点击此处进入聊天室 - Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接