DateFormatter: mga pangunahing konsepto, pag-format ng petsa at lokalisasyon

May-akda: IT Sectr Nai-publish: 2026-07-12 Oras ng pagbabasa: 7 min

DateFormatter — isang klase ng Foundation na idinisenyo para sa two-way na conversion sa pagitan ng Date objects at ng kanilang string representation. Isinasaalang-alang ng klase ang locale, timezone, at kalendaryo ng user, na tinitiyak ang tamang pagpapakita ng mga petsa sa anumang rehiyon ng mundo. Ayon sa Apple Developer Documentation (2025), sinusuportahan ng DateFormatter ang apat na paunang natukoy na estilo ng petsa at oras, pati na rin ang ganap na custom na mga format sa pamamagitan ng pattern string. Kung wala ang DateFormatter, hindi posible na tamang ipakita ang petsa sa user sa isang internasyonalisadong aplikasyon.

Mga Pangunahing

  • DateFormatter — klase para sa conversion ng Date sa string at pabalik na isinasaalang-alang ang locale at timezone.
  • dateStyle at timeStyle — paunang natukoy na mga estilo (.short, .medium, .long, .full) para sa mabilis na pag-format.
  • dateFormat — string ng pattern para sa custom na format, na tinutukoy sa pamamagitan ng mga simbolo ng Unicode LDML specification.
  • Locale at TimeZone — mga property ng formatter na tumutukoy sa regional na display at timezone.
  • ISO8601DateFormatter — mas mabilis na alternatibo para sa ISO 8601 format sa serialization sa API.

Ano ang DateFormatter?

DateFormatter — isang klase mula sa Foundation framework na nagpapatupad ng two-way na conversion sa pagitan ng Date at string. Lumitaw ito sa OpenStep bilang NSDateFormatter at mula noon ay nananatiling pangunahing tool para sa pag-format ng petsa sa lahat ng Apple platform. Ang klase ay nagmana mula sa Formatter at nagbibigay ng maginhawang API para sa lokalisadong pagpapakita ng petsa.

Ang prinsipyo ng pagpapatakbo ng DateFormatter ay batay sa Unicode LDML pattern — parehong ginagamit sa ICU (International Components for Unicode). Ang pattern ay tinutukoy sa pamamagitan ng dateFormat property, kung saan ang mga simbolo y, M, d, H, m, s ay tumutugma sa taon, buwan, araw, oras, minuto, at segundo. Ang pag-ulit ng simbolo ay tumutukoy sa format: “y” — dalawang-digit na taon, “yyyy” — apat na digit.

Ang paggawa ng DateFormatter ay isang magastos na operasyon, dahil sa pagsisimula ay naglo-load ng data ng locale at kalendaryo. Inirerekomenda ng Apple na gawin ang formatter nang isang beses para sa bawat uri ng pag-format at muling gamitin ito. Sa SwiftUI at UIKit, ang mga formatter ay madalas na naka-cache sa mga static na property o ginagawa nang tamad sa unang pag-access.

DateFormatter sa iOS SDK

DateFormatter ay ginagamit sa maraming system component ng iOS. Ang UIDatePicker ay gumagamit ng DateFormatter sa loob para sa pagpapakita ng mga petsa sa countDownTimer mode. Ang TextField na may formatter sa input ay maaaring awtomatikong i-validate ang petsa na ipinasok ng user. Sinusuportahan ng Core Data ang mga attribute ng uri ng Date, ngunit ang kanilang string display ay palaging ginagawa sa pamamagitan ng DateFormatter.

Thread Safety — Ang DateFormatter ay hindi thread-safe. Ang pagbabago ng mga property ng formatter mula sa iba’t ibang thread ay humahantong sa hindi tiyak na pag-uugali. Para sa multi-threaded na paggamit, gumawa ng magkahiwalay na instance ng formatter para sa bawat thread o gumamit ng synchronization sa pamamagitan ng NSLock o serial queue.

Mga estilo ng pag-format ng DateFormatter

dateStyle at timeStyle — ang pinakasimpleng paraan upang i-configure ang display ng petsa. Bawat estilo ay may apat na variant: .short, .medium, .long, .full. Ang kombinasyon ng dateStyle at timeStyle ay nagbibigay-daan sa independiyenteng pagsasaayos ng format ng petsa at oras, at ang property na .none ay nagdi-disable sa kaukulang bahagi.

Para sa US locale, ang .short style ay nagfo-format ng petsa bilang “7/21/26”, at para sa Pilipinas — bilang “21/07/2026”. Ang .long style para sa Philippine locale ay nagpapakita ng “21 Hulyo 2026”, at .full — “Martes, 21 Hulyo 2026” na may pagbanggit ng araw ng linggo. Lahat ng apat na estilo ay awtomatikong umaangkop sa mga regional standard, kabilang ang pagkakasunod-sunod ng mga component at separator.

RelativeDateFormatter sa iOS 15+ ay nag-aalok ng alternatibong approach sa pamamagitan ng RelativeDateFormatter at DateIntervalFormatter. Ang RelativeDateFormatter ay nagpapakita ng “ngayon”, “kahapon”, “pagkalipas ng 3 araw” para sa kasalukuyang konteksto. Ang DateIntervalFormatter ay nagpapakita ng range ng petsa: “21–25 Hulyo 2026” — para sa booking at pagpaplano.

EstiloHalimbawa (fil_PH)Halimbawa (en_US)
.short21/07/20267/21/26
.medium21 Hul 2026Jul 21, 2026
.long21 Hulyo 2026July 21, 2026
.fullMartes, 21 Hulyo 2026Tuesday, July 21, 2026

Sa pagsasama ng mga estilo, awtomatikong pumipili ang DateFormatter ng separator: para sa .short.date + .short.time ang resulta ay maaaring “21/07/2026, 14:30”. Para sa .full.date + .full.time — “Martes, 21 Hulyo 2026, 14:30:00 MSK”. Ang separator ay kinokontrol ng locale, hindi ng developer — ginagarantiyahan nito ang pagsunod sa regional expectations ng user.

Custom na mga format sa pamamagitan ng dateFormat

dateFormat ay nagbibigay-daan sa iyo na tukuyin ang isang arbitrary na pattern ng pag-format gamit ang mga simbolo ng Unicode LDML specification. Nagbibigay ito ng kumpletong kontrol sa display: maaari mong ipakita lamang ang taon at buwan, araw ng linggo nang walang numero, o oras nang walang segundo. Ang custom na format ay kailangang-kailangan para sa mga partikular na pangangailangan ng disenyo.

Mga pangunahing simbolo — yyyy (taon: 2026), MM (buwan: 07), dd (araw: 21), HH (oras: 14), mm (minuto: 30), ss (segundo: 00). Para sa buong pangalan ng buwan gamitin ang MMMM (Hulyo), para sa pinaikli — MMM (Hul). Araw ng linggo — EEEE (Martes), pinaikli — E (Mar).

Kapag gumagamit ng dateFormat, mahalagang itakda ang locale ng formatter. Kung hindi nakatakda ang locale, ginagamit ng formatter ang system locale, na maaaring hindi gusto para sa nakapirming format sa API. Inirerekomenda ng Apple ang pagtatakda ng locale = Locale(identifier: “en_US_POSIX”) para sa nakapirming inter-regional na format, lalo na kapag nagpa-parse ng mga petsa mula sa mga server response.

swift
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "ru_RU")
formatter.dateFormat = "d MMMM yyyy"
let customString = formatter.string(from: Date())
// "21 July 2026"

// Pag-parse ng custom na string
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date = formatter.date(from: "2026-07-21 14:30:00")!

Ang error sa dateFormat — isa sa mga karaniwang sanhi ng pag-crash ng app. Kung hindi tugma ang format sa string, ang method na date(from:) ay nagbabalik ng nil. Gumamit ng guard let o ?? para sa ligtas na pag-extract ng optional na halaga. Para sa validation ng format, subukan sa lahat ng suportadong wika — ang ilang LDML na simbolo ay gumagana nang iba sa iba’t ibang locale.

Lokalisasyon at TimeZone

Locale ay tumutukoy kung paano ipinapakita ang mga pangalan ng buwan, araw ng linggo, at kung anong mga separator ang ginagamit. Ang DateFormatter ay default na gumagamit ng Locale.current, ngunit sa ilang mga scenario ay kinakailangan ang pagtukoy ng partikular na locale: para sa nakapirming format sa logs gamitin ang en_US_POSIX, para sa server dates — locale na kapareho ng server.

Ang property na TimeZone ay tumutukoy sa timezone para sa display. Default na ginagamit ang system timezone, ngunit para sa mga aplikasyon na may international audience ay madalas na kinakailangan ang pagpapakita ng mga petsa sa timezone ng user o sa UTC. Ang pagbabago ng timeZone ay nakakaapekto lamang sa display — ang Date value ay nananatiling hindi nagbabago.

Mahalagang katangian: kung ang DateFormatter ay ginagamit para sa pag-parse ng string, at ang string ay naglalaman ng indikasyon ng timezone (halimbawa, “2026-07-21T14:30:00Z” na may Z para sa UTC), ang timeZone property ay binabalewala — ginagamit ng formatter ang timezone mula sa string. Kung ang timezone ay wala sa string, ang timeZone ng formatter ang ilalapat.

swift
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "ru_RU")
formatter.timeZone = TimeZone(identifier: "Europe/Moscow")
formatter.dateStyle = .long
formatter.timeStyle = .short

let moscowTime = formatter.string(from: Date())
// "21 July 2026, 14:30"

// Pag-parse nang walang timezone sa string
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd HH:mm"
let utcDate = formatter.date(from: "2026-07-21 10:30")!

AutoupdatingCurrentLocale — isang espesyal na uri ng locale na awtomatikong nag-a-update kapag nagbago ang system settings ng user. Default itong sinusuportahan ng DateFormatter. Kung ang aplikasyon ay tumatakbo sa background at binago ng user ang system language, ang formatter na ginawa bago ang pagbabago ay patuloy na gagamit ng lumang locale — para sa pag-update kailangan gumawa ng bagong instance.

ISO8601DateFormatter at mga alternatibo

ISO8601DateFormatter — isang dalubhasang formatter para sa pagtatrabaho sa mga petsa sa ISO 8601 format. Ang format na ito ay ang de facto na standard para sa REST API, JSON, at data exchange. Ang ISO8601DateFormatter ay gumagana nang mas mabilis kaysa sa DateFormatter dahil hindi ito nakadepende sa locale at gumagamit ng fixed parsing grammar.

Mga pangunahing opsyon ng formatter — .withInternetDateTime (2026-07-21T14:30:00Z), .withFractionalSeconds (nagdaragdag ng milliseconds), .withTimeZone (nagsasama ng timezone offset). Sa pamamagitan ng pagsasama ng mga opsyon, maaari kang makakuha ng anumang ISO 8601 variant: na may milliseconds, may timezone, may petsa na walang oras.

JSONEncoder.DateEncodingStrategy ay nagbibigay-daan sa iyo na i-configure ang pag-encode ng petsa para sa lahat ng Codable na modelo. Mga variant — .iso8601 (gumagamit ng ISO8601DateFormatter), .formatted(DateFormatter), .millisecondsSince1970, .secondsSince1970. Ang pagpili ng strategy ay nakakaapekto sa buong lifecycle ng serialization at dapat na pare-pareho para sa lahat ng API endpoint.

swift
// ISO8601DateFormatter
let isoFormatter = ISO8601DateFormatter()
isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let isoString = isoFormatter.string(from: Date())
// "2026-07-21T14:30:00.000Z"

// JSONEncoder na may ISO8601
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601

// Alternatibo: JSONEncoder na may custom na formatter
let customEncoder = JSONEncoder()
customEncoder.dateEncodingStrategy = .formatted(myFormatter)

DateFormatter vs ISO8601DateFormatter — piliin ang ISO8601DateFormatter para sa serialization at parsing ng mga petsa sa API, dahil gumagana ito ng 5-10 beses na mas mabilis kaysa sa DateFormatter at hindi madaling kapitan ng localization errors. Iwanan ang DateFormatter para sa user interface, kung saan kinakailangan ang lokalisadong display na may mga pangalan ng buwan at araw ng linggo sa katutubong wika ng user.

Mga halimbawa ng pag-format ng petsa

Isaalang-alang natin ang mga real na scenario ng paggamit ng DateFormatter sa isang iOS application: pagpapakita sa listahan ng balita, pagpasok ng petsa ng kapanganakan, at pag-export ng report na may mga petsa sa iba’t ibang timezone.

Pagpapakita ng petsa ng balita sa listahan

RelativeDateFormatter ay optimal para sa mga news feed. Ito ay nagpapakita ng “ngayon lang”, “5 minuto ang nakalipas”, “kahapon” para sa mga bagong balita at lumilipat sa buong petsa para sa mga luma. Ang threshold ng paglipat ay naka-configure sa pamamagitan ng calendar: para sa balita gumamit ng threshold na 24 oras, para sa messenger — isang linggo.

swift
func formatRelativeDate(_ date: Date) -> String {
    let relative = RelativeDateFormatter()
    relative.unitsStyle = .full

    let formatter = DateFormatter()
    formatter.dateStyle = .medium
    formatter.timeStyle = .short

    let daysDiff = Calendar.current.dateComponents(
        [.day], from: date, to: Date()
    ).day ?? 0

    return daysDiff < 1
        ? relative.localizedString(for: date, relativeTo: Date())
        : formatter.string(from: date)
}

Pagpasok ng petsa ng kapanganakan — isa pang karaniwang scenario. Ang DateFormatter ay naka-configure na may tiyak na dateFormat “dd/MM/yyyy” at locale “fil_PH”. Sa pag-parse ng ipinasok na string, mahalagang hawakan ang mga posibleng error: ang formatter ay nagbabalik ng nil para sa hindi tamang string. Pagkatapos ng matagumpay na pag-parse, ang petsa ay susuriin kung nasa loob ng pinapayagang range — hindi mas maaga sa 1900, hindi mas huli sa ngayon.

Pag-export ng report na may mga petsa ay nangangailangan ng nakapirming format na hindi nakadepende sa locale ng user. Gumamit ng dateFormat “yyyy-MM-dd HH:mm:ss” na may locale na en_US_POSIX at timezone na UTC. Ang approach na ito ay ginagarantiyahan na ang file ay magbubukas nang tama sa anumang bansa anuman ang regional settings ng system.

ScenarioFormatterKey Setting
News feedRelativeDateFormatterunitsStyle = .full
Date inputDateFormatterdateFormat + fallback
API serializationISO8601DateFormatterwithInternetDateTime
Report exportDateFormatteren_US_POSIX + UTC

Mga Madalas Itanong

Bakit nagbabalik ng nil ang DateFormatter para sa tamang string?

Pinakakaraniwang dahilan — hindi pagkakatugma ng dateFormat sa format ng string. Halimbawa, ang format na “dd/MM/yyyy” ay hindi magpa-parse ng string na “2026-07-21”. Pangalawang dahilan — hindi pagkakatugma ng locale: ang string na “July 21, 2026” ay hindi magpa-parse sa locale na fil_PH. Pangatlo — typo sa LDML symbols: gamitin ang yyyy, hindi YYYY (magkaibang kahulugan).

Kailangan bang gumawa ng bagong DateFormatter para sa bawat tawag?

Hindi. Ang DateFormatter ay isang mabigat na object, ang initialization nito ay may kasamang pag-load ng locale data. Gumawa ng isang instance bawat uri ng pag-format at gamitin itong muli. Sa multi-threaded na kapaligiran, gumamit ng Thread-local storage o pool ng mga formatter na may serial queue para sa synchronization.

Ano ang pagkakaiba ng DateFormatter sa RelativeDateFormatter?

DateFormatter ay nagpapakita ng absolute date (21 Hulyo 2026), habang ang RelativeDateFormatter ay nagpapakita ng relative date (ngayon, kahapon, pagkalipas ng 3 araw). Ang RelativeDateFormatter ay lumitaw sa iOS 15+ at gumagamit ng parehong LDML pattern, ngunit awtomatikong pumipili ng relative display.

Paano hahawakan ang mga petsa na walang timezone mula sa API?

Itakda ang timeZone ng formatter sa UTC bago mag-parse. Kung ang server ay nagbabalik ng petsa sa lokal na oras na walang indikasyon ng timezone, suriin ang API specification — malamang na UTC ang ibig sabihin. Para sa ISO 8601 na may Z sa dulo, hindi kailangan ang timeZone — ine-parse ng formatter ang offset mula sa string.

Paano gawing thread-safe ang DateFormatter?

Huwag gumamit ng isang instance mula sa iba’t ibang thread nang walang synchronization. Gumawa ng bagong instance sa bawat thread o gumamit ng Thread.current.threadDictionary para sa storage. Alternatibo — NSLock na may pag-lock sa panahon ng string(from:) at date(from:).

Buod

  • DateFormatter — klase ng Foundation para sa conversion ng Date sa string at pabalik na isinasaalang-alang ang locale, timezone, at kalendaryo ng user.
  • Paunang natukoy na mga estilo dateStyle at timeStyle na may variant na .short, .medium, .long, .full ay sumasaklaw sa karamihan ng mga UI scenario.
  • Custom na dateFormat sa pamamagitan ng LDML symbols ay nagbibigay ng kumpletong kontrol sa format, ngunit nangangailangan ng pag-iingat sa lokalisasyon.
  • Locale at TimeZone — mga mandatoryong property para sa tamang display: para sa UI — system locale, para sa API — en_US_POSIX at UTC.
  • ISO8601DateFormatter — mas pinipiling pagpipilian para sa serialization ng mga petsa sa API dahil sa bilis at stability.
  • DateFormatter ay hindi thread-safe — gumamit ng magkahiwalay na instance para sa bawat thread o i-synchronize ang access.
  • RelativeDateFormatter (iOS 15+) — optimal na solusyon para sa pagpapakita ng relative dates sa mga news feed at messenger.

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din