Android Kotlin 日期时间示例

Android Kotlin 日期时间示例,包括获取当前时间、日期时间格式化和解析日期字符串

💻 获取当前时间 kotlin

🟢 simple ⭐⭐

以各种格式和时区获取系统当前时间

⏱️ 15 min 🏷️ kotlin, android, datetime
Prerequisites: Basic Kotlin knowledge, Java Time API
// Android Kotlin Get Current Time Examples
// Using java.time API (Android API 26+) and legacy Date API

import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.Clock
import java.util.Date
import java.util.Calendar
import android.os.SystemClock

// 1. Current Time Using Modern API (API 26+)
class ModernTimeGetter {

    // Get current instant
    fun getCurrentInstant(): Instant {
        return Instant.now()
    }

    // Get current local date-time
    fun getCurrentLocalDateTime(): LocalDateTime {
        return LocalDateTime.now()
    }

    // Get current zoned date-time
    fun getCurrentZonedDateTime(zoneId: ZoneId = ZoneId.systemDefault()): ZonedDateTime {
        return ZonedDateTime.now(zoneId)
    }

    // Get current time in specific timezone
    fun getCurrentTimeInZone(zone: String): ZonedDateTime {
        val zoneId = ZoneId.of(zone)
        return ZonedDateTime.now(zoneId)
    }

    // Get current time from specific clock
    fun getCurrentTimeFromClock(clock: Clock): Instant {
        return Instant.now(clock)
    }

    // Get current timestamp (milliseconds since epoch)
    fun getCurrentTimestamp(): Long {
        return Instant.now().toEpochMilli()
    }

    // Get current unix timestamp (seconds since epoch)
    fun getCurrentUnixTimestamp(): Long {
        return Instant.now().epochSecond
    }
}

// 2. Current Time Using Legacy API
class LegacyTimeGetter {

    // Get current date
    fun getCurrentDate(): Date {
        return Date()
    }

    // Get current calendar
    fun getCurrentCalendar(): Calendar {
        return Calendar.getInstance()
    }

    // Get current timestamp
    fun getCurrentTimestamp(): Long {
        return System.currentTimeMillis()
    }

    // Get current time in specific timezone
    fun getCurrentTimeInTimezone(timezone: String): Calendar {
        return Calendar.getInstance(java.util.TimeZone.getTimeZone(timezone))
    }
}

// 3. System Time Measurements (Android)
class SystemTimeGetter {

    // Get elapsed realtime (since boot)
    fun getElapsedRealtime(): Long {
        return SystemClock.elapsedRealtime()
    }

    // Get elapsed realtime including deep sleep
    fun getElapsedRealtimeNanos(): Long {
        return SystemClock.elapsedRealtimeNanos()
    }

    // Get uptime (since boot, excluding deep sleep)
    fun getUptimeMillis(): Long {
        return SystemClock.uptimeMillis()
    }

    // Get current thread time
    fun getCurrentThreadTimeMillis(): Long {
        return SystemClock.currentThreadTimeMillis()
    }

    // Get current thread CPU time
    fun getCurrentThreadCpuTimeNano(): Long {
        return SystemClock.currentThreadCpuTimeNano()
    }
}

// 4. Time Components Extraction
class TimeComponentExtractor {

    // Extract components using modern API
    fun extractComponentsModern(localDateTime: LocalDateTime): TimeComponents {
        return TimeComponents(
            year = localDateTime.year,
            month = localDateTime.monthValue,
            day = localDateTime.dayOfMonth,
            hour = localDateTime.hour,
            minute = localDateTime.minute,
            second = localDateTime.second,
            nano = localDateTime.nano,
            dayOfWeek = localDateTime.dayOfWeek.value,
            dayOfYear = localDateTime.dayOfYear
        )
    }

    // Extract components using legacy API
    fun extractComponentsLegacy(calendar: Calendar): TimeComponents {
        return TimeComponents(
            year = calendar.get(Calendar.YEAR),
            month = calendar.get(Calendar.MONTH) + 1,
            day = calendar.get(Calendar.DAY_OF_MONTH),
            hour = calendar.get(Calendar.HOUR_OF_DAY),
            minute = calendar.get(Calendar.MINUTE),
            second = calendar.get(Calendar.SECOND),
            nano = calendar.get(Calendar.MILLISECOND) * 1_000_000,
            dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK),
            dayOfYear = calendar.get(Calendar.DAY_OF_YEAR)
        )
    }

    // Get time of day
    fun getTimeOfDay(localDateTime: LocalDateTime): String {
        val hour = localDateTime.hour
        return when (hour) {
            in 0..5 -> "Early Morning"
            in 6..11 -> "Morning"
            in 12..17 -> "Afternoon"
            in 18..21 -> "Evening"
            else -> "Night"
        }
    }
}

// Time Components Data Class
data class TimeComponents(
    val year: Int,
    val month: Int,
    val day: Int,
    val hour: Int,
    val minute: Int,
    val second: Int,
    val nano: Int,
    val dayOfWeek: Int,
    val dayOfYear: Int
) {
    fun print() {
        println("Date: $year-$month-$day")
        println("Time: $hour:$minute:$second")
        println("Day of week: $dayOfWeek")
        println("Day of year: $dayOfYear")
        println("Nanos: $nano")
    }
}

// 5. Time Zone Operations
class TimeZoneOperations {

    // Get current time in multiple timezones
    fun getCurrentTimeInZones(zones: List<String>): Map<String, ZonedDateTime> {
        val result = mutableMapOf<String, ZonedDateTime>()
        for (zone in zones) {
            val zoneId = ZoneId.of(zone)
            result[zone] = ZonedDateTime.now(zoneId)
        }
        return result
    }

    // Get available zone IDs
    fun getAvailableZoneIds(): Set<String> {
        return ZoneId.getAvailableZoneIds()
    }

    // Get system default timezone
    fun getSystemTimezone(): ZoneId {
        return ZoneId.systemDefault()
    }

    // Get offset from UTC
    fun getUTCOffset(zoneId: ZoneId = ZoneId.systemDefault()): String {
        val now = ZonedDateTime.now(zoneId)
        val offset = now.offset
        return offset.id
    }
}

// 6. Time Comparisons
class TimeComparer {

    // Compare two instants
    fun compareInstants(instant1: Instant, instant2: Instant): ComparisonResult {
        return when {
            instant1.isBefore(instant2) -> ComparisonResult.BEFORE
            instant1.isAfter(instant2) -> ComparisonResult.AFTER
            else -> ComparisonResult.EQUAL
        }
    }

    // Calculate duration between instants
    fun calculateDuration(instant1: Instant, instant2: Instant): DurationInfo {
        val duration = java.time.Duration.between(instant1, instant2)
        return DurationInfo(
            days = duration.toDays(),
            hours = duration.toHours(),
            minutes = duration.toMinutes(),
            seconds = duration.seconds,
            millis = duration.toMillis()
        )
    }

    // Check if time is within range
    fun isWithinRange(
                    instant: Instant,
                    start: Instant,
                    end: Instant
    ): Boolean {
        return !instant.isBefore(start) && !instant.isAfter(end)
    }
}

// Duration Info Data Class
data class DurationInfo(
    val days: Long,
    val hours: Long,
    val minutes: Long,
    val seconds: Long,
    val millis: Long
) {
    fun print() {
        println("Duration: ${days}d ${hours}h ${minutes}m ${seconds}s")
    }
}

// Comparison Result Enum
enum class ComparisonResult {
    BEFORE, EQUAL, AFTER
}

// Main demonstration
fun demonstrateGetCurrentTime() {
    println("=== Android Kotlin Get Current Time Examples ===\n")

    // 1. Modern API
    println("--- 1. Modern API (API 26+) ---")
    val modernGetter = ModernTimeGetter()

    val instant = modernGetter.getCurrentInstant()
    println("Current instant: $instant")

    val localDateTime = modernGetter.getCurrentLocalDateTime()
    println("Local date-time: $localDateTime")

    val zonedDateTime = modernGetter.getCurrentZonedDateTime()
    println("Zoned date-time: $zonedDateTime")

    val timestamp = modernGetter.getCurrentTimestamp()
    println("Timestamp (ms): $timestamp")

    val unixTimestamp = modernGetter.getCurrentUnixTimestamp()
    println("Unix timestamp: $unixTimestamp")

    // 2. Time in different zones
    println("\n--- 2. Time in Different Timezones ---")
    val timeInUTC = modernGetter.getCurrentTimeInZone("UTC")
    println("UTC: $timeInUTC")

    val timeInNY = modernGetter.getCurrentTimeInZone("America/New_York")
    println("New York: $timeInNY")

    val timeInTokyo = modernGetter.getCurrentTimeInZone("Asia/Tokyo")
    println("Tokyo: $timeInTokyo")

    val timeInLondon = modernGetter.getCurrentTimeInZone("Europe/London")
    println("London: $timeInLondon")

    // 3. Legacy API
    println("\n--- 3. Legacy API ---")
    val legacyGetter = LegacyTimeGetter()

    val date = legacyGetter.getCurrentDate()
    println("Current date: $date")

    val calendar = legacyGetter.getCurrentCalendar()
    println("Calendar time: ${calendar.time}")

    // 4. System time measurements
    println("\n--- 4. System Time Measurements ---")
    val systemGetter = SystemTimeGetter()

    println("Elapsed realtime: ${systemGetter.getElapsedRealtime()} ms")
    println("Uptime millis: ${systemGetter.getUptimeMillis()} ms")
    println("Current thread time: ${systemGetter.getCurrentThreadTimeMillis()} ms")

    // 5. Extract components
    println("\n--- 5. Extract Time Components ---")
    val extractor = TimeComponentExtractor()
    val components = extractor.extractComponentsModern(localDateTime)
    components.print()

    println("\nTime of day: ${extractor.getTimeOfDay(localDateTime)}")

    // 6. Multiple timezones
    println("\n--- 6. Multiple Timezones ---")
    val zoneOps = TimeZoneOperations()
    val zones = listOf("UTC", "America/Los_Angeles", "Europe/Paris", "Asia/Shanghai")
    val timesInZones = zoneOps.getCurrentTimeInZones(zones)

    timesInZones.forEach { (zone, time) ->
        println("$zone: $time")
    }

    println("\nSystem timezone: ${zoneOps.getSystemTimezone()}")
    println("UTC offset: ${zoneOps.getUTCOffset()}")

    // 7. Time comparison
    println("\n--- 7. Time Comparison ---")
    val comparer = TimeComparer()

    val now = Instant.now()
    val later = now.plusSeconds(3600)
    val earlier = now.minusSeconds(3600)

    println("Compare now vs later: ${comparer.compareInstants(now, later)}")
    println("Compare now vs earlier: ${comparer.compareInstants(now, earlier)}")

    val duration = comparer.calculateDuration(now, later)
    println("Duration between now and later:")
    duration.print()

    println("\n=== All Get Current Time Examples Completed ===")
}

💻 日期时间格式化 kotlin

🟡 intermediate ⭐⭐⭐

使用各种模式和语言环境将日期时间对象格式化为字符串

⏱️ 25 min 🏷️ kotlin, android, datetime, formatting
Prerequisites: Intermediate Kotlin, Java Time API
// Android Kotlin Date & Time Formatting Examples
// Using java.time.format (API 26+) and SimpleDateFormat

import java.time.LocalDateTime
import java.time.ZonedDateTime
import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.Calendar

// 1. Basic Formatting Using Modern API
class ModernDateFormatter {

    // ISO format
    fun formatToISO(localDateTime: LocalDateTime): String {
        return localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
    }

    // Custom pattern
    fun formatWithPattern(localDateTime: LocalDateTime, pattern: String): String {
        val formatter = DateTimeFormatter.ofPattern(pattern)
        return localDateTime.format(formatter)
    }

    // Pre-defined common formats
    fun formatDateFull(localDateTime: LocalDateTime): String {
        return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
    }

    fun formatTimeFull(localDateTime: LocalDateTime): String {
        return localDateTime.format(DateTimeFormatter.ofPattern("HH:mm:ss"))
    }

    fun formatDateTimeFull(localDateTime: LocalDateTime): String {
        return localDateTime.format(
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
        )
    }

    // Short format
    fun formatShort(localDateTime: LocalDateTime): String {
        return localDateTime.format(
            DateTimeFormatter.ofPattern("yy/MM/dd HH:mm")
        )
    }

    // With milliseconds
    fun formatWithMillis(localDateTime: LocalDateTime): String {
        return localDateTime.format(
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
        )
    }

    // With nanoseconds
    fun formatWithNanos(localDateTime: LocalDateTime): String {
        return localDateTime.format(
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.nnnnnnnnn")
        )
    }
}

// 2. Localized Formatting
class LocalizedFormatter {

    // Format with locale
    fun formatDateLocalized(localDateTime: LocalDateTime, locale: Locale): String {
        val formatter = DateTimeFormatter.ofPattern(
            "yyyy MMMM dd, EEEE",
            locale
        )
        return localDateTime.format(formatter)
    }

    // Format in different locales
    fun formatDateInMultipleLocales(localDateTime: LocalDateTime):
            Map<String, String> {
        val locales = listOf(
            "en" to Locale.ENGLISH,
            "zh" to Locale.CHINESE,
            "es" to Locale("es"),
            "fr" to Locale.FRENCH,
            "de" to Locale.GERMAN,
            "ja" to Locale.JAPANESE,
            "ar" to Locale("ar")
        )

        return locales.mapValues { (_, locale) ->
            val formatter = DateTimeFormatter.ofPattern(
                "yyyy MMMM dd, EEEE HH:mm",
                locale
            )
            localDateTime.format(formatter)
        }
    }

    // Format using localized date style
    fun formatDateStyle(localDateTime: LocalDateTime, locale: Locale): String {
        val formatter = DateTimeFormatter
            .ofLocalizedDate(java.time.format.FormatStyle.FULL)
            .withLocale(locale)
        return localDateTime.format(formatter)
    }

    // Format using localized time style
    fun formatTimeStyle(localDateTime: LocalDateTime, locale: Locale): String {
        val formatter = DateTimeFormatter
            .ofLocalizedTime(java.time.format.FormatStyle.SHORT)
            .withLocale(locale)
        return localDateTime.format(formatter)
    }

    // Format using localized date-time style
    fun formatDateTimeStyle(
                    localDateTime: LocalDateTime,
                    locale: Locale,
                    style: java.time.format.FormatStyle
    ): String {
        val formatter = DateTimeFormatter
            .ofLocalizedDateTime(style)
            .withLocale(locale)
        return localDateTime.format(formatter)
    }
}

// 3. Formatting ZonedDateTime
class ZonedFormatter {

    // Format with timezone
    fun formatWithZone(zonedDateTime: ZonedDateTime): String {
        val formatter = DateTimeFormatter.ofPattern(
            "yyyy-MM-dd HH:mm:ss Z"
        )
        return zonedDateTime.format(formatter)
    }

    // Format with timezone name
    fun formatWithZoneName(zonedDateTime: ZonedDateTime): String {
        val formatter = DateTimeFormatter.ofPattern(
            "yyyy-MM-dd HH:mm:ss zzz"
        )
        return zonedDateTime.format(formatter)
    }

    // Format ISO with zone
    fun formatISOWithZone(zonedDateTime: ZonedDateTime): String {
        return zonedDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
    }

    // Convert to different timezone and format
    fun formatInZone(
                    instant: Instant,
                    zoneId: ZoneId,
                    pattern: String
    ): String {
        val zoned = instant.atZone(zoneId)
        val formatter = DateTimeFormatter.ofPattern(pattern)
        return zoned.format(formatter)
    }
}

// 4. Legacy Formatting (SimpleDateFormat)
class LegacyDateFormatter {

    // Simple date format
    fun formatSimple(date: Date, pattern: String): String {
        val formatter = SimpleDateFormat(pattern)
        return formatter.format(date)
    }

    // Format with locale
    fun formatWithLocale(date: Date, pattern: String, locale: Locale): String {
        val formatter = SimpleDateFormat(pattern, locale)
        return formatter.format(date)
    }

    // Common date formats
    fun formatISO(date: Date): String {
        return SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(date)
    }

    fun formatReadable(date: Date): String {
        return SimpleDateFormat("MMMM dd, yyyy 'at' HH:mm").format(date)
    }

    fun formatShort(date: Date): String {
        return SimpleDateFormat("yy/MM/dd").format(date)
    }

    fun formatLong(date: Date): String {
        return SimpleDateFormat(
            "EEEE, MMMM dd, yyyy 'at' hh:mm a"
        ).format(date)
    }
}

// 5. Special Format Patterns
class SpecialFormatter {

    // Relative time (e.g., "2 hours ago")
    fun formatRelative(dateTime: LocalDateTime): String {
        val now = LocalDateTime.now()
        val duration = java.time.Duration.between(dateTime, now)

        val hours = duration.toHours()
        val minutes = duration.toMinutes()

        return when {
            minutes < 1 -> "just now"
            minutes < 60 -> "$minutes minutes ago"
            hours < 24 -> "$hours hours ago"
            hours < 48 -> "yesterday"
            else -> "${daysBetween(dateTime, now)} days ago"
        }
    }

    private fun daysBetween(start: LocalDateTime, end: LocalDateTime): Long {
        return java.time.Duration.between(start, end).toDays()
    }

    // Format duration
    fun formatDuration(duration: java.time.Duration): String {
        val days = duration.toDays()
        val hours = duration.toHours() % 24
        val minutes = duration.toMinutes() % 60
        val seconds = duration.seconds % 60

        return when {
            days > 0 -> "${days}d ${hours}h ${minutes}m ${seconds}s"
            hours > 0 -> "${hours}h ${minutes}m {seconds}s"
            minutes > 0 -> "${minutes}m ${seconds}s"
            else -> "${seconds}s"
        }
    }

    // Format as timestamp
    fun formatAsTimestamp(localDateTime: LocalDateTime): String {
        return localDateTime.atZone(ZoneId.systemDefault())
            .toInstant()
            .toEpochMilli()
            .toString()
    }

    // Format with ordinal indicator
    fun formatWithOrdinal(localDateTime: LocalDateTime): String {
        val day = localDateTime.dayOfMonth
        val ordinal = when (day) {
            1, 21, 31 -> "st"
            2, 22 -> "nd"
            3, 23 -> "rd"
            else -> "th"
        }

        val formatter = DateTimeFormatter.ofPattern("MMMM")
        val month = localDateTime.format(formatter)

        return "$month $day$ordinal, ${localDateTime.year}"
    }
}

// 6. Custom Business Formats
class BusinessFormatter {

    // Format for logs
    fun formatForLog(localDateTime: LocalDateTime): String {
        return localDateTime.format(
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
        )
    }

    // Format for filenames
    fun formatForFileName(localDateTime: LocalDateTime): String {
        return localDateTime.format(
            DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")
        )
    }

    // Format for reports
    fun formatForReport(localDateTime: LocalDateTime): String {
        return localDateTime.format(
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
        )
    }

    // Format for display
    fun formatForDisplay(localDateTime: LocalDateTime): String {
        return localDateTime.format(
            DateTimeFormatter.ofPattern("MMM dd, yyyy")
        )
    }

    // Format for invoices
    fun formatForInvoice(localDateTime: LocalDateTime): String {
        return localDateTime.format(
            DateTimeFormatter.ofPattern("yyyyMMdd")
        )
    }

    // Format week number
    fun formatWeek(localDateTime: LocalDateTime): String {
        val weekOfYear = localDateTime.get(
            java.time.temporal.WeekFields.ISO.weekOfYear()
        )
        return "${localDateTime.year}-W${weekOfYear}"
    }

    // Format quarter
    fun formatQuarter(localDateTime: LocalDateTime): String {
        val quarter = (localDateTime.monthValue - 1) / 3 + 1
        return "${localDateTime.year}-Q$quarter"
    }
}

// Main demonstration
fun demonstrateDateTimeFormatting() {
    println("=== Android Kotlin Date & Time Formatting Examples ===\n")

    val now = LocalDateTime.now()
    val zonedNow = ZonedDateTime.now()
    val date = Date()

    // 1. Basic modern formatting
    println("--- 1. Basic Modern Formatting ---")
    val modernFormatter = ModernDateFormatter()

    println("ISO format: ${modernFormatter.formatToISO(now)}")
    println("Date only: ${modernFormatter.formatDateFull(now)}")
    println("Time only: ${modernFormatter.formatTimeFull(now)}")
    println("Date-time: ${modernFormatter.formatDateTimeFull(now)}")
    println("Short: ${modernFormatter.formatShort(now)}")
    println("With millis: ${modernFormatter.formatWithMillis(now)}")

    // 2. Custom patterns
    println("\n--- 2. Custom Patterns ---")
    println("Custom 1: ${modernFormatter.formatWithPattern(now, "dd/MM/yyyy")}")
    println("Custom 2: ${modernFormatter.formatWithPattern(now, "MM-dd-yyyy HH:mm")}")
    println("Custom 3: ${modernFormatter.formatWithPattern(now, "EEEE, MMMM d, yyyy")}")

    // 3. Localized formatting
    println("\n--- 3. Localized Formatting ---")
    val localizedFormatter = LocalizedFormatter()
    val formattedLocales = localizedFormatter.formatDateInMultipleLocales(now)

    println("Date in different locales:")
    formattedLocales.forEach { (lang, dateStr) ->
        println("  $lang: $dateStr")
    }

    println("\nLocalized date style (English):")
    println("  ${localizedFormatter.formatDateStyle(now, Locale.ENGLISH)}")

    println("\nLocalized time style (English):")
    println("  ${localizedFormatter.formatTimeStyle(now, Locale.ENGLISH)}")

    // 4. Zoned formatting
    println("\n--- 4. Zoned Date-Time Formatting ---")
    val zonedFormatter = ZonedFormatter()

    println("With zone: ${zonedFormatter.formatWithZone(zonedNow)}")
    println("With zone name: ${zonedFormatter.formatWithZoneName(zonedNow)}")
    println("ISO with zone: ${zonedFormatter.formatISOWithZone(zonedNow)}")

    val instant = Instant.now()
    println("\nUTC time: ${zonedFormatter.formatInZone(instant, ZoneId.of("UTC"), "yyyy-MM-dd HH:mm:ss")}")
    println("NY time: ${zonedFormatter.formatInZone(instant, ZoneId.of("America/New_York"), "yyyy-MM-dd HH:mm:ss")}")

    // 5. Legacy formatting
    println("\n--- 5. Legacy Formatting ---")
    val legacyFormatter = LegacyDateFormatter()

    println("Simple: ${legacyFormatter.formatSimple(date, "yyyy-MM-dd")}")
    println("ISO: ${legacyFormatter.formatISO(date)}")
    println("Readable: ${legacyFormatter.formatReadable(date)}")
    println("Long: ${legacyFormatter.formatLong(date)}")

    // 6. Special formats
    println("\n--- 6. Special Formats ---")
    val specialFormatter = SpecialFormatter()

    val past = now.minusHours(2)
    println("Relative time: ${specialFormatter.formatRelative(past)}")

    val duration = java.time.Duration.ofHours(2).plusMinutes(30)
    println("Duration: ${specialFormatter.formatDuration(duration)}")

    println("With ordinal: ${specialFormatter.formatWithOrdinal(now)}")
    println("Timestamp: ${specialFormatter.formatAsTimestamp(now)}")

    // 7. Business formats
    println("\n--- 7. Business Formats ---")
    val businessFormatter = BusinessFormatter()

    println("Log format: ${businessFormatter.formatForLog(now)}")
    println("Filename format: ${businessFormatter.formatForFileName(now)}")
    println("Report format: ${businessFormatter.formatForReport(now)}")
    println("Display format: ${businessFormatter.formatForDisplay(now)}")
    println("Invoice format: ${businessFormatter.formatForInvoice(now)}")
    println("Week format: ${businessFormatter.formatWeek(now)}")
    println("Quarter format: ${businessFormatter.formatQuarter(now)}")

    println("\n=== All Date & Time Formatting Examples Completed ===")
}

💻 日期时间解析 kotlin

🟡 intermediate ⭐⭐⭐⭐

将各种格式的日期时间字符串解析为日期对象

⏱️ 25 min 🏷️ kotlin, android, datetime, parsing
Prerequisites: Intermediate Kotlin, Java Time API
// Android Kotlin Date & Time Parsing Examples
// Using java.time.format (API 26+) and SimpleDateFormat

import java.time.LocalDateTime
import java.time.ZonedDateTime
import java.time.Instant
import java.time.LocalDate
import java.time.LocalTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeParseException
import java.text.SimpleDateFormat
import java.text.ParseException
import java.util.Date
import java.util.Locale

// 1. Basic Parsing Using Modern API
class ModernDateParser {

    // Parse ISO format
    fun parseISO(dateString: String): LocalDateTime? {
        return try {
            LocalDateTime.parse(dateString, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
        } catch (e: DateTimeParseException) {
            println("Error parsing ISO date: ${e.message}")
            null
        }
    }

    // Parse with custom pattern
    fun parseWithPattern(dateString: String, pattern: String): LocalDateTime? {
        return try {
            val formatter = DateTimeFormatter.ofPattern(pattern)
            LocalDateTime.parse(dateString, formatter)
        } catch (e: DateTimeParseException) {
            println("Error parsing date: ${e.message}")
            null
        }
    }

    // Parse date only
    fun parseDate(dateString: String): LocalDate? {
        return try {
            LocalDate.parse(dateString)
        } catch (e: DateTimeParseException) {
            println("Error parsing date: ${e.message}")
            null
        }
    }

    // Parse time only
    fun parseTime(timeString: String): LocalTime? {
        return try {
            LocalTime.parse(timeString)
        } catch (e: DateTimeParseException) {
            println("Error parsing time: ${e.message}")
            null
        }
    }

    // Parse zoned date-time
    fun parseZoned(dateString: String): ZonedDateTime? {
        return try {
            ZonedDateTime.parse(dateString, DateTimeFormatter.ISO_ZONED_DATE_TIME)
        } catch (e: DateTimeParseException) {
            println("Error parsing zoned date: ${e.message}")
            null
        }
    }

    // Parse with multiple patterns
    fun parseWithPatterns(dateString: String, patterns: List<String>): LocalDateTime? {
        for (pattern in patterns) {
            try {
                val formatter = DateTimeFormatter.ofPattern(pattern)
                return LocalDateTime.parse(dateString, formatter)
            } catch (e: DateTimeParseException) {
                // Try next pattern
            }
        }
        println("Could not parse date with any pattern")
        return null
    }
}

// 2. Localized Parsing
class LocalizedParser {

    // Parse with locale
    fun parseWithLocale(dateString: String, pattern: String, locale: Locale): LocalDateTime? {
        return try {
            val formatter = DateTimeFormatter.ofPattern(pattern, locale)
            LocalDateTime.parse(dateString, formatter)
        } catch (e: DateTimeParseException) {
            println("Error parsing localized date: ${e.message}")
            null
        }
    }

    // Parse from different locales
    fun parseFromMultipleLocales(
                    dateString: String,
                    pattern: String
    ): Map<String, LocalDateTime?> {
        val locales = listOf(
            "en" to Locale.ENGLISH,
            "zh" to Locale.CHINESE,
            "es" to Locale("es"),
            "fr" to Locale.FRENCH,
            "de" to Locale.GERMAN
        )

        return locales.mapValues { (_, locale) ->
            try {
                val formatter = DateTimeFormatter.ofPattern(pattern, locale)
                LocalDateTime.parse(dateString, formatter)
            } catch (e: DateTimeParseException) {
                null
            }
        }
    }
}

// 3. Legacy Parsing (SimpleDateFormat)
class LegacyDateParser {

    // Simple parse
    fun parseSimple(dateString: String, pattern: String): Date? {
        return try {
            val formatter = SimpleDateFormat(pattern)
            formatter.parse(dateString)
        } catch (e: ParseException) {
            println("Error parsing date: ${e.message}")
            null
        }
    }

    // Parse with locale
    fun parseWithLocale(dateString: String, pattern: String, locale: Locale): Date? {
        return try {
            val formatter = SimpleDateFormat(pattern, locale)
            formatter.parse(dateString)
        } catch (e: ParseException) {
            println("Error parsing localized date: ${e.message}")
            null
        }
    }

    // Lenient parsing
    fun parseLenient(dateString: String, pattern: String): Date? {
        return try {
            val formatter = SimpleDateFormat(pattern)
            formatter.isLenient = false
            formatter.parse(dateString)
        } catch (e: ParseException) {
            println("Error parsing date (strict): ${e.message}")
            null
        }
    }

    // Parse to Calendar
    fun parseToCalendar(dateString: String, pattern: String): Calendar? {
        return try {
            val formatter = SimpleDateFormat(pattern)
            val date = formatter.parse(dateString)
            val calendar = Calendar.getInstance()
            calendar.time = date
            calendar
        } catch (e: ParseException) {
            println("Error parsing to calendar: ${e.message}")
            null
        }
    }
}

// 4. Parsing Special Formats
class SpecialFormatParser {

    // Parse Unix timestamp
    fun parseUnixTimestamp(timestamp: Long): LocalDateTime {
        return LocalDateTime.ofInstant(
            Instant.ofEpochSecond(timestamp),
            ZoneId.systemDefault()
        )
    }

    // Parse timestamp in milliseconds
    fun parseTimestampMillis(millis: Long): LocalDateTime {
        return LocalDateTime.ofInstant(
            Instant.ofEpochMilli(millis),
            ZoneId.systemDefault()
        )
    }

    // Parse Excel date serial
    fun parseExcelSerial(serial: Double): LocalDateTime {
        // Excel epoch is 1900-01-01, but with a bug (1900 is a leap year)
        val days = (serial - 25569).toLong() // Adjust to Unix epoch
        val seconds = days * 86400
        return LocalDateTime.ofInstant(
            Instant.ofEpochSecond(seconds),
            ZoneId.systemDefault()
        )
    }

    // Parse ISO 8601 with zone
    fun parseISO8601WithZone(dateString: String): ZonedDateTime? {
        return try {
            ZonedDateTime.parse(dateString)
        } catch (e: DateTimeParseException) {
            println("Error parsing ISO 8601: ${e.message}")
            null
        }
    }

    // Parse RFC 2822 date
    fun parseRFC2822(dateString: String): LocalDateTime? {
        val pattern = "EEE, dd MMM yyyy HH:mm:ss Z"
        return try {
            val formatter = DateTimeFormatter.ofPattern(pattern, Locale.ENGLISH)
            LocalDateTime.parse(dateString, formatter)
        } catch (e: DateTimeParseException) {
            println("Error parsing RFC 2822: ${e.message}")
            null
        }
    }

    // Parse relative date
    fun parseRelativeDate(relative: String): LocalDateTime? {
        val now = LocalDateTime.now()
        val pattern = Regex("([+-]?\\d+)\\s+(day|hour|minute|second)s?")

        return pattern.find(relative)?.let { match ->
            val amount = match.groupValues[1].toInt()
            val unit = match.groupValues[2]

            when (unit) {
                "day" -> now.plusDays(amount.toLong())
                "hour" -> now.plusHours(amount.toLong())
                "minute" -> now.plusMinutes(amount.toLong())
                "second" -> now.plusSeconds(amount.toLong())
                else -> null
            }
        }
    }
}

// 5. Flexible Parsing
class FlexibleParser {

    // Try multiple date formats
    fun parseAutoDetect(dateString: String): LocalDateTime? {
        val formats = listOf(
            "yyyy-MM-dd HH:mm:ss",
            "yyyy-MM-dd",
            "MM/dd/yyyy",
            "dd-MM-yyyy",
            "yyyy/MM/dd HH:mm",
            "MMM dd, yyyy",
            "dd MMM yyyy",
            "yyyy-MM-dd'T'HH:mm:ss",
            "ISO_OFFSET_DATE_TIME"
        )

        for (format in formats) {
            try {
                return when (format) {
                    "ISO_OFFSET_DATE_TIME" -> {
                        val zoned = ZonedDateTime.parse(dateString)
                        zoned.toLocalDateTime()
                    }
                    else -> {
                        val formatter = DateTimeFormatter.ofPattern(format)
                        LocalDateTime.parse(dateString, formatter)
                    }
                }
            } catch (e: Exception) {
                // Try next format
            }
        }

        println("Could not auto-detect format")
        return null
    }

    // Parse with fallback
    fun parseWithFallback(
                    dateString: String,
                    primaryPattern: String,
                    fallbackPattern: String
    ): LocalDateTime? {
        return parseWithPattern(dateString, primaryPattern)
            ?: parseWithPattern(dateString, fallbackPattern)
    }

    private fun parseWithPattern(dateString: String, pattern: String): LocalDateTime? {
        return try {
            val formatter = DateTimeFormatter.ofPattern(pattern)
            LocalDateTime.parse(dateString, formatter)
        } catch (e: DateTimeParseException) {
            null
        }
    }

    // Parse with normalization
    fun parseWithNormalization(dateString: String): LocalDateTime? {
        // Normalize: remove extra spaces, standardize separators
        val normalized = dateString
            .trim()
            .replace(Regex("\\s+"), " ")
            .replace("/", "-")
            .replace(".", "-")

        return parseAutoDetect(normalized)
    }
}

// 6. Validation and Sanitization
class DateInputValidator {

    // Validate date format
    fun isValidFormat(dateString: String, pattern: String): Boolean {
        return try {
            val formatter = DateTimeFormatter.ofPattern(pattern)
            LocalDateTime.parse(dateString, formatter)
            true
        } catch (e: DateTimeParseException) {
            false
        }
    }

    // Validate and parse
    fun validateAndParse(dateString: String, pattern: String): LocalDateTime? {
        return if (isValidFormat(dateString, pattern)) {
            parseWithPattern(dateString, pattern)
        } else {
            null
        }
    }

    private fun parseWithPattern(dateString: String, pattern: String): LocalDateTime? {
        return try {
            val formatter = DateTimeFormatter.ofPattern(pattern)
            LocalDateTime.parse(dateString, formatter)
        } catch (e: DateTimeParseException) {
            null
        }
    }

    // Sanitize date input
    fun sanitizeDateInput(dateString: String): String {
        return dateString
            .trim()
            .replace(Regex("\\s+"), " ")
            .replace(Regex("[^\\d\\w\\s:-]"), "")
    }

    // Check if date is reasonable
    fun isReasonableDate(localDateTime: LocalDateTime): Boolean {
        val now = LocalDateTime.now()
        val year = localDateTime.year

        return year in 1900..2100 &&
               !localDateTime.isAfter(now.plusYears(10))
    }
}

// Main demonstration
fun demonstrateDateTimeParsing() {
    println("=== Android Kotlin Date & Time Parsing Examples ===\n")

    val parser = ModernDateParser()

    // 1. Basic parsing
    println("--- 1. Basic Parsing ---")
    val isoDate = "2025-12-27T10:30:00"
    val parsed1 = parser.parseISO(isoDate)
    println("Parse ISO: $isoDate")
    println("Result: $parsed1")

    val customDate = "2025-12-27 14:30:45"
    val parsed2 = parser.parseWithPattern(customDate, "yyyy-MM-dd HH:mm:ss")
    println("\nParse custom: $customDate")
    println("Result: $parsed2")

    val dateOnly = "2025-12-27"
    val parsed3 = parser.parseDate(dateOnly)
    println("\nParse date only: $dateOnly")
    println("Result: $parsed3")

    // 2. Multiple patterns
    println("\n--- 2. Try Multiple Patterns ---")
    val ambiguousDate = "12/27/2025"
    val patterns = listOf("MM/dd/yyyy", "dd/MM/yyyy", "yyyy/MM/dd")
    val parsed4 = parser.parseWithPatterns(ambiguousDate, patterns)
    println("Parse '$ambiguousDate' with patterns:")
    patterns.forEach { println("  - $it") }
    println("Result: $parsed4")

    // 3. Localized parsing
    println("\n--- 3. Localized Parsing ---")
    val localizedParser = LocalizedParser()
    val englishDate = "December 27, 2025"
    val parsed5 = localizedParser.parseWithLocale(englishDate, "MMMM dd, yyyy", Locale.ENGLISH)
    println("English date: $englishDate")
    println("Parsed: $parsed5")

    // 4. Special formats
    println("\n--- 4. Special Formats ---")
    val specialParser = SpecialFormatParser()

    val timestamp = 1735300200L
    val parsed6 = specialParser.parseUnixTimestamp(timestamp)
    println("Unix timestamp: $timestamp")
    println("Result: $parsed6")

    val millis = 1735300200000L
    val parsed7 = specialParser.parseTimestampMillis(millis)
    println("\nMillis: $millis")
    println("Result: $parsed7")

    val isoZoned = "2025-12-27T10:30:00+02:00"
    val parsed8 = specialParser.parseISO8601WithZone(isoZoned)
    println("\nISO 8601 with zone: $isoZoned")
    println("Result: $parsed8")

    // 5. Flexible parsing
    println("\n--- 5. Flexible Parsing ---")
    val flexibleParser = FlexibleParser()

    val unknownFormat = "2025/12/27 10:30"
    val parsed9 = flexibleParser.parseAutoDetect(unknownFormat)
    println("Auto-detect format: $unknownFormat")
    println("Result: $parsed9")

    val normalized = " 2025 - 12 - 27  "
    val parsed10 = flexibleParser.parseWithNormalization(normalized)
    println("\nNormalize and parse: '$normalized'")
    println("Result: $parsed10")

    // 6. Validation
    println("\n--- 6. Validation ---")
    val validator = DateInputValidator()

    val validDate = "2025-12-27"
    val invalidDate = "2025-13-45"

    println("'$validDate' valid format: ${validator.isValidFormat(validDate, "yyyy-MM-dd")}")
    println("'$invalidDate' valid format: ${validator.isValidFormat(invalidDate, "yyyy-MM-dd")}")

    val parsed11 = validator.validateAndParse(validDate, "yyyy-MM-dd")
    println("\nValidate and parse: $parsed11")

    val reasonable = LocalDateTime.of(2025, 12, 27, 10, 30)
    println("\nIs reasonable: ${validator.isReasonableDate(reasonable)}")

    // 7. Legacy parsing
    println("\n--- 7. Legacy Parsing ---")
    val legacyParser = LegacyDateParser()

    val legacyDate = "27/12/2025 10:30"
    val parsed12 = legacyParser.parseSimple(legacyDate, "dd/MM/yyyy HH:mm")
    println("Legacy parse: $legacyDate")
    println("Result: $parsed12")

    println("\n=== All Date & Time Parsing Examples Completed ===")
}