这是一个非常古老的问题,然而我刚遇到了同样的问题。也许将来会有人阅读这篇文章并节省我刚刚花费的两个小时。
根据JodaStephen的答案,我使用了TheeTen-Extra项目和Java8的Instant作为输入和输出,编写了以下代码:
private final static int TAI_GPS_OFFSET = 19;
private final static LocalDate MODIFIED_JULIAN_EPOCH = LocalDate.of(1858, 11, 17);
public static Instant fromGpsTimeToUtc(Instant gpsTime) {
LocalDate day = LocalDate.ofInstant(gpsTime, ZoneOffset.UTC);
long days = ChronoUnit.DAYS.between(MODIFIED_JULIAN_EPOCH, day);
long taiUtcOffset = UtcRules.system().getTaiOffset(days);
return gpsTime.minusSeconds(taiUtcOffset).plusSeconds(TAI_GPS_OFFSET);
}
我用一些包含来自德国GPS时间维基百科页面的数据的测试验证了这种方法:
Instant today = OffsetDateTime.of(2022, 8, 3, 10, 0, 0, 0, ZoneOffset.UTC).toInstant();
assertThat(fromGpsTimeToUtc(today))
.isEqualTo(today.minus(18, ChronoUnit.SECONDS));
Instant firstOf2017 = OffsetDateTime.of(2017, 1, 1, 10, 0, 0, 0, ZoneOffset.UTC).toInstant();
assertThat(fromGpsTimeToUtc(firstOf2017))
.isEqualTo(firstOf2017.minus(18, ChronoUnit.SECONDS));
Instant lastOf2016 = OffsetDateTime.of(2016, 12, 31, 10, 0, 0, 0, ZoneOffset.UTC).toInstant();
assertThat(fromGpsTimeToUtc(lastOf2016))
.isEqualTo(lastOf2016.minus(17, ChronoUnit.SECONDS));
Instant firstOfJuly2015 = OffsetDateTime.of(2015, 7, 1, 10, 0, 0, 0, ZoneOffset.UTC).toInstant();
assertThat(fromGpsTimeToUtc(firstOfJuly2015))
.isEqualTo(firstOfJuly2015.minus(17, ChronoUnit.SECONDS));
Instant lastOfJune2015 = OffsetDateTime.of(2015, 6, 30, 10, 0, 0, 0, ZoneOffset.UTC).toInstant();
assertThat(fromGpsTimeToUtc(lastOfJune2015))
.isEqualTo(lastOfJune2015.minus(16, ChronoUnit.SECONDS));
Instant firstOfJuly2012 = OffsetDateTime.of(2012, 7, 1, 10, 0, 0, 0, ZoneOffset.UTC).toInstant();
assertThat(fromGpsTimeToUtc(firstOfJuly2012))
.isEqualTo(firstOfJuly2012.minus(16, ChronoUnit.SECONDS));