Android使用java.util.Date生成时间戳输出阿拉伯文数字问题修复
问题现象
- 应用向API发送遥测事件时,伊朗地区用户上报的时间戳为
"۲۰۲۲-۰۷-۰۶T۰۰:۰۳:۳۳.۳۹۰Z"格式,服务端解析失败抛出异常。
服务端返回的异常信息如下:
Exception while executing function: LogTelemetry Could not convert string to DateTimeOffset: ۲۰۲۲-۰۷-۰۶T۰۰:۰۳:۳۳.۳۹۰Z. Path 'appTimestamp', line 1, position 54.
- 本地测试将Locale切换为阿拉伯语无法复现该问题,当前代码中日期格式化器的Locale配置为
Locale.getDefault()。
现有实现
当前时间戳生成的Kotlin代码:
fun getGMTTImeStamp(): String { val formatter2 = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.getDefault()) formatter2.timeZone = TimeZone.getTimeZone("GMT") val date = Date() return (formatter2.format(date) + "Z") }
上报数据的JSON结构示例:
{ "action":6, "appTimestamp":"2022-07-08T08:36:45.454Z", "deviceId":"6d0ae55186cd5efc", "origin":3, "originId":"3c945925-53ac-4fbe-9266-210410903a85", "platform":0 }
根因分析
- 伊朗地区设备的默认系统Locale为波斯语(
fa_IR),该Locale下SimpleDateFormat格式化日期时,会自动将数字替换为波斯语本地使用的波斯-阿拉伯数字(即报错信息中的۲۰۲۲这类非拉丁数字字符),而服务端默认按0-9拉丁数字规则解析时间戳,直接触发类型转换失败。 - 本地切换阿拉伯语Locale无法复现的原因:阿拉伯语使用的数字变体、格式化规则和波斯语Locale存在差异,没有命中波斯语环境下的数字转本地字符逻辑。
修复方案
- 所有用于跨服务、跨端传输的标准化时间戳生成场景,禁止使用跟随系统配置的
Locale.getDefault(),必须指定通用的Locale.US作为日期格式化器的Locale参数,强制输出0-9拉丁数字格式的时间串,修复后的代码如下:
fun getGMTTimeStamp(): String { // 修正原方法名拼写错误:原方法名中TIme为拼写错误,应为Time val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US) formatter.timeZone = TimeZone.getTimeZone("GMT") return formatter.format(Date()) + "Z" }
- 若项目Android API等级≥26(或启用了Java 8+时间API脱糖),建议替换为线程安全的
java.time标准时间API,直接生成符合ISO 8601规范的UTC时间戳,从根源规避旧Date类API的适配问题,示例代码:
import java.time.Instant import java.time.format.DateTimeFormatter fun getGMTTimeStamp(): String { // 内置ISO_INSTANT格式化器默认输出UTC时间,无需手动拼接Z后缀 return DateTimeFormatter.ISO_INSTANT.format(Instant.now()) }
内容的提问来源于stack exchange,提问作者Wayne Whitehead
相关产品推荐
相关产品推荐

