如何在Groovy中实现已废弃Date.parse()的相同输出效果?
问题:替代废弃的Date.parse()方法并保持一致输出
我有一个运行旧版本Spring框架的应用,该应用原本使用已废弃的Date.parse()方法创建日期对象,代码如下:
Date getCstTimeZoneDateNow() { String dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" def zonedDateString = new Date().format(dateFormat, TimeZone.getTimeZone('CST')) Date date = Date.parse(dateFormat, zonedDateString) return date // Tue Oct 18 20:36:12 EDT 2022 (in Date) }
现在需要实现与该废弃代码完全相同的输出结果。我尝试使用SimpleDateFormat,但解析后的日期对象时区与原结果不符:
Date getCstTimeZoneDateNow() { Date now = new Date() String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" SimpleDateFormat sdf = new SimpleDateFormat() sdf.setTimeZone(TimeZone.getTimeZone('CST')) // cstDateTime prints times in cst String cstDateTime = sdf.format(now) // 2022-10-18T20:36:12.088Z (in String) // JVM current time Date date = sdf.parse(cstDateTime) // Tue Oct 18 21:36:12 EDT 2022 (in Date) return date }
我的目标是返回格式为Tue Oct 18 20:36:12 EDT 2022的日期对象,但目前解析后的时区存在偏差。请问如何实现与原废弃代码完全一致的效果,不限于使用SimpleDateFormat?
解决方案
核心逻辑分析
原代码的本质是:
- 将当前时间(
Date本质是时间戳)转换为CST时区的格式化字符串(其中Z是固定字面量,不是时区标识); - 调用
Date.parse()解析该字符串时,会使用JVM默认时区解析字符串中的日期时间值,而非格式化时的CST时区。
你的尝试错误在于用同一个SimpleDateFormat(设置了CST时区)同时做格式化和解析,导致解析时把字符串当作CST时间处理,最终时间戳和原代码不一致。
方案1:使用SimpleDateFormat还原原逻辑
分开使用两个SimpleDateFormat:一个用于CST时区格式化,另一个用默认时区解析,完全对齐原代码行为:
Date getCstTimeZoneDateNow() { String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" // 1. 用CST时区格式化当前时间 SimpleDateFormat cstFormatter = new SimpleDateFormat(pattern) cstFormatter.setTimeZone(TimeZone.getTimeZone("America/Chicago")) // 用具体时区ID替代歧义的CST String cstDateTime = cstFormatter.format(new Date()) // 2. 用JVM默认时区解析字符串,模拟Date.parse()的行为 SimpleDateFormat defaultParser = new SimpleDateFormat(pattern) Date resultDate = defaultParser.parse(cstDateTime) return resultDate // 输出与原代码完全一致:Tue Oct 18 20:36:12 EDT 2022 }
注意:
CST是歧义时区缩写(可能对应中国标准时间、美国中部时间等),建议使用具体时区ID(如America/Chicago)避免意外问题。
方案2:使用Java 8+时间API(推荐,无废弃API)
如果项目允许使用Java 8及以上的时间API,可以更清晰地模拟原逻辑:
Date getCstTimeZoneDateNow() { String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" ZoneId cstZone = ZoneId.of("America/Chicago") ZoneId defaultZone = ZoneId.systemDefault() // 1. 格式化当前时间为CST时区的字符串 String cstDateTime = DateTimeFormatter.ofPattern(pattern) .withZone(cstZone) .format(Instant.now()) // 2. 用默认时区解析字符串,转换为Date对象 LocalDateTime localDateTime = LocalDateTime.parse(cstDateTime, DateTimeFormatter.ofPattern(pattern)) ZonedDateTime zonedDateTime = localDateTime.atZone(defaultZone) return Date.from(zonedDateTime.toInstant()) }
这个方案通过类型安全的时间API实现相同逻辑,同时避免了Date、SimpleDateFormat这类线程不安全的废弃类。
内容的提问来源于stack exchange,提问作者Gwenda Thomas
相关产品推荐
相关产品推荐

