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

l2osamch  于 2023-01-27  发布在  Flutter
关注(0)|答案(6)|浏览(318)

在flutter中,DateTime.now()返回设备的日期和时间。用户有时会更改内部时钟,使用DateTime.now()可能会给予错误的结果。
1.如何在flutter中获得网络/服务器当前日期时间
1.是否可以不使用任何软件包获得网络/服务器当前日期时间

mfuanj7w

mfuanj7w1#

如果没有任何API,这是不可能的。您可以使用ntp插件:

一个插件,允许你从网络时间协议(NTP)获得精确的时间。它在dart中实现了整个NTP协议。
这对于基于时间的事件非常有用,因为DateTime.now()会返回设备的时间。用户有时会更改其内部时钟,使用DateTime.now()可能会给予错误的结果。您可以仅获取时钟偏移[NTP.getNtpTime],并在需要时将其手动应用于DateTime.now()对象(仅将偏移添加为毫秒持续时间),或者您可以从[ www.example.com 。
将以下代码添加到包的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');
}
zsohkypk

zsohkypk2#

尝试使用世界时钟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());
}}
tkclm6bt

tkclm6bt3#

你可以使用这个插件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
他们的React会是

{
      "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/

b09cbbtk

b09cbbtk4#

这是我的网络时间DateTime getNow()方法。它是一个全局方法,每两分钟才获取一次网络时间。我的应用程序对时间并不特别敏感,但我遇到了一些问题,人们的时钟会慢几分钟。它worldtimeapi.org最多每两分钟就ping www.example.com一次(如果您太频繁地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);
  }
}
cpjpxq1n

cpjpxq1n5#

因为我已经在使用Firebase了,所以我决定走另一条路。我以前从未使用过云函数,但我更喜欢这个选项,因为我不依赖于API调用(其中一些认为每四分钟ping一次以上是拒绝服务攻击)。

  1. firebase初始化函数
  2. flutter发布添加云函数
    1.在functions文件夹中生成的index.js文件中,为cloud函数添加以下代码:
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 deploy --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.');
        }
      }
oknwwptz

oknwwptz6#

不使用任何软件包就可以获得网络/服务器当前日期时间。
使用此命令获取网络/服务器当前日期时间:-

DateTime now =
        DateTime.now().isUtc ? DateTime.now() : DateTime.now().toUtc();

相关问题