如何获取UTC时区下带三位小数秒的OffsetDateTime对象?
如何生成带三位小数秒的UTC时区OffsetDateTime对象?
原代码生成的OffsetDateTime会带六位小数秒:
OffsetDateTime offsetDateTime = OffsetDateTime.now(ZoneId.of("UTC"));
我需要一个工具方法,返回当前UTC时区下、仅带三位小数秒的OffsetDateTime对象(示例:2023-05-15T02:22:39.330Z)。但尝试下面的代码后,返回结果还是带六位小数秒:
public static OffsetDateTime offsetDateTimeUtc(){ OffsetDateTime offsetDateTime = OffsetDateTime.now(ZoneId.of("UTC")); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("YYYY-MM-dd'T'HH:mm:ss.SSS'Z'"); return OffsetDateTime.parse(offsetDateTime.toString()); }
问题原因
你写的代码根本没用到自己定义的DateTimeFormatter——offsetDateTime.toString()默认会输出完整精度的ISO-8601字符串(比如2023-05-15T02:22:39.330123Z),解析后自然还是保留六位小数。
可行解决方案
不需要绕格式化解析的弯路,直接对时间对象的精度做处理即可,推荐两种方式:
方法一:截断到毫秒级(直接保留前三位小数)
最简单高效的方式,直接舍去毫秒之后的所有精度:
public static OffsetDateTime offsetDateTimeUtc() { return OffsetDateTime.now(ZoneId.of("UTC")) .truncatedTo(ChronoUnit.MILLIS); }
方法二:四舍五入到毫秒级
如果需要对小数部分做四舍五入处理,可以手动计算调整:
public static OffsetDateTime offsetDateTimeUtc() { OffsetDateTime now = OffsetDateTime.now(ZoneId.of("UTC")); long currentMillis = now.getLong(ChronoField.MILLI_OF_SECOND); long currentNanos = now.getLong(ChronoField.NANO_OF_SECOND); // 计算四舍五入后的毫秒值 long roundedMillis = currentMillis + (currentNanos >= 500_000 ? 1 : 0); // 处理毫秒满1000需要进位到秒的情况 if (roundedMillis == 1000) { return now.plusSeconds(1).with(ChronoField.MILLI_OF_SECOND, 0); } return now.with(ChronoField.MILLI_OF_SECOND, roundedMillis); }
(可选)格式化解析的正确写法
如果一定要用格式化解析的方式,得确保用自己定义的DateTimeFormatter来格式化原对象,而不是调用默认的toString():
public static OffsetDateTime offsetDateTimeUtc() { OffsetDateTime offsetDateTime = OffsetDateTime.now(ZoneId.of("UTC")); // 注意用yyyy而非YYYY(YYYY是周年,日常用yyyy表示年份),用X自动处理UTC偏移量 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX"); String formattedStr = formatter.format(offsetDateTime); return OffsetDateTime.parse(formattedStr, formatter); }
不过这种方式涉及字符串操作,性能不如直接截断/舍入。
内容的提问来源于stack exchange,提问作者Naim
相关产品推荐
相关产品推荐

