Reputation: 1957
In flutter DateTime.now()
returns the device date and time. Users sometimes change their internal clock and using DateTime.now()
can give the wrong results.
Upvotes: 28
Views: 17410
Reputation: 5984
You can use this plugin 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));
Or there are plenty of API's available
here is an example GET API for Indian time
http://worldtimeapi.org/api/timezone/Asia/Kolkata
The response will be like
{
"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
}
If you dont know your country zone just call this API to get all timezones in the world
http://worldtimeapi.org/api/timezone/
https://worldtimeapi.org/api/timezone/Etc/UTC
Upvotes: 3
Reputation: 1
in my case i have used firebase cloud functions to retrieve the time just call this function through an api call and the response will be in isostring you would just have to convert it by doing DateTime.parse(response.body).
this is the firebase javascript function code
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);
});
and this is the flutter function.
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);
}
Upvotes: 0
Reputation: 117
it is possible to get Network/Server Current DateTime Without using any packages.
Use this to get the Network/Server Current DateTime:-
DateTime now =
DateTime.now().isUtc ? DateTime.now() : DateTime.now().toUtc();
Upvotes: -4
Reputation: 109
I decided to go at this a different route since I'm already using Firebase. I had never used cloud functions before but I like this option better since I'm not reliant on api calls (some of which consider a ping more than once every four minutes a denial of service attack).
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.');
}
}
Upvotes: 4
Reputation: 109
This is my network time DateTime getNow() method. It is a global method that only gets the network time every two minutes. My app is not super time sensitive but I have run into some issues with people's clock's being off by a couple minutes. It just pings worldtimeapi.org at most every 2 minutes (you will get errors if you ping them too often) and uses their returned time to store an offset to modify the local datetime by. If there are errors with the http call, it falls back to the user's time. I'm also tracking the number of calls to this method just to help debug some timers I have to make sure they are getting disposed of properly.
The problem I had with worldclockapi is it was only accurate to the minute. I could have been doing something wrong but I solved it with using a different api. Here is the code:
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);
}
}
Upvotes: 3
Reputation: 1808
It's not possible without any API. You can use ntp
plugin:
A plugin that allows you to get precise time from Network Time Protocol (NTP). It implements the whole NTP protocol in dart.
This is useful for time-based events since DateTime.now() returns the time of the device. Users sometimes change their internal clock and using DateTime.now() can give the wrong result. You can just get clock offset [NTP.getNtpTime] and apply it manually to DateTime.now() object when needed (just add offset as milliseconds duration), or you can get already formatted [DateTime] object from [NTP.now].
Add this to your package's pubspec.yaml file:
dependencies:
ntp: ^1.0.7
Then add the code like this:
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');
}
Upvotes: 26
Reputation: 306
Try using the world clock api. Also, know that there is a chance the api could fail at some point... So I would recommend using a try-catch block around the http call, and if it does happen to fail, just return regular local time of the device....
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());
}}
Upvotes: 6