我需要在我的代码中在固定的日期时间安排一个任务。为此,我使用了带有schedule(Runnable command, long delay, TimeUnit unit);方法的ScheduledExecutorService
如何根据闰秒计算此延迟?
目前我使用的是Duration.between(),但它似乎没有意识到闰秒:
ZonedDateTime date1 = ZonedDateTime.of(2015, 06, 30, 23, 59, 59, 000000, ZoneOffset.UTC);
ZonedDateTime date2 = ZonedDateTime.of(2015, 07, 01, 00, 00, 00, 000000, ZoneOffset.UTC);
ZonedDateTime date3 = ZonedDateTime.of(2015, 07, 01, 00, 00, 01, 000000, ZoneOffset.UTC);
System.out.println(Duration.between(date1, date2)); // PT1S
System.out.println(Duration.between(date2, date3)); // PT1S发布于 2015-11-14 02:32:33
要支持闰秒,您需要ThreeTen-Extra扩展jar文件。它有专用于UTC and TAI和table of leap seconds的类。
要计算持续时间,请使用专用的durationUntil()方法。
发布于 2015-11-15 04:59:54
使用我的库Time4J (v3.x在Java7上工作-或者在安卓上的Time4A )将给你一个完整的解决方案,包括对不同时区的格式和解析的广泛支持。示例:
// Time4J - transformation from old world
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)); // 601
// Time4J - programmatical construction of timestamps (like in your example)
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)); // 601
// Time4J - parsing zoned inputs
ChronoFormatter<Moment> cf =
ChronoFormatter.ofMomentPattern(
"d. MMM uuuu HH:mm:ss[XXX]", // optional offset
PatternType.CLDR,
Locale.ENGLISH,
EUROPE.PARIS); // only used if the offset is missing in input
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)); // 601
// the leap second itself can also be parsed
Moment ls = cf.parse("1. Jul 2015 08:59:60+09:00"); // offset of Tokyo
System.out.println("leap second in 2015: " + ls);
// 2015-06-30T23:59:60Z还有更多的功能,即支持时钟感知闰秒和从IANA-TZDB传输闰秒数据。示例请参见我的article on DZone。请注意,Time4J可以完全取代ThreetenBP,但也可以与Java-8互操作(只需将版本更改为v4.x),并提供了更多超出本文讨论范围的特性。
注意:大多数人选择ThreetenBP显然是为了让将来更容易迁移到-8(只需更改一些导入语句)。但你的问题是
提议的其他第三方库Threeten-Extra不能在-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);
// 600 (OK, SI-seconds without counting leap second, a limitation of POSIX)
Instant instant1 = d1.toInstant();
Instant instant2 = d2.toInstant();
System.out.println(
"Java 8 without Threeten-Extra: "
+ (instant2.getEpochSecond() - instant1.getEpochSecond()));
// 600 (obviously using more or less fuzzy "rubber seconds", not SI-seconds)
// internally a simple 1:1-mapping of POSIX is applied within 'toInstant()'
UtcInstant utc1 = UtcInstant.of(instant1);
UtcInstant utc2 = UtcInstant.of(instant2);
System.out.println(
"Threeten-Extra-impl of UTC-SLS: "
+ utc1.durationUntil(utc2).getSeconds()); // pitfall, see next output!
// 600 (??? - where is the leap second, should be 601 because of original POSIX-input?!)
System.out.println(
"Threeten-Extra-impl of UTC-SLS: "
+ utc1.durationUntil(utc2)); // <= printing the duration object
// PT10M0.600600601S (OK, here the UTC-SLS-specific fraction of second appears
// Reason: Smoothing starts 1000s before leap second)
// only offset "Z=UTC+00:00" can be parsed
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());
// 601 (expected, the only way where seconds are really SI-seconds)抛开格式化和解析方面的一些明显限制不谈,主要问题似乎是时间尺度定义的混乱处理。秒的定义在这里取决于上下文。例如,如果您只考虑使用UTC-SLS的转换,则结果"PT10M0.600600601S“是可以的,但如果您考虑从POSIX通过UTC-SLS到UTC的整个转换,则结果是不好的。如前所述,POSIX时间被很好地定义在闰秒之前的10分钟,所以在闰秒期间POSIX的任何模糊性都不是借口。
请记住,除了NTP -world之外,实际上没有人谈论UTC-SLS,这是Markus Kuhn提出的一个解决java.time时间服务器或操作系统内核内部实现的建议(正式过期)。取而代之的是,像Google这样的其他人和企业引入了他们自己的不同的leap smear实现。我看不到UTC-SLS的未来。
由于java.util.Date与UTC-SLS (更早)没有任何关系,但也很好地定义了正常的时间戳(遵循UTC-定义的Si-second,但限制了根本不处理的闰秒),我们在这里看到了外部IT世界(它不想知道任何关于闰秒或UTC-SLS的信息)和Threeten-Extra之间的互操作性问题,这可能会导致计算的持续时间出现意外的差异。
发布于 2015-11-14 04:05:44
考虑在CronTrigger中使用Quartz
https://stackoverflow.com/questions/33698664
复制相似问题