Дата и время в мобильной разработке: что это такое, какие форматы и как работать

Автор: IT Sectr Опубликовано: 2026-07-22 Время чтения: 11 мин

Дата и время в мобильной разработке — одна из ключевых тем в мобильной инженерии. iOS использует DateFormatter и ISO8601DateFormatter, Android — DateTimeFormatter и LocalDate из java.time. По данным Android Developer Docs, правильный выбор мобильного API для форматирования даты и времени напрямую влияет на производительность и корректность отображения в разных часовых поясах.

Главное

  • DateFormatter на iOS — мощный, но медленный при частом создании. Кэшируйте экземпляры или используйте ISO8601DateFormatter для формата ISO 8601.
  • DateTimeFormatter на Android — потокобезопасный форматтер из java.time. Заменил устаревший SimpleDateFormat начиная с API 26.
  • ThreeTenABP — бэкпорт java.time для Android API ниже 26. Добавляет LocalDate, ZonedDateTime и DateTimeFormatter на старых устройствах.
  • TimeZone — критически важен для конвертации UTC в локальное время. Храните время в UTC, отображайте в часовом поясе пользователя.
  • Unix Timestamp — стандартный формат хранения времени. Синхронизация через NTP гарантирует точность до миллисекунд.

Дата и время на iOS: DateFormatter и ISO8601DateFormatter

На iOS дата и время традиционно форматируются через DateFormatter из Foundation. Этот класс преобразует Date в строку и обратно, используя заданный шаблон, локаль и часовой пояс. Основная проблема DateFormatter — он не потокобезопасен и медленно создаётся, поэтому в мобильном коде экземпляры обязательно кэшируют. Дата в мобильной разработке на iOS требует правильного форматтера.

DateFormatter и производительность

Создание DateFormatter занимает около 1 миллисекунды из-за парсинга шаблона dateFormat, загрузки локали и определения часового пояса. При форматировании списка из сотен дат многократное создание приводит к заметным лагам в UI. Решение — создавать форматтер один раз на весь экран и переиспользовать. Для многопоточного доступа используйте синхронизацию через DispatchQueue.

swift
import Foundation

// Кэшированный DateFormatter — создаётся один раз
private let dateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateFormat = "dd.MM.yyyy HH:mm"
    formatter.locale = Locale(identifier: "ru_RU")
    formatter.timeZone = TimeZone(identifier: "Europe/Moscow")
    return formatter
}()

// ISO8601DateFormatter — легковесная альтернатива
private let isoFormatter: ISO8601DateFormatter = {
    let formatter = ISO8601DateFormatter()
    formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
    return formatter
}()

let now = Date()
let formattedDate = dateFormatter.string(from: now)
// "01.07.2026 14:30"
let isoDate = isoFormatter.string(from: now)
// "2026-07-01T14:30:00.000Z"

Для формата ISO 8601 используйте ISO8601DateFormatter — он не требует указания шаблона и работает быстрее DateFormatter. На iOS 10+ этот класс предпочтительнее для работы с серверными датами. Для старых форматов оставляйте DateFormatter, но обязательно кэшируйте экземпляр как статическое свойство или синглтон.

Дата и время на Android: java.time и DateTimeFormatter

На Android дата и время обрабатываются через пакет java.time, доступный с API 26. Основные классы: LocalDate (только дата), LocalTime (только время), LocalDateTime (дата и время без часового пояса) и ZonedDateTime (с часовым поясом). DateTimeFormatter — потокобезопасный форматтер для мобильной платформы Android. Дата в мобильных приложениях форматируется через DateTimeFormatter и LocalDate без потери производительности.

LocalDate, ZonedDateTime и форматирование

LocalDate хранит дату без времени — идеально для дней рождения. ZonedDateTime хранит полную информацию с часовым поясом. DateTimeFormatter поддерживает предопределённые шаблоны (ISO_LOCAL_DATE, ISO_DATE_TIME) и кастомные через ofPattern. Все классы java.time иммутабельны и потокобезопасны, что исключает race conditions при работе в нескольких потоках.

kotlin
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.ZoneId

// Создание и форматирование текущей даты
val today = LocalDate.now()
val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy")
val formatted = today.format(formatter)

// Работа с часовыми поясами
val utcTime = ZonedDateTime.now(ZoneId.of("UTC"))
val moscowTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/Moscow"))

DateTimeFormatter значительно производительнее SimpleDateFormat, поскольку не парсит шаблон при каждом вызове. Рекомендуется создавать константы форматтеров на уровне класса или объекта-компаньона. Для конвертации Unix Timestamp используйте Instant.ofEpochSecond, затем преобразуйте в LocalDateTime или ZonedDateTime через часовой пояс.

Часовые пояса: дата и время в мобильных приложениях и TimeZone

Корректная дата и время на экране пользователя зависят от правильной обработки часовых поясов. Дата и время в мобильна разработка для Android требует учёта часового пояса устройства. Золотое правило: храните время в UTC, конвертируйте в локальный часовой пояс только для отображения. iOS предоставляет TimeZone из Foundation, Android — ZoneId из java.time. Оба API для мобильных платформ поддерживают автоматическое определение текущего часового пояса устройства. Дата в мобильном приложении зависит от ZoneId и TimeZone.

Летнее время и идентификаторы IANA

Летнее время создаёт неоднозначность: один момент времени может быть представлен двумя разными локальными часами. java.time и Foundation учитывают DST автоматически. Используйте идентификаторы IANA (Europe/Moscow, America/New_York), а не аббревиатуры (MSK, EST) — аббревиатуры неоднозначны и игнорируют переход на летнее время.

swift
import Foundation

// Конвертация UTC в локальное время на iOS
func formatToLocalTime(utcDate: Date, timeZoneId: String) -> String {
    let formatter = DateFormatter()
    formatter.dateFormat = "dd.MM.yyyy HH:mm"
    formatter.timeZone = TimeZone(identifier: timeZoneId)
    return formatter.string(from: utcDate)
}

// Определение часового пояса устройства
let localTimeZone = TimeZone.current
let isDST = localTimeZone.isDaylightSavingTime()
let secondsFromGMT = localTimeZone.secondsFromGMT()

На Android используйте ZoneId.systemDefault() для получения часового пояса устройства. При конвертации UTC в локальное время создавайте ZonedDateTime с ZoneOffset.UTC и применяйте withZoneSameInstant. Для старых API без java.time используйте TimeZone.getDefault() и Calendar — но лучше сразу подключайте ThreeTenABP.

kotlin
import java.time.Instant
import java.time.ZonedDateTime
import java.time.ZoneId

// Конвертация Unix Timestamp в локальное время
fun toLocalDisplay(unixSeconds: Long): String {
    val instant = Instant.ofEpochSecond(unixSeconds)
    val local = instant.atZone(ZoneId.systemDefault())
    return local.format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"))
}

ThreeTenABP — дата и время для старых версий Android

ThreeTenABP — библиотека-адаптер, портирующая java.time на Android API ниже 26. Она предоставляет те же классы: LocalDate, LocalTime, ZonedDateTime, DateTimeFormatter, Instant. Если приложение поддерживает Android 5 или 6 (API 21-25), ThreeTenABP — единственный способ использовать современный мобильный API без перехода на устаревшие Calendar. Дата и время в мобильна разработка для старых устройств реализованы через эту библиотеку. Для старых устройств дата и время реализованы через ThreeTenABP.

Подключение и настройка ThreeTenABP

Библиотека требует инициализации в методе Application.onCreate() вызовом AndroidThreeTen.init(). Это загружает данные часовых поясов из assets. После инициализации API полностью идентичен java.time — код для API 26+ и для API 21+ будет одинаковым. Размер библиотеки около 400 КБ, что приемлемо для большинства мобильных приложений.

kotlin
import org.threeten.bp.LocalDate
import org.threeten.bp.format.DateTimeFormatter

// Инициализация в Application
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}

// API идентичен java.time
val today = LocalDate.now()
val formatted = today.format(DateTimeFormatter.ISO_LOCAL_DATE)

Производительность ThreeTenABP сопоставима с оригинальным java.time на современных устройствах. На старых устройствах возможна задержка при первом вызове из-за загрузки данных часовых поясов. Мигрируйте существующий код с Calendar на ThreeTenABP постепенно: заменяйте Date и Calendar на Instant и LocalDate в новых модулях, оставляя старый код без изменений.

Unix Timestamp и синхронизация времени через NTP

Unix Timestamp — количество секунд, прошедших с 1 января 1970 года 00:00 UTC. Это универсальный формат для хранения и обмена временем между сервером и клиентом. Однако время на устройстве может отличаться от реального из-за настроек пользователя. Для синхронизации используется NTP — протокол точного времени через UDP. Unix Timestamp — формат, в котором хранятся дата и время на сервере.

Получение Unix Timestamp и NTP-синхронизация

Date().timeIntervalSince1970 на iOS возвращает секунды с 1970 года. На Android System.currentTimeMillis() возвращает миллисекунды. Для точности используйте NTP: библиотека TrueTime для iOS и AndroidNtp для Android отправляют запрос к NTP-серверу и вычисляют смещение времени. Точность NTP — до 1-10 мс в локальной сети и 10-100 мс через интернет.

swift
import Foundation

// Получение Unix Timestamp на iOS
let seconds = Date().timeIntervalSince1970
let milliseconds = Int64(seconds * 1000)

// NTP-синхронизация с TrueTime
TrueTime.shared.start { result in
    switch result {
    case .success:
        let ntpTime = TrueTime.shared.now()
        print("Точное время: \(ntpTime)")
    case .failure(let error):
        print("Ошибка NTP: \(error)")
    }
}

Без синхронизации в мобильном приложении возможны ошибки: неверная отметка событий, рассинхронизация с сервером. Время в мобильной разработке синхронизируется через NTP однократно при старте приложения, после чего используется вычисленное смещение. Для критичных к точности мобильных приложений (финансы, логистика) протокол NTP обязателен перед отправкой данных на сервер.

Часто задаваемые вопросы

Почему DateFormatter медленный на iOS?

DateFormatter парсит шаблон форматирования, загружает локаль и определяет часовой пояс при каждом создании экземпляра. Кэшируйте форматтер как статическую константу или используйте ISO8601DateFormatter для ISO 8601 — он легче и быстрее.

Что использовать вместо SimpleDateFormat на Android?

DateTimeFormatter из пакета java.time — потокобезопасный и производительный. Доступен с API 26. Для старых версий используйте ThreeTenABP, который предоставляет идентичный API.

Как работать с датами до Java 8 на Android?

Подключите ThreeTenABP — бэкпорт java.time для Android API 21+. Инициализация через AndroidThreeTen.init() в Application.onCreate(). API полностью идентичен оригинальному java.time.

Нужно ли хранить время в UTC?

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

Как получить Unix Timestamp на iOS?

Date().timeIntervalSince1970 возвращает количество секунд с 1 января 1970 года. Для миллисекунд умножьте на 1000 и приведите к Int64. Для точной синхронизации используйте библиотеку TrueTime с NTP-сервером.

Итоги

  • DateFormatter на iOS — основной инструмент для форматирования даты и времени, требует обязательного кэширования экземпляров. ISO8601DateFormatter — более лёгкая альтернатива для ISO 8601.
  • DateTimeFormatter на Android — потокобезопасный форматтер из java.time для API 26+. LocalDate и ZonedDateTime — основные классы для работы с датами.
  • ThreeTenABP — единый API для всех версий Android. Подключайте для обратной совместимости с API 21-25. Код не отличается от java.time.
  • TimeZone и UTC — храните время в UTC, конвертируйте в локальный часовой пояс только для отображения. Используйте IANA-идентификаторы.
  • Unix Timestamp — универсальный формат для обмена временем между сервером и клиентом. Получайте через Date().timeIntervalSince1970 на iOS.
  • NTP синхронизация — обеспечивает точность времени до миллисекунд. TrueTime (iOS) и AndroidNtp (Android) — стандартные библиотеки.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект