You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将ISO8601字符串转Epoch毫秒遇解析错误,求兼容API26的方案

解决ISO8601字符串转毫秒的解析错误与低API兼容问题

Hey there! Let's tackle your problem head-on—you're hitting two key issues here: a parsing error caused by missing timezone information, and an API level 26 restriction on Instant.toEpochMilli(). Here's how to fix both, with solid options for different use cases:

Why the parsing error happens

Your input string 2019-02-15T00:00:00 doesn't include a timezone identifier (like Z for UTC or +08:00 for GMT+8). The Instant class expects explicit timezone data, so it chokes at index 19 (the end of the string) where it can't find that critical info.

This is the official Android-compatible implementation of the JSR 310 date/time APIs (the same ones used in API 26+), and it works back to API 16. It's far more reliable than legacy classes like SimpleDateFormat.

Step 1: Add the dependency

Add this to your app-level build.gradle (or build.gradle.kts):

implementation 'com.jakewharton.threetenabp:threetenabp:1.4.6'

Step 2: Initialize the library

In your Application class:

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}

Don't forget to declare this Application class in your AndroidManifest.xml if you haven't already.

Step 3: Parse and convert to milliseconds

import org.threeten.bp.LocalDateTime
import org.threeten.bp.ZoneOffset
import org.threeten.bp.ZonedDateTime

val dateStr = "2019-02-15T00:00:00"

// Parse the string into a LocalDateTime (since it has no timezone)
val localDateTime = LocalDateTime.parse(dateStr)

// Attach a timezone—use ZoneOffset.UTC for universal time, or ZoneId.systemDefault() for local timezone
val zonedDateTime = localDateTime.atZone(ZoneOffset.UTC)

// Convert to milliseconds since epoch
val millisecondsSinceUnixEpoch = zonedDateTime.toInstant().toEpochMilli()
println("EPOCH $millisecondsSinceUnixEpoch")

Solution 2: Use SimpleDateFormat (No Third-Party Library)

If you don't want to add a dependency, you can use the legacy SimpleDateFormat—just be aware it's not thread-safe, so wrap it in a ThreadLocal if you're using it in multi-threaded contexts like coroutines or background tasks.

import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*

val dateStr = "2019-02-15T00:00:00"

// Define the format matching your input string
val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US)
// Set the timezone to ensure consistent parsing—use UTC unless your business logic requires local time
sdf.timeZone = TimeZone.getTimeZone("UTC")

try {
    val date = sdf.parse(dateStr)
    val millisecondsSinceUnixEpoch = date?.time ?: 0 // date.time gives epoch milliseconds
    println("EPOCH $millisecondsSinceUnixEpoch")
} catch (e: ParseException) {
    // Handle parsing failure
    e.printStackTrace()
}

Final Notes

  • Prefer ThreeTenABP for most cases: it avoids the pitfalls of SimpleDateFormat (like thread unsafety and weird edge cases with date parsing) and aligns with modern date/time best practices.
  • Always be explicit about timezones: whether you use UTC or local time, make sure it's intentional—ambiguous timezones are a common source of bugs.

内容的提问来源于stack exchange,提问作者Jodi Shane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:28:20