Дата і час у мобільній розробці: що це таке, які формати та як працювати

Автор: 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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект