Date — یک ساختار Foundation است که یک لحظه خاص از زمان را مستقل از تقویم و منطقه زمانی نشان میدهد. این نوع تعداد ثانیههای سپری شده از تاریخ مرجع ۱ ژانویه ۲۰۰۱ (reference date) را ذخیره میکند و عملیات پایهای مقایسه و محاسبه فواصل زمانی را فراهم میکند. بر اساس Apple Developer Documentation (2025)، Date در تمام فریمورکهای اپل استفاده میشود: از UIKit و SwiftUI گرفته تا CloudKit و Core Data. درک عملکرد Date برای هر توسعهدهنده iOS ضروری است، زیرا بدون آن نمیتوان زمان را در برنامه مدیریت کرد.
مهمترین نکات
Date — یک نوع مقداری (value type) از فریمورک Foundation است که یک لحظه مطلق زمان را ثبت میکند. بر خلاف نمایشهای تقویمی (سال، ماه، روز)، Date به منطقه زمانی و سیستم تقویم وابسته نیست — این یک مقدار عددی محض از برچسب زمانی است.
نمایش داخلی Date یک TimeInterval است (نام مستعار برای Double) که تعداد ثانیهها را نسبت به تاریخ مرجع — ۱ ژانویه ۲۰۰۱ ساعت ۰۰:۰۰:۰۰ UTC — ذخیره میکند. اپل این تاریخ را به جای Unix epoch (سال ۱۹۷۰) برای سازگاری با سیستمهای قدیمی NeXTSTEP که iOS و macOS بر اساس آن ساخته شدهاند انتخاب کرد.
Date به عنوان نوع استاندارد زمان در تمام APIهای اپل استفاده میشود: UIDatePicker، DatePicker، UserDefaults، Codable، Core Data، CloudKit. بدون Date نمیتوان با برنامهها، تایمرها، رویدادهای تقویم، سریالسازی دادهها و هر عملیات مرتبط با زمان کار کرد.
Date با انواع تقویمی تفاوت دارد زیرا یک برچسب زمانی فیزیکی را نشان میدهد، نه یک مقدار قابل خواندن برای انسان. همان Date ممکن است در مناطق زمانی مختلف با تاریخهای تقویمی متفاوتی مطابقت داشته باشد. برای دریافت اجزاء (سال، ماه، روز) Date از طریق Calendar و DateComponents تبدیل میشود.
Date همچنین با DispatchTime که برای توزیع وظایف در Grand Central Dispatch استفاده میشود متفاوت است. DispatchTime نسبت به لحظه راهاندازی سیستم نسبی است، در حالی که Date یک برچسب مطلق است که میتوان آن را ذخیره، منتقل و بازیابی کرد.
Date() — سادهترین راه برای ایجاد یک شی با لحظه فعلی زمان است. مقداردهنده اولیه بدون آرگومان زمان دقیق فراخوانی را برمیگرداند. برای ایجاد تاریخ در گذشته یا آینده از TimeInterval و روش addingTimeInterval یا مقداردهی از یک Date موجود استفاده میشود.
برای ایجاد یک تاریخ دلخواه از اجزاء از ترکیب Calendar و DateComponents استفاده میشود. Calendar اجزاء قابل خواندن برای انسان (سال، ماه، روز، ساعت، دقیقه) را به Date تبدیل میکند. همچنین میتوان Date را از طریق ISO8601DateFormatter از یک رشته در قالب ISO 8601 یا از طریق DateFormatter از یک نمایش رشتهای دلخواه مقداردهی کرد.
Date.distantPast و Date.distantFuture — دو ویژگی ایستا که لحظات بینهایت دور گذشته و آینده را نشان میدهند. آنها به عنوان مقادیر مرزی در فیلتر کردن و مرتبسازی تاریخها در الگوریتمها استفاده میشوند.
import Foundation
// ایجاد Date با زمان فعلی
let now = Date()
print("Current time: \(now)")
// تاریخ پس از ۱ ساعت (۳۶۰۰ ثانیه)
let inOneHour = now.addingTimeInterval(3600)
// تاریخ از اجزاء
var components = DateComponents()
components.year = 2025
components.month = 12
components.day = 25
let christmas = Calendar.current.date(from: components)!
در مثال سه روش ایجاد Date نشان داده شده است: زمان فعلی، اضافه کردن بازه و ایجاد از طریق DateComponents. هر سه رویکرد یک مقدار از نوع Date را با دقت میلیثانیه برمیگردانند. Calendar.current از تقویم سیستم کاربر استفاده میکند — در دستگاههای اپل این معمولاً تقویم میلادی است.
TimeInterval — یک نام مستعار برای Double است که تعداد ثانیههای بین دو لحظه زمان را نشان میدهد. دقت TimeInterval به کسری از میلیثانیه میرسد که برای بیشتر کاربردها کافی است. مقدار منفی TimeInterval نشاندهنده گذشته نسبت به نقطه مرجع است.
Date از تمام عملگرهای استاندارد مقایسه پشتیبانی میکند: ==، <، >، <=، >=. Swift به طور خودکار TimeInterval داخلی مقادیر را مقایسه میکند. روش compare یک ComparisonResult با گزینههای .orderedSame، .orderedAscending، .orderedDescending برای مقایسه صریحتر برمیگرداند.
Date.distance(to:) — روشی که TimeInterval تا تاریخ مشخص شده را برمیگرداند. اگر تاریخ هدف در گذشته باشد، نتیجه منفی است. advanced(by:) یک تاریخ جدید با اضافه کردن TimeInterval مشخص شده به تاریخ فعلی ایجاد میکند. این روشها پروتکل Strideable را پیادهسازی میکنند و امکان استفاده از Date را در بازههای Range و ClosedRange فراهم میکنند.
let start = Date()
let end = start.addingTimeInterval(86400)
// مقایسه از طریق عملگرها
if start < end {
print("start is earlier")
}
// TimeInterval بین دو تاریخ
let interval: TimeInterval = end.timeIntervalSince(start)
print("Seconds: \(Int(interval / 60)) minutes")
// Using Date in range
let range = start...end
let mid = start.addingTimeInterval(43200)
if range.contains(mid) {
print("mid is between start and end")
}
TimeInterval برابر با ۸۶۴۰۰ معادل یک شبانهروز است. برای بازههای پیچیدهتر — هفتهها، ماهها، سالها — از Calendar و DateComponents استفاده کنید، زیرا این واحدها طول متغیری دارند (سالهای کبیسه، تغییر ساعت تابستانی). TimeInterval فقط برای فواصل ثابت بر حسب ثانیه قابل استفاده است.
Calendar — پلی بین Date و اجزاء قابل خواندن برای انسان است. Calendar Date را با در نظر گرفتن منطقه زمانی و locale به DateComponents (سال، ماه، روز، ساعت، دقیقه، ثانیه) تبدیل میکند. بدون Calendar نمیتوان سال یا ماه را از Date استخراج کرد — Date به دلیل ماهیت مطلق خود این اطلاعات را ندارد.
روش Calendar.component یک جزء را از Date استخراج میکند: سال، ماه، روز، ساعت، دقیقه، ثانیه، weekday، quarter. روش Calendar.dateComponents مجموعهای از اجزاء را در یک فراخوانی استخراج میکند — این کارآمدتر از فراخوانی component برای هر فیلد به صورت جداگانه است.
Calendar.isDateInToday، isDateInTomorrow، isDateInYesterday — روشهای مناسب برای بررسی تاریخهای نسبی. Calendar.dateInterval شروع و پایان دوره مشخص شده (روز، هفته، ماه، سال) را برمیگرداند. Calendar.compare تاریخها را با دقت جزء مشخص شده مقایسه میکند — برای مثال، سال بدون در نظر گرفتن ماه و روز.
let calendar = Calendar.current
// استخراج اجزاء
let year = calendar.component(.year, from: Date())
let month = calendar.component(.month, from: Date())
// Check relative date
if calendar.isDateInToday(someDate) {
print("Today!")
}
// شروع و پایان روز
let dayInterval = calendar.dateInterval(of: .day, for: Date())!
print("Day start: \(dayInterval.start)")
print("Day end: \(dayInterval.end)")
Calendar.current از تنظیمات سیستم کاربر — تقویم، منطقه زمانی و locale — استفاده میکند. برای تست یا محاسبات خاص میتوان Calendar با پارامترهای مشخص از طریق Calendar(identifier: .gregorian) ایجاد کرد و TimeZone مورد نظر را از طریق ویژگی timeZone تنظیم نمود.
DateFormatter — یک جزء اجباری است اگر Date باید به کاربر نمایش داده شود. DateFormatter Date را بر اساس قالب و locale مشخص شده به رشته تبدیل میکند. تبدیل مستقیم Date به رشته از طریق String(describing:) یک نمایش فنی با reference date و TimeInterval برمیگرداند — این برای کاربر طراحی نشده است.
رویکرد پایه استفاده از سبکهای از پیش تعیین شده dateStyle و timeStyle است. iOS از چهار سبک پشتیبانی میکند: .short، .medium، .long، .full. ترکیب سبکهای تاریخ و زمان امکان تنظیم انعطافپذیر نمایش را فراهم میکند. DateFormatter به طور خودکار بومیسازی را اعمال میکند: برای locale فارسی تاریخ در قالب \"۲۱ ژوئیه ۲۰۲۶\" نمایش داده میشود.
ISO8601DateFormatter — یک فرمتدهنده تخصصی برای ISO 8601، رایجترین قالب برای API و تبادل داده است. این فرمتدهنده سریعتر از DateFormatter کار میکند و به locale وابسته نیست، که آن را برای سریالسازی تاریخها در JSON ترجیحپذیر میکند.
// سبکهای از پیش تعیین شده
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
let userString = formatter.string(from: Date())
// ISO 8601 برای API
let isoFormatter = ISO8601DateFormatter()
let apiString = isoFormatter.string(from: Date())
// تجزیه از رشته
let parsed = isoFormatter.date(from: "2026-07-21T10:30:00Z")!
هنگام کار با DateFormatter مهم است که عملکرد را در نظر داشته باشید: ایجاد یک فرمتدهنده جدید عملیات پرهزینهای است. توصیه میشود فرمتدهنده را حافظهنهان (cache) کنید یا یک بار ایجاد کرده و مجدداً استفاده کنید. در ویژگیهای فرمتدهنده میتوان timeZone را تنظیم کرد — به طور پیشفرض از منطقه زمانی سیستم استفاده میشود، اما برای تاریخهای سرور اغلب TimeZone(identifier: \"UTC\") مورد نیاز است.
بیایید سناریوهای معمول کار با Date در یک برنامه iOS را بررسی کنیم. سناریوی اول — محاسبه سن کاربر از تاریخ تولد. دوم — تایمر شمارش معکوس تا یک رویداد. سوم — گروهبندی رکوردها بر اساس تاریخ برای نمایش به صورت بخشهای جدول.
Calendar.dateComponents با پرچم [.year] تفاوت بین دو تاریخ را محاسبه میکند. تنظیم صحیح منطقه زمانی حیاتی است — اگر timeZone در Calendar مشخص نشود، نتیجه ممکن است به دلیل عبور از نیمهشب در یک منطقه زمانی دیگر یک روز متفاوت باشد.
func calculateAge(from birthDate: Date) -> Int {
let calendar = Calendar.current
let now = Date()
let components = calendar.dateComponents(
[.year], from: birthDate, to: now
)
return components.year ?? 0
}
تایمر شمارش معکوس از طریق TimeInterval پیادهسازی میشود. تفاوت بین تاریخ هدف و تاریخ فعلی را محاسبه میکنیم، باقیمانده را بر حسب ثانیه میگیریم و به روزها، ساعتها، دقیقهها تبدیل میکنیم. برای بهروزرسانی منظم از Timer با بازه ۱ ثانیه استفاده میشود. ObservableObject با ویژگی @Published به SwiftUI اجازه میدهد به طور خودکار رابط را بهروزرسانی کند.
گروهبندی بر اساس تاریخ از طریق یک دیکشنری با کلید Date پیادهسازی میشود. Calendar.dateInterval(of: .day, for:) تاریخ را تا شروع روز نرمال میکند که امکان گروهبندی رکوردهای مربوط به یک روز را فراهم میکند. همان رویکرد برای هفتهها، ماهها و سالها نیز کار میکند — کافی است جزء را در dateInterval به .weekOfYear یا .month تغییر دهید.
| سناریو | API کلیدی | ویژگی |
|---|---|---|
| محاسبه سن | Calendar.dateComponents | timeZone را در نظر بگیرید |
| شمارش معکوس | Date.timeIntervalSince | Timer+Combine |
| گروهبندی تاریخها | Calendar.dateInterval | نرمالسازی تا روز |
| سریالسازی JSON | ISO8601DateFormatter | Locale تأثیر ندارد |
سوالات متداول
Date — یک نمایش داخلی از زمان بدون وابستگی به تقویم و locale است. رشته یک نمایش فرمتشده وابسته به تنظیمات کاربر است. Date را میتوان با دقت صد درصد مقایسه، سریالسازی و ریاضی پردازش کرد، در حالی که نمایش رشتهای همیشه نیاز به تجزیه از طریق فرمتدهنده دارد.
Date — یک برچسب زمانی مطلق (تعداد ثانیه از reference date) است که به منطقه زمانی وابسته نیست. منطقه زمانی زمینه نمایش است. همان Date در UTC و تهران همان لحظه فیزیکی را نشان میدهد اما به عنوان زمان تقویمی متفاوت نمایش داده میشود.
Date مستقیماً توسط Core Data به عنوان نوع ویژگی پشتیبانی میشود. Core Data به طور خودکار Date را در ذخیرهگاه سریالسازی میکند. برای پرسوجوهای با فیلتر بر اساس تاریخ از NSPredicate با عملگرهای مقایسه استفاده کنید — Core Data timezone را در سطح SQLite به درستی پردازش میکند.
CFAbsoluteTime — یک نوع Core Foundation است که از همان تاریخ مرجع (۱ ژانویه ۲۰۰۱) استفاده میکند. Date و CFAbsoluteTime از طریق تبدیل مستقیم قابل جایگزینی هستند. Date(timeIntervalSinceReferenceDate:) CFAbsoluteTime را میپذیرد و Date.timeIntervalSinceReferenceDate CFAbsoluteTime را برمیگرداند.
Date دارای دقت تا میلیثانیه است، اما به دلیل محدودیتهای سختافزاری iOS/macOS دقت نانوثانیه را تضمین نمیکند. برای اندازهگیریهای با دقت بالا از mach_absolute_time یا ContinuousClock از Swift 5.7+ استفاده کنید که روی شمارندههای چرخه پردازنده کار میکنند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید