使用我的库
Time4J(v3.x适用于Java 7 - 或者在Android上使用Time4A)将为您提供完整的解决方案,包括对不同时区的格式化和解析的广泛支持。 示例:
Moment m1 = TemporalType.JAVA_UTIL_DATE.translate(d1);
Moment m2 = TemporalType.JAVA_UTIL_DATE.translate(d2);
System.out.println("Time4J - from j.u.Date: " + SI.SECONDS.between(m1, m2));
m1 = PlainTimestamp.of(2012, 6, 30, 23, 50, 0).atUTC();
m2 = PlainTimestamp.of(2012, 7, 1, 0, 0, 0).atUTC();
System.out.println("Time4J - from utc-timestamps: " + SI.SECONDS.between(m1, m2));
ChronoFormatter<Moment> cf =
ChronoFormatter.ofMomentPattern(
"d. MMM uuuu HH:mm:ss[XXX]",
PatternType.CLDR,
Locale.ENGLISH,
EUROPE.PARIS);
m1 = cf.parse("1. Jul 2015 01:50:00");
m2 = cf.parse("1. Jul 2015 09:00:00+09:00");
System.out.println("Time4J - from offsets or zones: " + SI.SECONDS.between(m1, m2));
Moment ls = cf.parse("1. Jul 2015 08:59:60+09:00");
System.out.println("leap second in 2015: " + ls);
更值得一提的是,Time4J支持时钟意识到闰秒,并且可以从IANA-TZDB传输闰秒数据。请参见我在
DZone上的文章中的示例。请注意,Time4J可以完全替代ThreetenBP,但也与Java-8互操作(只需将版本更改为v4.x),并提供了许多超出本问题范围的其他功能。
侧记:大多数人显然选择ThreetenBP是为了使未来迁移到Java-8更容易(只需更改一些导入语句)。但是,您的情况问题在于:
- Java标准(任何版本)本身不知道闰秒(甚至没有必要的数据)。
- 建议使用的其他第三方库Threeten-Extra无法在Java-7上工作。它需要Java-8。
迁移到Java-8后,Threeten-Extra似乎提供了解决方案。然而,我现在已经进行了自己的测试,并建议不要使用该库,请参见以下代码:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
Date d1 = sdf.parse("2012-06-30T23:50:00Z");
Date d2 = sdf.parse("2012-07-01T00:00:00Z");
System.out.println(
"Old world in Posix - ignorant of leap seconds: "
+ (d2.getTime() - d1.getTime()) / 1000);
Instant instant1 = d1.toInstant();
Instant instant2 = d2.toInstant();
System.out.println(
"Java 8 without Threeten-Extra: "
+ (instant2.getEpochSecond() - instant1.getEpochSecond()));
UtcInstant utc1 = UtcInstant.of(instant1);
UtcInstant utc2 = UtcInstant.of(instant2);
System.out.println(
"Threeten-Extra-impl of UTC-SLS: "
+ utc1.durationUntil(utc2).getSeconds());
System.out.println(
"Threeten-Extra-impl of UTC-SLS: "
+ utc1.durationUntil(utc2));
utc1 = UtcInstant.parse("2012-06-30T23:50:00Z");
utc2 = UtcInstant.parse("2012-07-01T00:00:00Z");
System.out.println(
"Threeten-Extra-impl of UTC-SLS: " + utc1.durationUntil(utc2).getSeconds());
撇开格式和解析中的一些明显限制不谈,主要问题似乎是时间尺度定义的混淆处理。这里秒的定义取决于上下文。例如,如果您只考虑使用UTC-SLS进行转换,则结果“PT10M0.600600601S”是可以接受的,但如果您考虑从POSIX通过UTC-SLS到UTC的整个转换,则不可以接受。正如前面所说,POSIX时间在闰秒之前已经被很好地定义了,因此在闰秒期间POSIX的任何模糊都没有借口。
请记住,除了
java.time
世界外,真正的没有人会谈论UTC-SLS,它是
Markus Kuhn的一个(已经过期的)建议,用于解决NTP时间服务器或操作系统内核的内部实现。相反,其他人和企业,如Google,介绍了自己不同的闰秒扩散实现。我不认为UTC-SLS有未来。
由于java.util.Date与UTC-SLS无关(它比较古老),但对于普通时间戳也有明确定义(遵循UTC定义的秒,但不处理闰秒的限制),因此我们在这里看到了外部IT世界(不想知道闰秒或UTC-SLS)和Threeten-Extra之间的互操作性问题,这可能会导致计算持续时间时出现意外差异。
Duration
是以Java时间测量的,因此您永远不会看到闰秒。 - dhke