Как распарсить и создать дату/время с дробными секундами и UTC в формате ISO 8601 / RFC 3339 в Swift?
Решение с использованием ISO8601DateFormatter (iOS 10+)
Начиная с iOS 10, Apple представила ISO8601DateFormatter, который специально разработан для работы с форматом ISO 8601. Однако по умолчанию он не поддерживает дробные секунды. Но это можно легко исправить с помощью опции .withFractionalSeconds.
import Foundation
// Пример строки с дробными секундами
let dateString = "2024-03-15T14:30:45.123Z"
// Создаём форматтер
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
// Парсинг строки в Date
if let date = formatter.date(from: dateString) {
print("Успешно распарсено: \(date)")
// Обратное преобразование Date в строку
let outputString = formatter.string(from: date)
print("Строка для отправки: \(outputString)")
} else {
print("Ошибка парсинга")
}
Поддержка разной точности дробных секунд
Этот код автоматически обрабатывает дробные секунды любой точности (от 1 до 6 знаков):
- "2024-03-15T14:30:45.1Z" — 1 знак
- "2024-03-15T14:30:45.12Z" — 2 знака
- "2024-03-15T14:30:45.123456Z" — 6 знаков
Важные замечания
- Опция
.withFractionalSecondsдоступна с iOS 11 / macOS 10.13 и новее - Форматтер автоматически использует часовой пояс UTC (буква Z в конце строки)
- При обратном преобразовании в строку, дробные секунды будут содержать 3 знака (миллисекунды)
- Если нужно другое количество знаков, используйте
DateFormatter(см. альтернативный ответ)
Полный пример с обработкой ошибок
func parseISO8601Date(from string: String) -> Date? {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
return formatter.date(from: string)
}
func formatISO8601Date(_ date: Date) -> String {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
return formatter.string(from: date)
}
// Использование
if let date = parseISO8601Date(from: "2024-03-15T14:30:45.123456Z") {
print(formatISO8601Date(date)) // "2024-03-15T14:30:45.123Z"
}
Почему это лучший подход?
- Надёжность: Специализированный форматтер для ISO 8601
- Простота: Минимум кода, нет необходимости вручную задавать маску
- Совместимость: Поддержка различных вариантов ISO 8601 (с Z, с часовым поясом, без)
- Производительность: Оптимизирован Apple для работы с датами
Альтернативное решение с DateFormatter
Если вам нужен полный контроль над форматом (например, другое количество знаков после точки), используйте классический DateFormatter с правильной маской:
let dateString = "2024-03-15T14:30:45.123Z"
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(abbreviation: "UTC")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
if let date = formatter.date(from: dateString) {
print("Date: \(date)")
// Обратное преобразование
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let output = formatter.string(from: date)
print(output) // "2024-03-15T14:30:45.123Z"
}
Важные моменты
- Всегда устанавливайте
localeвen_US_POSIXдля стабильной работы - Явно указывайте
timeZone= UTC - Маска
SSS— ровно 3 цифры миллисекунд. Для другого количества используйте соответствующее количество S - Этот метод не сможет обработать 6 знаков (микросекунды) — для этого нужен
ISO8601DateFormatter
Когда использовать этот подход?
- Когда нужно строго определённое количество знаков после точки
- Для совместимости со старыми версиями iOS (до iOS 10)
- Когда нужен нестандартный формат (например, без буквы Z, а с +00:00)
Ответов пока нет.
Войдите чтобы оставить ответ