在 flutter 中
DateTime.now()
返回设备日期和时间。用户有时会改变他们的内部时钟,使用 DateTime.now()
可能会给出错误的结果。
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');
}
尝试使用世界时钟 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());
}}
我决定采用不同的路线,因为我已经在使用 Firebase。我以前从未使用过云功能,但我更喜欢这个选项,因为我不依赖 api 调用(其中一些将每四分钟一次以上的 ping 视为拒绝服务攻击)。
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();
});
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.');
}
}
你可以使用这个插件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即可获取世界上所有时区
这是我的网络时间 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);
}
}
就我而言,我使用 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);
}
无需使用任何软件包即可获取网络/服务器当前日期时间。
使用它来获取网络/服务器当前日期时间:-
DateTime now =
DateTime.now().isUtc ? DateTime.now() : DateTime.now().toUtc();