Добавление смещения времени в Swift

У меня есть куча разных времен показа в базе данных, и я хочу отображать правильное время в зависимости от часового пояса пользователей, создавая смещение.

Я получаю смещение часового пояса пользователей от GMT и сначала конвертирую его в часы.

NSTimeZone.localTimeZone().secondsFromGMT / 60 / 60

Затем мне нужно найти способ добавить часы к объекту даты... вот где я борюсь.

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

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

Затем я создаю строку с датой для использования в метке, чтобы ее было легко читать с помощью AM / PM.

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

Я просто не могу понять, как добавить/вычесть часы. Я разделил строку, но иногда она становится отрицательной и не работает. Может быть, я говорю об этом неправильно.

Спасибо за любую помощь.

Кейт


person Keith    schedule 23.12.2014    source источник


Ответы (3)


Если вы хотите преобразовать время показа, которое хранится в виде строки в часовом поясе по Гринвичу, и вы хотите показать его в местном часовом поясе пользователя, вы не должны не вручную настраивать объекты 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)

Или в Свифт 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!)
person Rob    schedule 23.12.2014
comment
вам не следует вручную настраивать объекты NSDate - Gold! - person TruMan1; 09.02.2017

Я бы использовал dateByAddingTimeInterval для сложения и вычитания часов. Добавьте к строке dateFormat, чтобы напечатать am или pm.

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)
person Blake Morgan    schedule 23.12.2014
comment
Спасибо за ответ. То, что вы поставили, в значительной степени работает, мне пришлось просто добавить опции. Теперь я пытаюсь поместить смещение там, где у вас есть 3600 let offsetTime = NSTimeZone.localTimeZone().secondsFromGMT, но я получаю, что Int не конвертируется в NSTimeInterval. Есть ли способ применить это? - person Keith; 23.12.2014
comment
Спасибо. Пожалуйста, проголосуйте и выберите правильный ответ, если это сработало. Разыграть: let offsetTime = Int(NSTimeZone.localTimeZome().secondsFromGMT). Это сработает, но поймите, что это урежет интервал (т.е. 83,96748 станет 83, а не 84). Если вы хотите округлить, а затем бросить, то ответ на этот пост: stackoverflow.com/questions/11121459/ поможет вам. - person Blake Morgan; 23.12.2014
comment
На самом деле он вычитает только 7 минут, и эта ссылка на самом деле не работает быстро, если только я не делаю это неправильно. - person Keith; 23.12.2014
comment
Я ошибался. Я неправильно понял ваше сообщение об ошибке. Это будет правильный код: let offsetTime = NSTimeZone.localTimeZone().secondsFromGMT showTime!.dateByAddingTimeInterval(NSTimeInterval(offsetTime)). Вам нужно указать offsetTime как NSTimeInterval. - person Blake Morgan; 23.12.2014

Вот мой окончательный код в сочетании с ответом 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!)
person Keith    schedule 23.12.2014
comment
Таким образом вы часто получаете правильный результат, но это противоречит фундаментальному непониманию NSDate объектов. Например, в этом коде переменная showTime — это не 17:00 по Гринвичу, а 17:00 в вашем местном часовом поясе (для меня в Нью-Йорке 17:00 — это 22:00 по Гринвичу). Конечно, в finalTime вы обращаете эту ошибку, заменяя 22:00 по Гринвичу на 17:00 по Гринвичу, и когда вы затем используете средство форматирования для повторного отображения в виде строки, вы получаете правильное отображение 17:00 по Гринвичу в вашем местном часовом поясе (т.е. полдень здесь, в Нью-Йорке). ). Это излишне сбивает с толку (и если вы начнете использовать полные строки даты, вы иногда будете отключены на 24 часа). - person Rob; 23.12.2014
comment
Большое спасибо, Роб, это имеет смысл, и я хочу сделать это правильно и избежать путаницы. - person Keith; 23.12.2014
comment
Да, на самом деле я тоже использую дату. В основном у меня есть отдельное поле в базе данных для времени и отдельное поле даты, т.е. 2014-01-01. Но, возможно, мне следует использовать оба одновременно, и я настраиваю содержимое базы данных так, как мне нужно, чтобы я мог настроить форматирование и раньше. Так что да, в основном все, что работает лучше всего, и, в конце концов, мне нужна дата в качестве одной метки и время в качестве другой в приложении. Спасибо. - person Keith; 23.12.2014
comment
Да, я должен был больше подумать об этом, изначально я думал только о времени США. Я предполагаю, что теперь это был бы совершенно другой вопрос, связанный с датой. - person Keith; 23.12.2014
comment
Давайте продолжим обсуждение в чате. - person Rob; 23.12.2014