تاریخ و زمان در توسعه موبایل: چیست، چه فرمت‌هایی و چگونه کار کنیم

نویسنده: IT Sectr منتشر شده: 2026-07-22 زمان مطالعه: 11 دقیقه

تاریخ و زمان در توسعه موبایل — یکی از موضوعات کلیدی در مهندسی موبایل است. iOS از DateFormatter و ISO8601DateFormatter استفاده می‌کند، Android از DateTimeFormatter و LocalDate از java.time استفاده می‌کند. به گفته Android Developer Docs، انتخاب صحیح API موبایل برای قالب‌بندی تاریخ و زمان به طور مستقیم بر عملکرد و نمایش صحیح در مناطق زمانی مختلف تأثیر می‌گذارد.

نکات اصلی

  • DateFormatter در iOS — قدرتمند، اما هنگام ایجاد مکرر کند. نمونه‌ها را کش کنید یا برای فرمت ISO 8601 از ISO8601DateFormatter استفاده کنید.
  • DateTimeFormatter در Android — قالب‌بند امن برای نخ از java.time. از API 26 جایگزین SimpleDateFormat منسوخ شد.
  • ThreeTenABP — backport از java.time برای Android API پایین‌تر از 26. LocalDate، ZonedDateTime و DateTimeFormatter را به دستگاه‌های قدیمی اضافه می‌کند.
  • TimeZone — برای تبدیل UTC به زمان محلی حیاتی است. زمان را در UTC ذخیره کنید، در منطقه زمانی کاربر نمایش دهید.
  • Unix Timestamp — فرمت استاندارد ذخیره‌سازی زمان. همگام‌سازی از طریق NTP دقت میلی‌ثانیه را تضمین می‌کند.

تاریخ و زمان در iOS: DateFormatter و ISO8601DateFormatter

در iOS، تاریخ و زمان به طور سنتی از طریق DateFormatter از Foundation قالب‌بندی می‌شوند. این کلاس با استفاده از یک الگو، locale و منطقه زمانی مشخص، Date را به رشته و بالعکس تبدیل می‌کند. مشکل اصلی DateFormatter — امن برای نخ نیست و به کندی ایجاد می‌شود، بنابراین در کد موبایل نمونه‌ها باید کش شوند. تاریخ در توسعه موبایل در iOS به قالب‌بند صحیح نیاز دارد.

DateFormatter و عملکرد

ایجاد DateFormatter حدود 1 میلی‌ثانیه طول می‌کشد به دلیل تجزیه الگوی dateFormat، بارگذاری locale و تعیین منطقه زمانی. هنگام قالب‌بندی فهرستی از صدها تاریخ، ایجاد مکرر باعث تأخیر قابل توجه در 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 را نگه دارید اما حتماً نمونه را به عنوان یک ویژگی استاتیک یا singleton کش کنید.

تاریخ و زمان در 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 تغییرناپذیر و امن برای نخ هستند، که شرایط رقابتی را هنگام کار در چندین نخ از بین می‌برد.

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 هر بار که یک نمونه ایجاد می‌شود، الگوی قالب‌بندی را تجزیه می‌کند، locale را بارگذاری می‌کند و منطقه زمانی را تعیین می‌کند. قالب‌بند را به عنوان یک ثابت استاتیک کش کنید یا برای ISO 8601 از ISO8601DateFormatter استفاده کنید — سبک‌تر و سریع‌تر است.

به جای SimpleDateFormat در Android از چه استفاده کنیم؟

DateTimeFormatter از بسته java.time — امن برای نخ و کارآمد. از API 26 در دسترس است. برای نسخه‌های قدیمی، از ThreeTenABP استفاده کنید که API یکسانی را فراهم می‌کند.

چگونه با تاریخ‌های قبل از Java 8 در Android کار کنیم؟

ThreeTenABP را اضافه کنید — backport از 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 از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه