如何获取ZonedDateTime对应时区下的当日起始时间
如何获取ZonedDateTime所属时区对应的当日起始时间
给定一个ZonedDateTime实例,需要获取该时间所属时区本身对应的当日起始(零点)时间,不需要转换为UTC时区计算日起始点。
常规示例
给定输入:
ZonedDateTime.of(2022, 6, 8, 1, 0, 0, 0, ZoneId.of("America/New_York"))
期望返回:
ZonedDateTime.of(2022, 6, 7, 0, 0, 0, 0, ZoneId.of("America/New_York"))
原因:该时间点对应UTC时间6月8日凌晨1点,换算为美国东部时间(ET)为6月7日晚9点,我们需要取输入时间所在时区的当日0点,而非UTC时区的日起始点。
夏令时场景示例
给定输入:
ZonedDateTime.of(2022, 6, 8, 6, 0, 0, 0, ZoneId.of("America/New_York"))
期望返回:
ZonedDateTime.of(2022, 6, 8, 0, 0, 0, 0, ZoneId.of("America/New_York"))
原因:该时间点对应UTC时间6月8日早6点,换算为美国东部时间(ET)为6月8日凌晨2点,此时纽约正处于夏令时时段,需要取输入时间所在时区的当日0点。
实现方案
直接使用Java 8 日期时间API内置的atStartOfDay方法即可,该方法会自动处理夏令时跳时、时区偏移等特殊场景,不会出现跨时区计算错误:
public static ZonedDateTime getDayStartInOwnZone(ZonedDateTime source) { // 先获取该时间在自身所属时区下的本地日期,再调用方法取对应时区的当日起始 return source.toLocalDate().atStartOfDay(source.getZone()); }
注意避坑
- 不要先将
ZonedDateTime转换为Instant再做日期计算,该路径会默认基于UTC时区做偏移,最终得到的是UTC时区的日起始点,不符合需求 - 不要手动链式调用
withHour(0).withMinute(0).withSecond(0).withNano(0)来重置时间:部分时区夏令时切换当天不存在0点(比如跳时直接从0点跳到1点),手动设值会抛出异常或者返回错误偏移量的时间 atStartOfDay(ZoneId)方法已经内置了全量时区规则适配,如果当天0点不存在,会自动返回对应时区规则下的合法日起始时间,无需额外处理边界场景
内容的提问来源于stack exchange,提问作者user7340
相关产品推荐
相关产品推荐

