Работа с датами и временем в Swift: полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Работа с датами и временем в Swift: от основ до продвинутых техник

Работа с датами и временем — одна из ключевых задач в разработке приложений для iOS и macOS. Swift предоставляет мощный и гибкий набор инструментов для этой цели: Date, DateFormatter, Calendar, DateComponents и TimeInterval. В этой статье мы подробно разберем каждый из них, покажем практические примеры и научимся решать типовые задачи, такие как форматирование дат, вычисление разницы во времени, работа с часовыми поясами и календарями.

1. Основы: класс Date и TimeInterval

Базовым типом для представления момента времени является Date. Он хранит количество секунд, прошедших с 1 января 2001 года 00:00:00 UTC (эталонная дата для Apple).

Создание и сравнение дат:

import Foundation

// Текущая дата и время
let now = Date()
print("Сейчас: \(now)")

// Дата на основе временного интервала (120 секунд от текущего момента)
let futureDate = Date(timeIntervalSinceNow: 120)
print("Через 2 минуты: \(futureDate)")

// Дата на основе фиксированного интервала от эталонной даты
let specificDate = Date(timeIntervalSinceReferenceDate: 3600 * 24 * 365) // 1 год от 2001 года
print("Примерная дата: \(specificDate)")

// Сравнение дат
if now < futureDate {
    print("Текущая дата раньше будущей")
}

TimeInterval — это просто псевдоним для Double, представляющий количество секунд. Он используется для вычисления разницы между датами:

let startDate = Date()
sleep(2) // Имитация задержки
let endDate = Date()

let elapsed: TimeInterval = endDate.timeIntervalSince(startDate)
print("Прошло \(elapsed) секунд") // Выведет ~2.0

// Обратная операция
let minutes: TimeInterval = 5 * 60
let fiveMinutesLater = Date(timeInterval: minutes, since: startDate)

2. Форматирование дат с DateFormatter

Чтобы отобразить дату пользователю в понятном виде, используется DateFormatter. Он поддерживает локализацию и множество стилей.

Базовое форматирование:

let formatter = DateFormatter()
formatter.locale = Locale(identifier: "ru_RU") // Русская локаль
formatter.timeZone = TimeZone.current       // Текущий часовой пояс

// Стандартные стили
formatter.dateStyle = .full
formatter.timeStyle = .short
print(formatter.string(from: Date())) // Например: "пятница, 24 февраля 2025 г., 14:30"

formatter.dateStyle = .medium
formatter.timeStyle = .none
print(formatter.string(from: Date())) // "24 февр. 2025 г."

Пользовательский формат:

formatter.dateFormat = "dd.MM.yyyy HH:mm"
print(formatter.string(from: Date())) // "24.02.2025 14:30"

// Парсинг строки в дату
let dateString = "25.12.2024 10:00"
if let parsedDate = formatter.date(from: dateString) {
    print("Распарсена дата: \(parsedDate)")
}

Важно: При парсинге всегда проверяйте, что date(from:) возвращает не nil. Неправильный формат строки или несоответствие локали приведет к ошибке.

3. Календарные вычисления: Calendar и DateComponents

Класс Calendar инкапсулирует информацию о календарной системе (григорианский, исламский, буддийский и т.д.) и позволяет выполнять сложные операции с датами. DateComponents используется для описания отдельных компонентов даты (год, месяц, день, час и т.д.).

Извлечение компонентов:

let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month, .day, .weekday], from: Date())

print("Год: \(components.year!)")
print("Месяц: \(components.month!)")
print("День: \(components.day!)")
print("День недели: \(components.weekday!)") // 1 - воскресенье, 2 - понедельник...

Создание даты из компонентов:

var dateComponents = DateComponents()
dateComponents.year = 2025
dateComponents.month = 3
dateComponents.day = 15
dateComponents.hour = 12
dateComponents.minute = 0

if let constructedDate = calendar.date(from: dateComponents) {
    print("Сконструированная дата: \(constructedDate)")
}

Сложение и вычитание временных промежутков:

let today = Date()

// Добавить 3 дня
if let threeDaysLater = calendar.date(byAdding: .day, value: 3, to: today) {
    print("Через 3 дня: \(threeDaysLater)")
}

// Добавить 2 месяца и 1 неделю
var addComponents = DateComponents()
addComponents.month = 2
addComponents.weekOfMonth = 1
if let futureDate = calendar.date(byAdding: addComponents, to: today) {
    print("Через 2 месяца и 1 неделю: \(futureDate)")
}

// Начало текущего месяца
if let startOfMonth = calendar.date(from: calendar.dateComponents([.year, .month], from: today)) {
    print("Начало месяца: \(startOfMonth)")
}

// Конец текущего месяца (последняя секунда)
if let endOfMonth = calendar.date(byAdding: DateComponents(month: 1, day: -1), to: startOfMonth) {
    print("Конец месяца: \(endOfMonth)")
}

Определение разницы между датами:

let birthday = DateComponents(calendar: calendar, year: 1990, month: 5, day: 20).date!
let ageComponents = calendar.dateComponents([.year, .month, .day], from: birthday, to: today)
print("Возраст: \(ageComponents.year!) лет, \(ageComponents.month!) месяцев, \(ageComponents.day!) дней")

4. Работа с часовыми поясами и ISO 8601

При работе с серверными данными часто используется формат ISO 8601 (например, "2025-02-24T14:30:00Z"). Для его корректной обработки нужно учитывать часовой пояс.

Форматтер для ISO 8601:

let isoFormatter = ISO8601DateFormatter()
isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] // Включаем миллисекунды

// Парсинг строки
let isoString = "2025-02-24T14:30:00.123Z"
if let isoDate = isoFormatter.date(from: isoString) {
    print("ISO дата: \(isoDate)")
}

// Обратное преобразование
let nowDate = Date                

Блоги

Рекомендаций по книгам