Строка Swift DateFormatter, загруженная из байтов, не разбирающих в правильном формате - PullRequest
2 голосов
/ 05 февраля 2020

Я загружаю строку из байтового массива в Swift, используя следующий код

let bytes = data[position...position + length]
guard let let dateString = String(bytes: bytes, encoding: .utf8)
    else {return}

Это дает мне правильную строку, например "20160714".

Использование DateFormatter Затем я пытаюсь проанализировать дату из строки следующим образом:

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYYMMdd"
let date = dateFormatter.date(from: dateString)

Этот должен работать, но date всегда nil. Когда я пытаюсь сделать то же самое на игровой площадке со строковым литералом (let dateString = "20160714"), он работает как положено, я думаю, что это как-то связано с кодировкой.

Любая помощь очень ценится.

РЕДАКТИРОВАТЬ: я пробовал как YYYY, так и yyyy в течение года, оба возвращают nil

Стоит также отметить, что байтовый массив получается при загрузке файла в память с использованием

guard let data = try? NSData(contentsOfFile: urlString, 
                             options: .alwaysMapped)
    else {fatalError("Invalid file")}

. по запросу @vadian печать Data(bytes) as NSData в консоли дает следующий вывод

{length = 8, bytes = 0x3230313630373134}

Ответы [ 4 ]

0 голосов
/ 05 февраля 2020

Сначала преобразовать байты в строку, затем преобразовать ее в действительную дату.

let bytes = data [position ... position + length] let dateString = NSString (bytes: bytes !, length: data! .Count, кодировка: NSUTF8StringEncoding)

let dateFormatter = DateFormatter ()

dateFormatter.dateFormat = "YYYYMMdd"

let date = dateFormatter.date (от: dateString)

0 голосов
/ 05 февраля 2020

Код, который вы написали, верен. Также его преобразование в объект Date. Попробуйте напечатать дату на консоли.

let dateString = "20160714"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYYMMdd"
let date = dateFormatter.date(from: dateString)

Просто преобразуйте объект даты в нужный вам формат строки (т. Е. Гггг / мм / дд)

0 голосов
/ 05 февраля 2020

Попробуйте проанализировать dateString с ISO8601DateFormatter (требуется iOS 10.0+, tvOS 10.0+ или macOS 10.12 +):

let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = [.withYear, .withMonth, .withDay]
let date = dateFormatter.date(from: dateString)

Протестировано с Swift 5.1.3 / Xcode 11.3.1 .

0 голосов
/ 05 февраля 2020
let dateString = String(bytes: bytes, encoding: .'t)

Это дает мне правильную строку

НЕТ, это дает вам Optional<String>

, поэтому компилятор не будет компилировать

let date = dateFormatter.date(from: dateString)

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

ОК, ОБНОВИТЬ с некоторым примером, где увидеть ошибку не так просто. Попробуйте это на игровой площадке и посмотрите, что он печатает!

let str = "0170101"
var data = Data(str.utf8)
// this makes a trouble
data[0] = UInt8(1)
let dateString = String(bytes: data[0 ..< data.count], encoding: .utf8)

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYYMMdd"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")

let date = dateFormatter.date(from: dateString ?? "")

let strd = "170101"
let date2 = dateFormatter.date(from: strd)

print(dateString ?? "", date)
print(strd, date2)

и он печатает

170101 nil
170101 Optional(2016-12-31 23:00:00 +0000)

Вы ожидаете этого? Попробуйте найти ошибку в другом месте вашего кода ...

И посмотрите, как она отображает дату, если она выглядит действительной. Интересно, не правда ли?

Cjange первая строка для

let str = "020170101"

, и она печатает

20170101 nil
20170101 Optional(2016-12-31 23:00:00 +0000)
...