วันที่และเวลาในการพัฒนามือถือ: คืออะไร รูปแบบใดบ้าง และวิธีการทำงาน

ผู้แต่ง: 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 — backport ของ 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 ทั้งหมดไม่สามารถเปลี่ยนแปลงได้และปลอดภัยต่อเธรด ซึ่งกำจัดสภาวะการแข่งขันเมื่อทำงานในหลายเธรด

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 KB ซึ่งยอมรับได้สำหรับแอปพลิเคชันมือถือส่วนใหญ่

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 ms บนเครือข่ายท้องถิ่นและ 10-100 ms ผ่านอินเทอร์เน็ต

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 — 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 สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ