srawlins / timezone

Time zone database and time zone aware DateTime object for Dart.
BSD 2-Clause "Simplified" License
102 stars 54 forks source link

Converting local DateTime to TZDateTime #101

Open DieGlueckswurst opened 3 years ago

DieGlueckswurst commented 3 years ago

I need to convert a local DateTime to TZDatetTime or just set TZDateTime to the local time. But I simply can not make it work. I couldn't find anything on this ... Is there a simply way to get this done? I found this StackOverflow question but the answers are outdated for me. Any help is appreciated!

LongXiangGuo commented 2 years ago

I have met the same problem, when got the timeZoneOffset, how to convert it to the special Location? There are so many location names in the table, and the user may change their phone's timeZone, so it's not a good idea to hard coding the location. It will be more convenient if you add a function to convert the DateTime to Location.

LongXiangGuo commented 2 years ago

I need to convert a local DateTime to TZDatetTime or just set TZDateTime to the local time. But I simply can not make it work. I couldn't find anything on this ... Is there a simply way to get this done? I found this StackOverflow question but the answers are outdated for me. Any help is appreciated!

After further in to the device_calendar package, you can use the flutter_native_timezone to got current timeZone of the phone, then got the correct Location in current location tables, hope it will help you.

Related code

~/.pub-cache/hosted/pub.flutter-io.cn/flutter_native_timezone-2.0.0/lib/flutter_native_timezone.dart:
  static Future<String> getLocalTimezone() async {
    final String? localTimezone =
        await _channel.invokeMethod("getLocalTimezone");
    if (localTimezone == null) {
      throw ArgumentError("Invalid return from platform getLocalTimezone()");
    }
    return localTimezone;
  }
example/lib/presentation/pages/calendar_event.dart:
    87        print('calendar_event _timezone ------------------------- $_timezone');
    88:       var currentLocation = timeZoneDatabase.locations[_timezone];
jtmuller5 commented 1 year ago

I came up with a way to do this without using a package:

  1. Get timezone-less time of local
  2. Get timezone-less time of desired timezone
  3. Calculate difference
  4. Use difference to adjust local time

Function to get "timezone-less" time:

  DateTime getDateWithoutTimeZone(DateTime dateTime) {
    return DateTime.utc(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
  }

Full code:

DateTime localDate = DateTime(
      DateTime.now().year,
      DateTime.now().month,
      DateTime.now().day,
      TimeOfDay.now().hour,
      TimeOfDay.now().minute,
    );

    DateTime dateInTimeZone = tz.TZDateTime.from(localDate.toUtc(), desiredTimeZoneLocation!);

    Duration timeDifferenceFromDesiredTimezone =
        timeService.getDateWithoutTimeZone(localDate).difference(timeService.getDateWithoutTimeZone(dateInTimeZone));

    DateTime utcTimeInDesiredTimeZone = (dateInTimeZone.add(timeDifferenceFromDesiredTimezone).toUtc());
martin-braun commented 1 year ago

@jtmuller5 Thanks for sharing. Yes, TZDateTime overrides DateTimes toLocal(). toLocal() will work with the set Location, which we cannot know and set without using flutter_native_timezone, but converting the TZDateTime object toUtc() and then passing it into DateTime.utc() allows to use the original toLocal() function that will convert the DateTime or any specific timezone to the timezone of the device.

This eliminates the need to deal with Location altogether. I had to take this route, as I still have to deal with Flutter 2 and flutter_native_timezone won't work prior Flutter 3.

Also, I don't think it is necessary to add or substract any times here. It should just work as well to convert the local DateTime back toUtc(), to then feed it into TZDateTime.utc() to convert it into any foreign timezone.