'How to specify a TimeZone when creating a DateTime object in Dart/Flutter?

Dart?flutter does not appear to allow a timezone (eg: "Australia/Sydney" or "America/Detroit") to be specified when creating a DateTime object. Either the local timezone will be used, or UT may be specified.

Is anyone aware of a workaround?

There's the Dart package TimeZone, but it appears to be unusable within a flutter app.

See https://pub.dartlang.org/packages/timezone for the package I'm referring to.

EDIT: The timezone package does work in Flutter, with some setup. See Richard Heap's answer below.



Solution 1:[1]

You have to do a bit of magic to get package:timezone to work in flutter.

Extract whichever data file you need (there are 3: default, all and 2010-2020) and move it to your flutter assets folder. (I use 2018c_2010-2020.tzf, which is available in a branch.)

Add it as an asset in pubspec.yaml:

  assets:
    - assets/2018c_2010-2020.tzf

Then load that file on startup (e.g. from the initState of a top level StatefulWidget) and use it to initialise the database.

ByteData tzf = await rootBundle.load('assets/2018c_2010-2020.tzf');
initializeDatabase(tzf.buffer.asUint8List());
...
Location newYork = getLocation('US/Eastern');

I haven't tried, but you may even be able to load it from main if you mark it async.

I also notice that I must have cloned the latest branch, as I see this in my pubspec

  timezone:
    path: ../../dart/source/timezone

... but looks like you just need to grab 0.5.0-dev-2 from pub

dependencies:
  timezone: "^0.5.0-dev-2"

Solution 2:[2]

This solution worked for me

simple add these lines in initState


import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/data/latest.dart' as tz;
 @override
  void initState() {
   super.initState();
   tz.initializeTimeZones();
   final String locationName = await FlutterNativeTimezone.getLocalTimezone();
   tz.setLocalLocation(tz.getLocation(locationName));
}

Solution 3:[3]

The TimeZone package does work. From the issues list on GitHub:

Sorry this took 6 months but I have a good solution. I think it will be the recommended solution.

See Flutter's docs on Adding Assets. You should be able to add to your Flutter app's pubspec.yaml:

flutter:
  assets:
    - packages/timezone/data/2015b.tzf

and load in your app with:

Future<List<int>> loadDefaultData() async {
  var byteData = await rootBundle.load('packages/timezone/data/2015b.tzf');
  return byteData.buffer.asUint8List();
}

// Call the above with something like:

loadDefaultData().then((rawData) {
  initializeDatabase(rawData);
  var zurich = getLocation('Europe/Zurich');
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Arslan Kaleem
Solution 3 Yahya Uddin