package org.kne.cloud.clock; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import org.kne.math.Long128; public class NTPTimestamps { // 常量定义 public static final Long128 NANOS_PER_SECOND = Long128.valueOf(1_000_000_000L); public static final Long128 NANOS_PER_MILLIS = Long128.valueOf(1_000_000L); // NTP 纪元 (1900) 和 Unix 纪元 (1970) 之间的纳秒差 public static final Long128 NTP_EPOCH_OFFSET_NS = Long128.valueOf(2208988800L) .multiply(NANOS_PER_SECOND); // 2^64 值,用于单位转换 public static final Long128 TWO_POW_64 = Long128.ONE.shiftLeft(64); // 2^32 值,用于 64 位时间戳处理 public static final Long128 TWO_POW_32 = Long128.ONE.shiftLeft(32); // 掩码常量 public static final Long128 MASK_32_BIT = new Long128(0xFFFFFFFF); public static final Long128 MASK_64_BIT = new Long128(0xFFFFFFFFFFFFFFFFL); // ================== 核心转换方法 ================== // 2^32 秒,约 136.192 年,一个 NTP 纪元的长度 public static final Long128 SECONDS_PER_ERA = Long128.valueOf(0x100000000L); private static final Long128 TWO_POW_N64_PER_NANOS = Long128.valueOf("1208925819614629"); public static Long128 inferNtp64To128(long remote64Bit,Long128 local128Bit ) { return inferNtp64To128(toUnsignedLong128(remote64Bit),local128Bit); } /** * 根据本地 128 位时间戳和网络 64 位时间戳,推断并补全纪元信息 * * @param remote64Bit 从网络接收的 64 位 NTP 时间戳 * @param local128Bit 本地已知的 128 位 NTP 时间戳 * @return 推断出的完整 128 位 NTP 时间戳 */ public static Long128 inferNtp64To128(Long128 remote64Bit,Long128 local128Bit ) { // 1. 从本地 128 位时间戳中提取纪元号和 64 位时间戳部分 Long128 localEra = NTPTimestamps.getEraNumber(local128Bit); Long128 local64Bit = NTPTimestamps.getNtp64Timestamp(local128Bit); // 3. 计算本地和远程 64 位时间戳的差异 Long128 difference = remote64Bit.subtract(local64Bit); // 4. 判断纪元关系并推断远程时间戳的纪元 Long128 remoteEra; // 如果差异很大(超过半个纪元),可能需要调整纪元 Long128 halfEra = Long128.valueOf(Long.MAX_VALUE); if (difference.compareTo(halfEra) > 0) { // 远程时间戳比本地小很多,可能属于上一个纪元 remoteEra = localEra.subtract(Long128.ONE); } else if (difference.compareTo(halfEra.negate()) < 0) { // 远程时间戳比本地大很多,可能属于下一个纪元 remoteEra = localEra.add(Long128.ONE); } else { // 差异不大,属于同一个纪元 remoteEra = localEra; } // 5. 组合纪元号和 64 位时间戳,得到完整的 128 位时间戳 return NTPTimestamps.ntp64To128(remote64Bit, remoteEra); } /** * 将从1970年开始的纳秒数转换为 NTPv4 128 位时间戳 * 128位时间戳表示从1900年1月1日起经过的 2⁻⁶⁴ 秒的数量 */ public static Long128 nanosToNtp128BitTimestamp(Long128 nanosSince1970) { // 1. 计算从 1900 年开始的总纳秒数 Long128 totalNanosFrom1900 = nanosSince1970.add(NTP_EPOCH_OFFSET_NS); // 2. 将纳秒转换为 2⁻⁶⁴ 秒单位 // return totalNanosFrom1900.multiply(TWO_POW_64).divide(NANOS_PER_SECOND); return totalNanosFrom1900.multiply(TWO_POW_N64_PER_NANOS).shiftRight(16); } /** * 从 NTPv4 128 位时间戳转换回从1970年开始的纳秒数 */ public static Long128 ntp128BitToNanosTimestamp(Long128 ntp128Timestamp) { // 1. 将 2⁻⁶⁴ 秒单位转换回纳秒 Long128 totalNanosFrom1900 = ntp128Timestamp.multiply(NANOS_PER_SECOND).divide(TWO_POW_64); // 2. 计算从 1970 年开始的总纳秒数 return totalNanosFrom1900.subtract(NTP_EPOCH_OFFSET_NS); } public static Long128 nanosToNtp128BitTimeInterval(Long128 nanos) { // 2. 将纳秒转换为 2⁻⁶⁴ 秒单位 return nanos.multiply(TWO_POW_64).divide(NANOS_PER_SECOND); } public static Long128 ntp128BitToNanosInterval(Long128 ntp128Timestamp) { // 1. 将 2⁻⁶⁴ 秒单位转换回纳秒 Long128 totalNanosFrom1900 = ntp128Timestamp.multiply(NANOS_PER_SECOND).divide(TWO_POW_64); return totalNanosFrom1900; } // ================== 128位 ↔ 64位 转换 ================== /** * 将 NTP 128 位时间戳转换为 NTP 64 位时间戳 * 64位时间戳就是128位时间戳的中间64位 */ public static Long128 ntp128To64(Long128 ntp128Timestamp) { return ntp128Timestamp.shiftRight(32).and(MASK_64_BIT); } /** * 将 NTP 64 位时间戳转换为 NTP 128 位时间戳 * 64位时间戳放在128位时间戳的中间64位,高32位Era和低32位分数为0 */ public static Long128 ntp64To128(Long128 ntp64Timestamp) { return ntp64Timestamp.and(MASK_64_BIT).shiftLeft(32); } /** * 将 NTP 64 位时间戳转换为 NTP 128 位时间戳(指定Era Number) */ public static Long128 ntp64To128(Long128 ntp64Timestamp, Long128 eraNumber) { return eraNumber.and(MASK_32_BIT).shiftLeft(96) .or(ntp64Timestamp.and(MASK_64_BIT).shiftLeft(32)); } /** * 从 NTP 128 位时间戳中提取 Era Number(高32位) */ public static Long128 getEraNumber(Long128 ntp128Timestamp) { return ntp128Timestamp.shiftRight(96).and(MASK_32_BIT); } /** * 从 NTP 128 位时间戳中提取 64 位时间戳(中间64位) */ public static Long128 getNtp64Timestamp(Long128 ntp128Timestamp) { return ntp128Timestamp.shiftRight(32).and(MASK_64_BIT); } /** * 从 NTP 128 位时间戳中提取分数部分(低32位) */ public static Long128 getFraction(Long128 ntp128Timestamp) { return ntp128Timestamp.and(MASK_32_BIT); } // ================== 工具方法 ================== /** * 从毫秒和纳秒偏移构造 Long128 纳秒 */ public static Long128 toNanosSince1970(long unixTimeMillis, long nanosOffset) { return Long128.valueOf(unixTimeMillis) .multiply( NANOS_PER_MILLIS) .add(Long128.valueOf(nanosOffset)); } /** * 从 Long128 纳秒提取毫秒和纳秒偏移 */ public static long[] toMillisAndNanos(Long128 nanosSince1970) { Long128[] millisAndNanos = nanosSince1970.divideAndRemainder( NANOS_PER_MILLIS); return new long[]{millisAndNanos[0].longValue(), millisAndNanos[1].longValue()}; } /** * 计算两个 128 位时间戳之间的时间差(纳秒) */ public static Long128 calculateTimeDifference(Long128 timestamp1, Long128 timestamp2) { Long128 diff = timestamp2.subtract(timestamp1); return diff.multiply(NANOS_PER_SECOND).divide(TWO_POW_64); } /** * 将 64 位 NTP 时间戳分解为秒数和分数 */ public static Long128[] parseNtp64Timestamp(Long128 ntp64Timestamp) { Long128 seconds = ntp64Timestamp.shiftRight(32).and(MASK_32_BIT); Long128 fraction = ntp64Timestamp.and(MASK_32_BIT); return new Long128[]{seconds, fraction}; } /** * 从秒数和分数构建 64 位 NTP 时间戳 */ public static Long128 buildNtp64Timestamp(Long128 seconds, Long128 fraction) { return seconds.and(MASK_32_BIT).shiftLeft(32).or(fraction.and(MASK_32_BIT)); } // 日期时间格式化器 private static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); private static final DateTimeFormatter DETAILED_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.n"); public static String nanosSince1970ToString(Long128 nanos) { Long128 millis = nanos.divide(Long128.valueOf(1_000_000)); Long128 nanosPart = nanos.mod(Long128.valueOf(1_000_000)); Instant instant = Instant.ofEpochMilli(millis.longValue()); LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); return String.format("%s.%06d", DEFAULT_FORMATTER.format(dateTime), nanosPart.longValue()); } public static String nanosSince1970ToString2(Long128 nanos) { Long128 millis = nanos.divide(Long128.valueOf(1_000_000)); Instant instant = Instant.ofEpochMilli(millis.longValue()); LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); return DEFAULT_FORMATTER.format(dateTime); } /** * 将 128 位时间戳转换为可读字符串 */ public static String ntp128ToString(Long128 ntp128Timestamp) { Long128 nanosSince1970 = ntp128BitToNanosTimestamp(ntp128Timestamp); return nanosSince1970ToString(nanosSince1970); } /** * 将 64 位时间戳转换为可读字符串 */ public static String ntp64ToString(Long128 ntp64Timestamp) { Long128 nanosSince1970 = ntp128BitToNanosTimestamp(ntp64To128( ntp64Timestamp)); return nanosSince1970ToString(nanosSince1970); } public static Long128 toUnsignedLong128(long unsignedLong) { if (unsignedLong >= 0) { return Long128.valueOf(unsignedLong); } else { // 对于负数,通过添加 2^64 来转换为无符号表示 return Long128.valueOf(unsignedLong & 0x7FFFFFFFFFFFFFFFL) .setBit(63); } } }