Функция Swift Date не работает должным образом - PullRequest
0 голосов
/ 09 октября 2018

Я пытаюсь выяснить разницу между двумя датами в секундах, используя Swift 4.1.Это код, который я использую,

func getDurationInSeconds(date1 :Date) -> Int{
    guard let durationInSeconds = Calendar.current.dateComponents([.second], from: Date(), to: date1).second else {
            return 0
    }
    return durationInSeconds
}

Функция для генерации даты1 с 2018-10-09T18: 19: 00Z

func dateFromString(stringDate:String) -> Date? {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
        dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") as Locale?
        let date = dateFormatter.date(from: stringDate)
        return date
    }

Дата всегда возвращается назад на час меньше моеготекущее время устройства, поэтому расчет не работает, как ожидалось.Если мое текущее время устройства равно 16:34, функция Date () возвращает его как 15:34.

Я видел, что Date () возвращает время в UTC, не основанное на моем часовом поясе.

В настоящий момент, если я передаю дату 09/10/2018 14: 25: 00 и текущее время устройства: 09/10/2018 14: 20: 00 .Я ожидаю, что эта функция вернет значение 300, которое составляет 60 * 5-минутную разницу между двумя датами .

Но я получаю обратно значение 3900 , котороепотому что функция даты возвращает дату как

09/10/2018 13:20:00 вместо 14: 20

.Таким образом, продолжительность составит 1 час + разница в 300 секунд.

Включая пример вывода с консоли Xcode, время выполнения моего кода на моем устройстве было 2018-10-09 17: 56: 28.565423

(lldb) po date1
▿ 2018-10-09 17:59:00 +0000
  - timeIntervalSinceReferenceDate : 560800740.0

(lldb) po durationInSeconds
3731

(lldb) po Date()
▿ 2018-10-09 16:57:04 +0000
  - timeIntervalSinceReferenceDate : 560797024.35021996

(lldb)

Но я не могу найти правильный способ найти правильную продолжительность между двумя периодами на основе моего текущего часового пояса.Как я могу это сделать?

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

Проблема не в том, что Дата () возвращает неправильное время. Date () всегда возвращает текущее время, которое на самом деле не основано на вашем (любом другом) местном часовом поясе.

Кажется, проблема в dateFormatter , которыйвы используете для генерации объекта Дата из строки даты.

Пожалуйста, попробуйте использовать следующие строки кода:

dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"

// Not necessary as the dateFormatter would take the device's timeZone to be the default.
dateFormatter.timeZone = Calendar.current.timeZone   

вместо:

dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"

Проблема с последним заключается в том, что вы указываете ' Z ' как часовой пояс с нулевым смещением (UTC).Таким образом, разница в 1 час от UTC на вашем устройстве вызывает это смещение.

И, передавая строку даты, убедитесь, что вы пропускаете 'Z' в конце (например, этодолжно быть похоже на 2018-10-09T18: 19: 00 ).

Обновленный код должен работать хорошо и возвращать ожидаемую разницу в секундах.

0 голосов
/ 09 октября 2018

Поскольку вы используете строку, которая представляет текущее время в вашем часовом поясе, попробуйте вместо этого:

func getDurationInSeconds(date1: Date) -> Int {
    return Int(-date1.timeIntervalSinceNow + TimeZone.current.daylightSavingTimeOffset(for: date1))
}

Используется свойство и это method.

Или если вы хотите учесть разницу часовых поясов с UTC в dateFromString(stringDate:):

func getDurationInSeconds(date1: Date) -> Int {
    return Int(-date1.timeIntervalSinceNow)
}

func dateFromString(stringDate:String) -> Date? {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
    dateFormatter.locale = Locale(identifier: "en_US_POSIX")
    let date = dateFormatter.date(from: stringDate)! //I am force-unwrapping for brevity
    let adjustedDate = date.addingTimeInterval(-TimeZone.current.daylightSavingTimeOffset(for: date))
    return adjustedDate
}

Test

Я нахожусь в UTC + 1 час часовой пояс:

let str = "2018-10-09T19:50:00Z"    //"2018-10-09T19:50:00Z"
let date1 = dateFromString(stringDate: str)! //"Oct 9, 2018 at 7:50 PM"
Date()         //At the time of testing this it is "Oct 9, 2018 at 7:53 PM"
getDurationInSeconds(date1: date1)  //213, which is 3 minutes and 33 seconds
...