Android API 34下SimpleDateFormat解析GMT日期抛ParseException求助
问题分析
在Android API Level 34中,SimpleDateFormat的解析行为更严格——默认会使用设备系统Locale,若系统Locale非英文,就无法匹配输入字符串里的英文星期(Mon)和月份(Sep)缩写,从而抛出ParseException。API33及以下版本对Locale兼容更宽松,因此未触发该问题。
解决方法
方法1:为SimpleDateFormat指定英文Locale
直接修改现有代码,显式传入Locale.ENGLISH,确保解析时用英文规则匹配日期格式:
fun calculateAge(dateString: String): String { // 显式指定英文Locale,避免系统Locale影响解析 val dateFormat = SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH) dateFormat.timeZone = TimeZone.getTimeZone("GMT") val inputDate = dateFormat.parse(dateString) ?: return "Invalid date" // 增加空判断防止NPE val currentCalendar = Calendar.getInstance() val inputCalendar = Calendar.getInstance().apply { time = inputDate } val years = currentCalendar.get(Calendar.YEAR) - inputCalendar.get(Calendar.YEAR) val months = currentCalendar.get(Calendar.MONTH) - inputCalendar.get(Calendar.MONTH) val days = currentCalendar.get(Calendar.DAY_OF_MONTH) - inputCalendar.get(Calendar.DAY_OF_MONTH) return when { years > 0 -> "$years years" months > 0 -> "$months months" days > 0 -> "$days days" else -> "0 days" } }
方法2:迁移到Java 8+的java.time API(推荐)
SimpleDateFormat和Calendar属于过时且线程不安全的类,Android API 26+(Android 8.0)原生支持java.time现代日期API,API26以下可通过开启Core Library Desugaring兼容。
修改后的代码如下:
import java.time.ZonedDateTime import java.time.format.DateTimeFormatter import java.time.temporal.ChronoUnit fun calculateAge(dateString: String): String { // 使用预定义的RFC_1123格式,完全匹配输入的日期字符串 val formatter = DateTimeFormatter.RFC_1123_DATE_TIME val inputDate = ZonedDateTime.parse(dateString, formatter) val currentDate = ZonedDateTime.now(inputDate.zone) val years = ChronoUnit.YEARS.between(inputDate, currentDate) val months = ChronoUnit.MONTHS.between(inputDate, currentDate) % 12 val days = ChronoUnit.DAYS.between(inputDate, currentDate) % 30 // 如需精确天数可调整计算逻辑 return when { years > 0 -> "$years years" months > 0 -> "$months months" days > 0 -> "$days days" else -> "0 days" } }
该方案稳定性更高、可读性更强,且无线程安全问题,是长期维护的最优选择。
内容的提问来源于stack exchange,提问作者MARSH
相关产品推荐
相关产品推荐

