codecov GitHub Buy Me A Coffee PayPal Sponsor Support Me on Ko-fi

my_timezone returns the device's local IANA time zone details, available identifiers, and time zone change events on Android, iOS, macOS, and web.

Features

  • Get the local IANA identifier with the existing lightweight API.
  • Get structured details including localized name, abbreviation, current UTC offset, and daylight-saving status where available.
  • Observe system time zone changes as a broadcast stream.
  • Get available IANA identifiers, including the browser-supported list on modern web platforms.
  • Uses stable MethodChannel and EventChannel contracts across Android, iOS, macOS, and web.
  • Requires Flutter 3.47.1 or newer and Dart 3.13.1 or newer.

Platform requirements

  • Android API 24 or newer.
  • iOS 15.0 or newer.
  • macOS 12.0 or newer.
  • A modern browser with Intl.DateTimeFormat support.

Installation

Add the following to your pubspec.yaml:

my_timezone: ^0.1.0

Then run:

flutter pub get

Basic usage

import 'package:my_timezone/my_timezone.dart';

final String localTimezone = await MyTimezone.getLocalTimezone();
final TimezoneInfo timezoneInfo = await MyTimezone.getLocalTimezoneInfo();
final List<String> availableTimezones =
    await MyTimezone.getAvailableTimezones();

TimezoneInfo.isDaylightSavingTime is null when a platform cannot determine the value reliably. Abbreviations are intended for display and are not unique identifiers.

On web, getAvailableTimezones() uses Intl.supportedValuesOf('timeZone') when available. Older browsers fall back to a one-item list containing the local identifier.

Observe time zone changes

final StreamSubscription<TimezoneInfo> subscription =
    MyTimezone.onTimezoneChanged.listen((timezoneInfo) {
  print('Time zone changed to ${timezoneInfo.identifier}');
});

await subscription.cancel();

Android, iOS, and macOS use native system notifications. Web checks every 30 seconds while the stream has an active listener.

Example in a widget

class _MyAppState extends State<MyApp> {
  TimezoneInfo? _timezone;
  StreamSubscription<TimezoneInfo>? _subscription;

  @override
  void initState() {
    super.initState();
    _subscription = MyTimezone.onTimezoneChanged.listen((timezone) {
      if (!mounted) return;
      setState(() => _timezone = timezone);
    });
    _loadTimezone();
  }

  Future<void> _loadTimezone() async {
    final timezone = await MyTimezone.getLocalTimezoneInfo();
    if (!mounted) return;
    setState(() => _timezone = timezone);
  }

  @override
  void dispose() {
    _subscription?.cancel();
    super.dispose();
  }
}

Contribution

If you have any suggestions or find any issues, feel free to open an issue or submit a pull request on GitHub.

Developer Team:

Any comments please contact us ThaoDoan and DucNguyen.