Java String转Date无时区问题:Android与Spring控制器时间不一致
问题分析与解决方案
为什么会出现时间差异?
这完全是时区不一致导致的问题,拆解来看有两个核心原因:
- Android端的时区绑定:你用
Locale.getDefault()初始化SimpleDateFormat时,它会自动使用设备当前时区(也就是你这里的GMT+07:00)。解析200901时,它默认把这个字符串当成当前时区下的2020年9月1日0点(yy格式会取当前世纪的后两位,所以20对应2020年)。但Date对象本质是UTC时间戳,存储的是从1970年1月1日UTC开始的毫秒数——这个GMT+7的0点,对应UTC时间就是2020年8月31日17:00。 - Spring服务器的时区解析:你的服务器时区是GMT+03:00,当它接收这个
Date对象(本质是UTC时间戳),会用自己的时区去转换显示:UTC的17:00加上3小时就是20:00,日期自然变成了8月31日,也就是你看到的Mon Aug 31 20:00:00 GMT+03:00。
另外还要提个坑:SimpleDateFormat是线程不安全的,而且yy格式存在世纪歧义(比如09可能被解析成2009还是2029?完全取决于当前系统时间,非常不稳定)。
怎么解决这个问题?
第一步:替换老旧的日期工具,统一时区
放弃SimpleDateFormat,改用Java 8+的java.time包(Android API 26+原生支持,低版本可以用ThreeTenABP兼容),它线程安全,时区处理也更清晰。
Android端修改后的代码:
// 指定统一时区(推荐用UTC,或者你们业务约定的固定时区) private static final DateTimeFormatter CARD_DATE_FORMAT = DateTimeFormatter.ofPattern("yyMMdd") .withZone(ZoneId.of("UTC")); public static Instant toCardDateFormat(String date) { try { // 先解析为本地日期,再转成UTC时区的Instant(标准时间戳对象) LocalDate localDate = LocalDate.parse(date, CARD_DATE_FORMAT); return localDate.atStartOfDay(ZoneId.of("UTC")).toInstant(); } catch (DateTimeParseException e) { return null; } }
第二步:统一Spring服务器的时区配置
确保服务器和客户端用相同的时区处理日期,推荐用UTC作为全局统一时区,避免混乱:
- 在Spring Boot的
application.properties中添加配置:
# 设置全局时区为UTC spring.jackson.time-zone=UTC # 统一日期序列化格式为ISO 8601标准格式 spring.jackson.date-format=yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
- 如果是接收请求参数,给日期参数明确指定时区:
@PostMapping("/submit") public ResponseEntity<?> submitDate( @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME, timezone = "UTC") Instant date) { // 业务逻辑处理 return ResponseEntity.ok(date); }
第三步:传输时用标准ISO 8601字符串
尽量避免直接传输Date对象(序列化/反序列化时极易受时区影响),转而传输ISO 8601格式的字符串(比如2020-09-01T00:00:00Z,Z代表UTC时区),这样两端解析时都能明确时区,不会出错。
Android端转成标准字符串的示例:
Instant instant = toCardDateFormat("200901"); String isoDateStr = DateTimeFormatter.ISO_INSTANT.format(instant); // 把这个isoDateStr传给服务器即可
Spring控制器直接接收并解析:
@PostMapping("/submit") public ResponseEntity<?> submitDate(@RequestParam String dateStr) { Instant date = Instant.parse(dateStr); // 业务逻辑处理 return ResponseEntity.ok(date); }
这样就能彻底解决时区不一致导致的时间差异问题啦!
内容的提问来源于stack exchange,提问作者ip696
相关产品推荐
相关产品推荐

