ตัวอย่างนี้สาธิตวิธี แปลง String รูปแบบ ISO 8601 (เช่น "2020-07-05T09:27:37Z") เป็น Date Object ใน Android โดยใช้ SimpleDateFormat และ java.time (API 26+)
ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่
Android Studio → New Project → Empty Activity
ขั้นตอนที่ 2: Layout (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="24dp"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:text="ISO 8601 Parser Demo"
android:textAlignment="center"
android:textColor="@android:color/holo_green_dark"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvResult"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="@android:color/holo_red_dark"
android:textSize="18sp"
android:textStyle="bold"
android:lineSpacingExtra="8dp" />
</RelativeLayout>
ขั้นตอนที่ 3: โค้ดหลัก (MainActivity.kt)
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.TimeZone
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
title = "ISO 8601 Parser"
val tvResult = findViewById(R.id.tvResult)
val isoString = "2020-07-05T09:27:37Z"
// 🔑 วิธีที่ 1: SimpleDateFormat (Legacy, ทุก API)
val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.getDefault()).apply {
timeZone = TimeZone.getTimeZone("UTC") // สำคัญ: Z = UTC
}
val date: Date = try {
sdf.parse(isoString)!!
} catch (e: java.text.ParseException) {
Date() // Fallback
}
// แสดงผล
val outputFormat = SimpleDateFormat("dd MMM yyyy, HH:mm:ss z", Locale.getDefault())
tvResult.text = "Input: $isoString\n\nParsed Date:\n${outputFormat.format(date)}"
}
}
🚀 วิธีทันสมัย: java.time (API 26+ / Android 8.0+)
แนะนำให้ใช้ java.time package (ต้อง enable Core Library Desugaring)
// build.gradle (Module)
android {
defaultConfig {
multiDexEnabled true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
coreLibraryDesugaringEnabled true
}
dependencies {
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.0.4"
}
import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
// Parse ISO 8601 (รองรับหลายรูปแบบอัตโนมัติ)
val instant = Instant.parse("2020-07-05T09:27:37Z")
val zonedDateTime = instant.atZone(ZoneId.systemDefault())
// Format
val formatter = DateTimeFormatter.ofPattern("dd MMM yyyy, HH:mm:ss z", Locale.getDefault())
val formatted = zonedDateTime.format(formatter)
// หรือใช้ ZonedDateTime.parse โดยตรง
val zdt = ZonedDateTime.parse("2020-07-05T09:27:37+07:00[Asia/Bangkok]")
📋 รูปแบบ ISO 8601 ที่พบบ่อย
| Format | ตัวอย่าง | Pattern (SimpleDateFormat) |
|---|---|---|
| UTC (Zulu) | 2020-07-05T09:27:37Z |
yyyy-MM-dd'T'HH:mm:ss'Z' |
| With Offset | 2020-07-05T09:27:37+07:00 |
yyyy-MM-dd'T'HH:mm:ssXXX |
| With Millis | 2020-07-05T09:27:37.123Z |
yyyy-MM-dd'T'HH:mm:ss.SSS'Z' |
| Date Only | 2020-07-05 |
yyyy-MM-dd |
🛠️ ฟังก์ชันช่วย Parse แบบทนทาน (Robust Parser)
fun parseIso8601(isoString: String): Date? {
val patterns = arrayOf(
"yyyy-MM-dd'T'HH:mm:ss'Z'",
"yyyy-MM-dd'T'HH:mm:ssXXX",
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
"yyyy-MM-dd'T'HH:mm:ss.SSSXXX",
"yyyy-MM-dd"
)
for (pattern in patterns) {
try {
val sdf = SimpleDateFormat(pattern, Locale.US).apply {
timeZone = TimeZone.getTimeZone("UTC")
isLenient = false
}
return sdf.parse(isoString)
} catch (e: java.text.ParseException) {
// Try next pattern
}
}
return null
}
💡 Best Practices
- ✅ ใช้ java.time (API 26+) เป็นหลัก - Immutable, Thread-safe, รองรับ Timezone ดี
- ✅ ใช้ ThreeTenABP สำหรับ API < 26 (Legacy)
- ✅ ตั้ง
TimeZone = UTCเมื่อ Parse String ที่มี Z - ✅ ใช้
Locale.USสำหรับ Parse (Thai Locale อาจ Parse ไม่ได้) - ❌ หลีกเลี่ยง
SimpleDateFormatใน Production (Not Thread-safe, Lenient)
ขั้นตอนที่ 4: AndroidManifest.xml
Manifest มาตรฐาน
ทดสอบ
- รันแอป → แสดงวันที่แปลงแล้ว: "05 Jul 2020, 09:27:37 UTC" (หรือ Timezone ของเครื่อง)
- ลองเปลี่ยน isoString ในโค้ดเป็นรูปแบบอื่นๆ
- ทดสอบกับ java.time หาก minSdkVersion >= 26