ntp_time_service.dart 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import 'package:nomo/app/data/sp/ix_sp.dart';
  2. import 'package:ntp/ntp.dart';
  3. import 'package:system_clock/system_clock.dart';
  4. import 'log/logger.dart';
  5. class NtpTimeService {
  6. static const String TAG = 'NtpTimeService';
  7. static final NtpTimeService _instance = NtpTimeService._internal();
  8. factory NtpTimeService() => _instance;
  9. NtpTimeService._internal();
  10. // 国内外NTP服务器列表
  11. static const List<String> _ntpServers = [
  12. // 国内服务器
  13. 'time.cloudflare.com',
  14. 'pool.ntp.org',
  15. 'time.google.com',
  16. 'time.nist.gov',
  17. 'ntp.aliyun.com',
  18. 'ntp1.aliyun.com',
  19. 'ntp2.aliyun.com',
  20. 'ntp.tencent.com',
  21. 'time1.cloud.tencent.com',
  22. 'time2.cloud.tencent.com',
  23. 'time3.cloud.tencent.com',
  24. 'ntp.ntsc.ac.cn',
  25. 'cn.pool.ntp.org',
  26. 'time.windows.com',
  27. 'time.apple.com',
  28. 'time-a-g.nist.gov',
  29. 'time-b-g.nist.gov',
  30. 'time-c-g.nist.gov',
  31. 'time-d-g.nist.gov',
  32. 'time-e-g.nist.gov',
  33. 'time-a-wwv.nist.gov',
  34. 'time-b-wwv.nist.gov',
  35. 'time-c-wwv.nist.gov',
  36. 'time-d-wwv.nist.gov',
  37. 'time-e-wwv.nist.gov',
  38. 'time-a-b.nist.gov',
  39. 'time-b-b.nist.gov',
  40. 'time-c-b.nist.gov',
  41. 'time-d-b.nist.gov',
  42. 'time-e-b.nist.gov',
  43. ];
  44. DateTime? _ntpInitialTime;
  45. Duration? _elapsedRealtimeInitial;
  46. String? _currentServer;
  47. bool get isInitialized =>
  48. _ntpInitialTime != null && _elapsedRealtimeInitial != null;
  49. String? get currentServer => _currentServer;
  50. /// 初始化:从多个NTP服务器获取时间,并记录系统启动时间
  51. Future<bool> initialize() async {
  52. try {
  53. log(TAG, 'NTP time calibrator initialization begins...');
  54. // 尝试多个NTP服务器
  55. for (final server in _ntpServers) {
  56. try {
  57. log(TAG, 'Try to connect to the NTP server: $server');
  58. // 加上请求的时间
  59. final requestTime = DateTime.now();
  60. _ntpInitialTime = await NTP.now(lookUpAddress: server);
  61. final responseTime = DateTime.now();
  62. final requestDuration = responseTime.difference(requestTime);
  63. log(TAG, 'Request time: ${requestTime.toIso8601String()}');
  64. log(TAG, 'Response time: ${responseTime.toIso8601String()}');
  65. log(
  66. TAG,
  67. 'Request time-consuming: ${requestDuration.inMilliseconds}ms',
  68. );
  69. _ntpInitialTime = _ntpInitialTime?.add(requestDuration);
  70. _elapsedRealtimeInitial = SystemClock.elapsedRealtime();
  71. _currentServer = server;
  72. log(TAG, 'NTP time calibration is successful, server: $server');
  73. log(TAG, 'Initial time of NTP: $_ntpInitialTime');
  74. log(TAG, 'System start-up time: $_elapsedRealtimeInitial');
  75. log(TAG, 'Current time: ${DateTime.now().toIso8601String()}');
  76. return true;
  77. } catch (e) {
  78. log(TAG, 'NTP server $server connection failed: $e');
  79. continue;
  80. }
  81. }
  82. log(TAG, 'All NTP server connection failed, using system time');
  83. return false;
  84. } catch (e) {
  85. log(TAG, 'NTP time calibrator initialization abnormality: $e');
  86. return false;
  87. }
  88. }
  89. /// 获取当前"网络时间",通过系统运行时间 + NTP 差值计算
  90. DateTime getCurrentTime() {
  91. if (!isInitialized) {
  92. final appConfig = IXSP.getAppConfig();
  93. if (appConfig != null && appConfig.serverTime != null) {
  94. return DateTime.fromMillisecondsSinceEpoch(appConfig.serverTime!);
  95. }
  96. return DateTime.now();
  97. }
  98. final currentElapsedRealtime = SystemClock.elapsedRealtime();
  99. final elapsed = currentElapsedRealtime - _elapsedRealtimeInitial!;
  100. return _ntpInitialTime!.add(elapsed);
  101. }
  102. /// 获取当前时间戳(毫秒)
  103. int getCurrentTimestamp() {
  104. final currentTime = getCurrentTime();
  105. return currentTime.millisecondsSinceEpoch;
  106. }
  107. int getNtpInitialTime() {
  108. if (!isInitialized) {
  109. return getCurrentTimestamp();
  110. }
  111. return _ntpInitialTime?.millisecondsSinceEpoch ?? getCurrentTimestamp();
  112. }
  113. int getElapsedRealtimeInitial() {
  114. if (!isInitialized) {
  115. return SystemClock.elapsedRealtime().inMilliseconds;
  116. }
  117. return _elapsedRealtimeInitial?.inMilliseconds ??
  118. SystemClock.elapsedRealtime().inMilliseconds;
  119. }
  120. /// 同步一次 NTP,重新校准
  121. Future<bool> resync() async {
  122. try {
  123. if (isInitialized) {
  124. return true;
  125. }
  126. log(TAG, 'Start resynchronizing NTP time...');
  127. return await initialize();
  128. } catch (e) {
  129. log(TAG, 'Resynchronization of NTP time failed: $e');
  130. return false;
  131. }
  132. }
  133. }