如何打印带时区且不含URL非法字符的ZonedDateTime字符串
问题描述
- 业务场景需要在URL参数中传递日期,要求日期字符串不能包含连字符
-、斜杠/、冒号:这类特殊符号 - 最初判断
20220615T160543Z是唯一适配的格式,但该格式固定使用UTC时区,无法满足其他时区的传参需求 - 初始疑问:是否存在类似
20220615T160543+2:00、通过+2:00字段标识UTC时区偏移的格式?如果存在该格式,能否直接从ZonedDateTime对象输出对应格式字符串?
当前获取ZonedDateTime实例的代码如下:
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(date.getStartsOn().toInstant(), timezone);
结论说明
你最初设想的带偏移量的格式本身属于ISO 8601标准定义的合法日期格式,但实际落地时存在无法规避的问题:负时区偏移场景下会生成20220615T160543-2:00这类带连字符的结果,偏移量部分的冒号也属于URL禁止直接传递的特殊字符,哪怕自定义格式化器去掉偏移量中的冒号,负偏移自带的连字符依然会违反传参规则,强行替换特殊字符会生成非标准日期格式,后续跨端、跨服务解析时极易出现兼容性问题。
目前唯一稳妥的可行方案是使用百分号URL编码处理标准格式的日期字符串,不需要为了适配URL规则修改日期本身的格式:
- 先使用标准日期格式化器将
ZonedDateTime输出为合法的ISO 8601格式字符串 - 对生成的字符串直接做URL编码,编码后所有特殊字符都会被转义为URL兼容的格式
- 服务端接收参数时,先做URL解码再按标准ISO 8601格式解析即可,不需要额外适配自定义格式
参考实现代码:
import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.time.format.DateTimeFormatter; // 格式化输出标准带偏移的日期字符串 String standardDateStr = zonedDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); // 直接做URL编码得到URL安全的参数值 String urlSafeDateParam = URLEncoder.encode(standardDateStr, StandardCharsets.UTF_8);
不要为了绕开特殊字符自定义非标准日期格式,这类方案短期看能跑通,后续对接其他语言、其他服务时会出现大量解析兼容问题,URL编码是URL参数特殊字符处理的通用标准方案,不存在兼容风险。
内容的提问来源于stack exchange,提问作者Snookums
相关产品推荐
相关产品推荐

