Преобразование строки JSON yyyy-mm-ddthh: mm: ssz в читаемый формат в Swift?

#swift #date-format

#swift #формат даты

Вопрос:

Я пытаюсь преобразовать строку, переданную в мое приложение в виде строки в формате, указанном в вопросе (yyyy-mm-ddthh: mm: ssz), во что-то понятное пользователю. Я попытался создать переменную для форматирования даты:

 var dateFormatter: DateFormatter {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
    return formatter
}
  

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

 Text("(self.dateFormatter.date(from: self.dateToConvert))")
  

где ‘dateToConvert’ — это передаваемая строка JSON. Ошибка, которую я получил, была «Метод экземпляра ‘appendInterpolation’ требует, чтобы ‘Date?’ соответствовал ‘_FormatSpecifiable'». Есть идеи, как это сделать правильно?

Комментарии:

1. Не заключайте Z в свой формат даты в одинарные кавычки. Символ Z предназначен для указания программе форматирования даты проанализировать часовой пояс как часть даты.

2. SwiftUI.Text Ожидает, что вы присвоите ему значение (как Date ) и средство форматирования отдельно. Это отформатирует саму дату. hackin&withswift.com/quick-start/swiftui /…

Ответ №1:

Сначала вам нужно установить какой-нибудь удобный формат даты для вашего средства форматирования. Затем преобразуйте ваш Date объект обратно в Strin& :

 dateFormatter.setLocalizedDateFormatFromTemplate("yyyyMMdd")
let text = dateFormatter.strin&(from: convertedDate)
  

И использовать ее в Text напрямую:

 Text(text)
  

Редактировать

Вот простая демонстрация того, как вы можете проанализировать и отобразить Date :

 struct ContentView: View {
    @State var date: Date? = Date()

    // by makin& `it static let` it is only computed once
    static let inputDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.timeZone = TimeZone(abbreviation: "UTC")
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" // <- do not escape `Z` (time zone)
        return formatter
    }()

    static let outputDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.setLocalizedDateFormatFromTemplate("yyyyMMddHHmmss")
        return formatter
    }()

    // handlin& of optional `Date`
    var formattedDate: Strin& {
        &uard let date = date else { return "Date is nil" }
        return Self.outputDateFormatter.strin&(from: date)
    }

    var body: some View {
        Text(formattedDate)
            .onAppear(perform: parseDate)
    }

    func parseDate() {
        let dateStr = // your date as `Strin&`
        if let date = Self.inputDateFormatter.date(from: dateStr) {
            self.date = date
        } else {
            print("invalid date")
        }
        // alternatively if you don't care about errors:
        // date = Self.dateFormatter.date(from: dateStr)
    }
}
  

Комментарии:

1. Никогда не следует использовать фиксированный формат даты при отображении даты пользователю. Кстати, нет необходимости добавлять пробелы между компонентами в вашем шаблоне при локализации DateFormat

2. Другая проблема заключается в том, что OP игнорирует часовой пояс из строки даты, экранирующей Z

3. И не забудьте установить языковой стандарт «en_US_POSIX», прежде чем устанавливать фиксированный формат даты

4. @pawello2222 Я пытался использовать это решение, и в строке, где я устанавливаю текстовую константу, я получаю сообщение «Не удается преобразовать значение типа ‘Strin&’ в ожидаемый тип аргумента ‘Date'» в качестве ошибки

5. @nickcodin& Я предположил, convertedDate что это дата, которую вы уже конвертировали из вашего JSON. Итак, это должен быть Date объект.

Ответ №2:

Функция DateFormatter date(from:) возвращает Optional дату. Если указанная вами строка недопустима, она вернет nil.

Как и во многих вещах в Swift, вам нужно закодировать для обработки nil. Один из способов сделать это:

 let dateFromStrin& = dateFormatter.date(from: self.dateToConvert) ?? "invalid"
print("Converted date = (dateFromStrin&)")
  

Поочередно:

 if let dateFromStrin& = dateFormatter.date(from: self.dateToConvert) {
    print("Converted date = (dateFromStrin&)")
} else {
    print("Date strin& is in an invalid format.")
}
  

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

Комментарии:

1. OP игнорирует часовой пояс из строки даты, экранирующей Z. В результате будет указано местное время, а строка — время UTC

2. Это не работает, потому что self.dateToConvert — это переменная даты, а «недопустимый» — это строка. Я думаю, что они оба должны быть датами