如何获取网络DateTime.Now()?

问题描述 投票:0回答:7

在 flutter 中

DateTime.now()
返回设备日期和时间。用户有时会改变他们的内部时钟,使用
DateTime.now()
可能会给出错误的结果。

  1. 如何在 flutter 中获取网络/服务器当前日期时间
  2. 是否可以在不使用任何软件包的情况下获取网络/服务器当前日期时间
flutter dart
7个回答
25
投票

没有任何 API 是不可能的。您可以使用

ntp
插件:

一个允许您从网络时间协议(NTP)获取精确时间的插件。它在 dart 中实现了整个 NTP 协议。

这对于基于时间的事件很有用,因为 DateTime.now() 返回设备的时间。用户有时会更改其内部时钟,并且使用 DateTime.now() 可能会给出错误的结果。您可以获取时钟偏移量 [NTP.getNtpTime] 并在需要时手动将其应用于 DateTime.now() 对象(只需将偏移量添加为毫秒持续时间),或者您可以从 [NTP.now] 获取已格式化的 [DateTime] 对象。

将其添加到包的 pubspec.yaml 文件中:

dependencies:
  ntp: ^1.0.7

然后添加这样的代码:

import 'package:ntp/ntp.dart';

Future<void> main() async {
  DateTime _myTime;
  DateTime _ntpTime;

  /// Or you could get NTP current (It will call DateTime.now() and add NTP offset to it)
  _myTime = await NTP.now();

  /// Or get NTP offset (in milliseconds) and add it yourself
  final int offset = await NTP.getNtpOffset(localTime: DateTime.now());
  _ntpTime = _myTime.add(Duration(milliseconds: offset));

  print('My time: $_myTime');
  print('NTP time: $_ntpTime');
  print('Difference: ${_myTime.difference(_ntpTime).inMilliseconds}ms');
}

6
投票

尝试使用世界时钟 API。另外,要知道 api 有可能在某个时候失败......所以我建议在 http 调用周围使用 try-catch 块,如果它确实失败,只需返回设备的常规本地时间。 ...

  Future<void> getTime()async{
  var res = await http.get(Uri.parse('http://worldclockapi.com/api/json/est/now'));
  if (res.statusCode == 200){
  print(jsonDecode(res.body).toString());
}}

4
投票

我决定采用不同的路线,因为我已经在使用 Firebase。我以前从未使用过云功能,但我更喜欢这个选项,因为我不依赖 api 调用(其中一些将每四分钟一次以上的 ping 视为拒绝服务攻击)。

  1. firebase 初始化函数
  2. flutter pub 添加 cloud_functions
  3. 在functions文件夹中生成的index.js文件中添加以下代码 云功能:
    const functions = require("firebase-functions");
    const admin = require('firebase-admin');
    admin.initializeApp();
    
    exports.timestamp = functions.https.onCall((data, context) => {
        // verify Firebase Auth ID token
        if (!context.auth) {
            return 'Authentication Required!';
        }
        let date = new Date();
        return date.toJSON();
    });
  1. firebase 部署 --only 功能 然后在 dart 代码中调用该函数看起来像这样返回一个网络 日期时间:
    final _functions = FirebaseFunctions.instance;
    
      Future<DateTime> getDateTime() async {
        try {
          final result = await _functions.httpsCallable('timestamp').call();
          return DateTime.parse(result.data);
        }on FirebaseFunctionsException  catch (error) {
          log(error.code);
          log(error.message!);
          log(error.details);
          throw Exception('Error getting datetime from cloud function.');
        }
      }

3
投票

你可以使用这个插件ntp

import 'package:ntp/ntp.dart';

final int offset = await NTP.getNtpOffset(
        localTime: DateTime.now(), lookUpAddress: "time.google.com");
DateTime internetTime = DateTime.now().add(Duration(milliseconds: offset));

或者有很多可用的 API

这是印度时间的 GET API 示例

http://worldtimeapi.org/api/timezone/Asia/Kolkata

反应会是这样的

  {
      "abbreviation": "IST",
      "client_ip": "45.125.117.46",
      "datetime": "2022-02-26T10:50:43.406519+05:30",
      "day_of_week": 6,
      "day_of_year": 57,
      "dst": false,
      "dst_from": null,
      "dst_offset": 0,
      "dst_until": null,
      "raw_offset": 19800,
      "timezone": "Asia/Kolkata",
      "unixtime": 1645852843,
      "utc_datetime": "2022-02-26T05:20:43.406519+00:00",
      "utc_offset": "+05:30",
      "week_number": 8
    }

如果您不知道自己所在的国家时区,只需调用此API即可获取世界上所有时区

http://worldtimeapi.org/api/timezone/

https://worldtimeapi.org/api/timezone/Etc/UTC


2
投票

这是我的网络时间 DateTime getNow() 方法。它是一种全局方法,每两分钟才获取一次网络时间。我的应用程序对时间不是超级敏感,但我遇到了一些问题,人们的时钟偏差了几分钟。它最多每 2 分钟 ping 一次 worldtimeapi.org(如果你 ping 太频繁,你会得到错误),并使用它们返回的时间来存储一个偏移量来修改本地日期时间。如果 http 调用出现错误,则会回退到用户的时间。我还跟踪对此方法的调用次数,只是为了帮助调试一些计时器,我必须确保它们得到正确处理。

我在使用 worldclockapi 时遇到的问题是它只精确到分钟。我可能做错了什么,但我使用不同的 api 解决了它。这是代码:

int _nowOffset = 0;
int _lastHttpGet = 0;
int _nowCalls = 0;
Future<DateTime> getNow() async {
  try {
    _nowCalls++;
    DateTime nowLocal = DateTime.now();
    if ((nowLocal.millisecondsSinceEpoch - _lastHttpGet) > (oneMinuteMilliSeconds * 2)) {
      _lastHttpGet = nowLocal.millisecondsSinceEpoch;
      var res = await http.get(Uri.parse('https://worldtimeapi.org/api/timezone/Etc/UTC'));
      if (res.statusCode == 200) {
        //print(jsonDecode(res.body).toString());
        Map<String, dynamic> json = jsonDecode(res.body);
        DateTime nowHttp = DateTime.parse(json['datetime']);
        _nowOffset = nowLocal.millisecondsSinceEpoch - nowHttp.millisecondsSinceEpoch;
        if (_nowOffset > 0) {
          _nowOffset *= -1;
        }
        log('http $_nowCalls');
        return nowHttp;
      }
    }
    return DateTime.fromMillisecondsSinceEpoch(nowLocal.millisecondsSinceEpoch + _nowOffset);
  } catch (e, stack) {
    log('{http error: now calls: $_nowCalls $e\n $stack}');
    return DateTime.fromMillisecondsSinceEpoch(DateTime.now().millisecondsSinceEpoch + _nowOffset);
  }
}

0
投票

就我而言,我使用 firebase 云函数来检索时间 只需通过 api 调用调用此函数,响应将采用 isostring 形式,您只需通过执行 DateTime.parse(response.body) 来转换它。

这是firebase javascript函数代码

exports.getDateTime = functions.https.onRequest((request, response) => {
    const londonTime = new Date().toLocaleString('en-GB', { timeZone: 'Europe/London' });
    const londonTimeISO = new Date(londonTime).toISOString();
    response.send(londonTimeISO);
});

这就是颤振功能。

Future<DateTime> getNetworkDateTime() async {
  final url = Uri.parse(
    'https://us-central1-service-finder-27584.cloudfunctions.net/getDateTime',
  );

  final response = await http.post(
    url,
    headers: {
      'Content-Type': 'application/json',
    },
    body: json.encode(
      {},
    ),
  );
  return DateTime.parse(response.body);
}

-4
投票

无需使用任何软件包即可获取网络/服务器当前日期时间。

使用它来获取网络/服务器当前日期时间:-

DateTime now =
        DateTime.now().isUtc ? DateTime.now() : DateTime.now().toUtc();
© www.soinside.com 2019 - 2024. All rights reserved.