49

I'm receiving a DateTime response from API that's sets the timezone to UTC.

But when I try to convert the received data using toLocal() it doesn't convert.

my local time is HKT

here's my code.

    //TIME DIFFERENCE
  getNotificationDate(DateTime date) {
    date = date.toUtc();
    final convertedDate = date.toLocal();

    final dateNow = DateTime.now();
    print('TIMENOW: ' + dateNow.toString());
    print('TIMENOTIFC: ' + convertedDate.toString());
    final difference = dateNow.difference(convertedDate);
    print('DIFFERENCE: ' + difference.toString());
    return getDurationFormat(difference);
  }

EDIT:

date is the DateTime I'm receiving from the API. which is in UTC timezone.

I used print('TIMEZONENAME: ' + date.timeZoneName; and it automatically sets the timezone to HKT. that's why it does nothing when I try to use date.toLocal()

Gentle
  • 759
  • 2
  • 8
  • 20
  • What do you mean that it "doesn't convert"? Is the result not in local time (e.g., according to `isUtc`)? Is the time for it not correct? What output did you *expect* for your example program? – lrn Oct 10 '19 at 14:50
  • for example, my current `local time` is **11:00 PM**. I'm now sending **11:00 PM** to the API. Now, my **11:00 PM** is being converted by the backend to `UTC` which would then become **3:08 pm** because the backend's `DateTime` is set to `UTC` by default. Now I will navigate to a page wherein I'm getting that `DateTime` that I just sent. I thought that by default, flutter would detect that `DateTime's` timezone but I was wrong. flutter automatically sets the incoming `DateTime` to my `Local` Timezone. – Gentle Oct 10 '19 at 15:13
  • **P.S.** I'm not including my `local time` as a parameter when calling a `POST` request. it would simply be `created_at` at the backends side. – Gentle Oct 10 '19 at 15:17
  • Dart `DateTime` only supports two time zones - UTC and "local". If you get an incoming time and you create a `DateTime` object for it, it will be in one of those two time zones. The incoming "time" is probably a string, so I assume you parse it. If that string contains, say, a `+02:00` time-zone marker then it is parsed as UTC by subtracting the time-zone offset from the parsed date. If it has no time-zone marker (no "+02" and no "Z") then it is interpreted as a local time. – lrn Oct 11 '19 at 06:05
  • unfortunately it doesn't have `+02` or `Z`. will there be a way to change that after I receive it? – Gentle Oct 11 '19 at 14:03
  • 2
    If you get the string, you can add something to it, like "Z", but that will make it be interpreted as a UTC time, not the local-time of the sender. If you get the `DateTime` object, you probably have to create a new object from that, say by doing toString, adding "Z" and parsing it again. If you *know* the time zone of the server, say UTC+3, you can add `+03:00` after the string and get the UTC-time corresponding to that moment in time – lrn Oct 12 '19 at 20:40
  • 1
    Did you finally found something working ? I have same problem – Jason Simard Oct 11 '20 at 15:54
  • 1
    @Gentle Can you please mark as an accepted answer so that we can save others time? :) – Aanal Shah Jan 25 '21 at 07:30

12 Answers12

74

Flutter gave us the easiest way to convert it. You just need to pass utc: true while parsing your date.

var dateTime = DateFormat("yyyy-MM-dd HH:mm:ss").parse(dateUtc, true);
var dateLocal = dateTime.toLocal();

Input:

Assume my TimeZone : +05:30

UTC Date -> 2020-02-12 23:57:02.000

Output:

Local Date -> 2020-02-12 18:27:02.019660

Aanal Shah
  • 1,946
  • 2
  • 20
  • 30
21
// you have time in utc
var dateUtc = DateTime.now().toUtc();
print("dateUtc: $dateUtc"); // 2019-10-10 12:05:01

// convert it to local
var dateLocal = dateUtc.toLocal();
print("local: $dateLocal"); // 2019-10-10 14:05:01

Can you see the difference in hours, in utc it is 12 and locally it is 14.

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
8

Firstly, convert your Sting to DateTime.

> DateTime dateTime = DateTime.parse(json['pickUpTime']);

Secondly, add timeZoneOffSet to your converted date time it will convert utc to your local time.

> dateTime = dateTime.add(DateTime.parse(json['pickUpTime']).timeZoneOffset);

Final Code

DateTime dateTime = DateTime.parse(json['pickUpTime']);
dateTime = dateTime.add(DateTime.parse(json['pickUpTime']).timeZoneOffset);
Ahmad hassan
  • 769
  • 4
  • 14
  • 1
    all the advices with the DateFormat and toLocal or toUtc methods were not working for me. Yours did the trick. Thanks! – Christian X Apr 30 '22 at 22:19
7

Two solutions I implemented

var date = DateFormat("yyyy-MM-ddTHH:mm:ss").parse(json, true);
var dateLocal  = date.toLocal();

Other solutions add "Z" You need to indicate a timezone to DateTime.parse, otherwise it assumes local time. From the dartdoc:

var date = DateTime.parse("${dateString}Z").toLocal();
var dateFormat = date2.toLocal();
Ema
  • 71
  • 1
  • 2
3

You can try this code:

getNotificationDate(DateTime date) {
    date = DateTime.utc(date.year,date.month,date.day,date.hour,date.minute,date.second);;
    final convertedDate = date.toLocal();

    final dateNow = DateTime.now();
    print('TIMENOW: ' + dateNow.toString());
    print('TIMENOTIFC: ' + convertedDate.toString());
    final difference = dateNow.difference(convertedDate);
    print('DIFFERENCE: ' + difference.toString());
    return getDurationFormat(difference);
  }
Ahmad Aghazadeh
  • 16,571
  • 12
  • 101
  • 98
3

I've done something like this.

String dateTimeFormatter(String dateTime, {String? format}) {
  return DateFormat(format ?? 'yyyy/MM/dd, hh:mm a')
      .format(DateTime.parse(dateTime).toLocal())
      .toString();
}

just pass the format which you want to display in your app.

Prajun Lungeli
  • 117
  • 1
  • 12
2

For those who parsing TimeStamp from Firestore.

*sentAt is Timestamp

String timeToDate = widget.sentAt.toDate().toString();
    var dateTime = DateFormat("yyyy-MM-dd HH:mm:ss").parse(timeToDate, true);
    var dateLocal = dateTime.toLocal();
Hamdam Muqimov
  • 319
  • 2
  • 7
2

If somebody needs to parse a UTC timestamp in isoformat, for example something like this:

>>> from datetime import datetime
>>> datetime.utcnow().format()
'2021-07-20T19:35:19.769891'

Then you can parse this and convert this to local time by

DateTime parseDatetimeFromUtc({required String isoFormattedString}){
  var dateTime = DateTime.parse(isoFormattedString + '+00:00');
  return dateTime.toLocal();
}

The '+00:00' is append here as the timezone information part which I do not send over my API to save some bytes. Maybe this helps someone who is in the same situation.

Of course you do not need this hardcoded suffix if you use a timezone aware timestamp in your backend:

>>> from datetime import datetime, timezone
>>> datetime.now(timezone.utc).isoformat()
'2021-07-20T19:42:36.538195+00:00'
DarkMath
  • 1,089
  • 2
  • 15
  • 29
1

I tried several examples and forums, but it kept getting me the incorrect date time for my zone, The only way I made it work correctly was by using the GMT package

var nowLocal = DateTime.now();
print("toUtc: ${nowLocal.toUtc()}");
print("toLocalDateTime ${nowLocal.toLocalDateTime()}");
print("toLocal ${nowLocal.toLocal()}");
print("toIso8601String ${nowLocal.toIso8601String()}");
final timeZoneOffsetInHours = DateTime.now().timeZoneOffset.inHours;
final nowGMT = await GMT.now();
print("GMT: $nowGMT");
final nowActual = nowGMT?.add(Duration(hours: timeZoneOffsetInHours));
print("nowActual $nowActual");
0

this is how i converted to my required time .which was showing as

I/flutter ( 5709): 16 Apr 08:30 PM 2021

when using the

var date=DateFormat("dd MMM hh:mm a y").format(DateTime.fromMillisecondsSinceEpoch(start*1000));
      print(date);

but after using this code i got my right time

var date=DateFormat("dd MMM hh:mm a y").format(DateTime.fromMillisecondsSinceEpoch(start*1000).toUtc());
      print(date);
      

which is

I/flutter ( 5709): 16 Apr 03:00 PM 2021
Dharman
  • 30,962
  • 25
  • 85
  • 135
Spsnamta
  • 479
  • 6
  • 11
-1

Install intl package from pub.dev

add following line :

import 'package:intl/intl.dart';

You can make an extension like below so it will be very helpful and easy to use anywhere in a whole project.

//just make sure you have passed the right date format of utc("yyyy-MM-dd HH:mm:ss"). I have passed by default my format.

//for example
// 2020-11-25 24:12:36 -> "yyyy-MM-dd HH:mm:ss"
DateTime localDate=utcDateTime.toLocalDateTime();


//for different formats you can pass your own dateFormat for utcDate like below:
// 20-11-25 24:12:36 -> "yy-MM-dd HH:mm:ss"
DateTime localDate=utcDateTime.toLocalDateTime("yy-MM-dd HH:mm:ss");

extension DateTimeExtension on DateTime {
  DateTime toLocalDateTime({String format = "yyyy-MM-dd HH:mm:ss"}) {
    var dateTime = DateFormat(format).parse(this.toString(), true);
    return dateTime.toLocal();
  }
}
Code Runner
  • 868
  • 16
  • 27
-2

convert utc number to DateTime:

  DateTime utcToDateTime(int utc) {
    return DateTime(1970, 1, 1).add(Duration(seconds: utc));
  }

  //test
  DateTime d = utcToDateTime(1649297709);
  print(d);