#ios #swift
Вопрос:
У меня есть строка, которую я получаю с сервера, которая выглядит так:
You blocked until 2022-01-01T11:00:00.350Z
И теперь я хочу преобразовать его в удобочитаемую дату, например
2022-01-01 11:00
Для этого я сначала попытался найти дату:
let types: NSTextCheckingResult.CheckingType = [.date]
if let detector = try? NSDataDetector(types: types.rawValue) {
let range = NSMakeRange(0, message.count)
let matches = detector.matches(in: message,
options: NSRegularExpression.MatchingOptions(rawValue: 0),
range: range)
if !matches.isEmpty {
for match in matches {
print(match.date)
let aSubstring = NSString(string: message).substring(with: match.range)
print(aSubstring)
}
}
}
Так что в результате match.date
меня вернули 2022-01-01 11:00:00 0000
, но результат aSubstring
есть until 2021-08-02T11:38:10.214Z
.
Поэтому мне любопытно, почему он включается until
в подстроку и как я могу этого избежать?
Комментарии:
1. @мэтт, спасибо тебе! Не могли бы вы, пожалуйста, помочь мне с регулярным выражением для этой
2022-01-01T11:00:00.350Z
строки? Я так плохо разбираюсь в регулярных выражениях и не могу открыть еще один вопрос SO в течение следующих 90 минут. Я была бы так благодарна!2. На самом деле, если это всегда последнее слово фразы, вам вообще не нужно регулярное выражение или поиск.
Ответ №1:
Возможное решение состоит в том, чтобы извлечь строку ISO8601, опуская секунды, дробные секунды и часовой пояс с помощью регулярного выражения, а затем получить первые 10 (дата) и последние 5 символов (время).
let string = "You blocked until 2022-01-01T11:00:00.350Z"
if let range = string.range(of: "\d{4}-\d{2}-\d{2}T\d{2}:\d{2}", options: .regularExpression) {
let trimmedString = String(string[range])
let humanReadable = "(trimmedString.prefix(10)) (trimmedString.suffix(5))"
print(humanReadable) // 2022-01-01 11:00
}
Однако есть одно предостережение: дата указана в UTC. Если вы хотите, чтобы дата отображалась в текущем часовом поясе, вам необходимо использовать форматер даты (на самом деле два).
let string = "You blocked until 2022-01-01T11:00:00.350Z"
if let range = string.range(of: "\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}", options: .regularExpression) {
let trimmedString = String(string[range]) "Z"
let inputFormatter = ISO8601DateFormatter()
if let date = inputFormatter.date(from: trimmedString) {
let outputFormatter = DateFormatter()
outputFormatter.locale = Locale(identifier: "en_US")
outputFormatter.dateFormat = "yyyy-MM-dd HH:mm"
let humanReadable = outputFormatter.string(from: date)
print(humanReadable)
}
}
Ответ №2:
если часть даты находится в конце строки, то вы могли бы попробовать что-то более сложное, но выполнимо. Что-то вроде этого:
struct ContentView: View {
@State var txt = ""
func humanDate(_ str: String) -> String? {
// convert the string to a date
let dateFormatter1 = DateFormatter()
dateFormatter1.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
// re-format the date to your liking
if let date = dateFormatter1.date(from: str) {
let dateFormatter2 = DateFormatter()
dateFormatter2.dateFormat = "yyyy-MM-dd HH:mm"
// dateFormatter2.dateFormat = "yyyy MMMM EEEE HHa:mm" // even more human readable
return dateFormatter2.string(from: date)
} else {
return nil
}
}
var body: some View {
Text(txt).onAppear {
let inputString = "You blocked until 2022-01-01T11:00:00.350Z"
if let dateStr = inputString.split(separator: " ").last {
if let theDate = humanDate(String(dateStr)) {
print("n----> " theDate "n")
txt = theDate
}
}
}
}
}