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.DateTimeFormatsupport.
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.