😺

timezoneとdevice_calendarを併用する際の注意点

2024/05/12に公開

概要

timezonedevice_calendar を併用した際に、思わぬ挙動に遭遇したので、その備忘録です。
結論から書くと、timezone と device_calendar を併用する際は、DeviceCalendarPlugin の初期化時にshouldInitTimezone: falseにしましょう。

// shouldInitTimezoneをfalseに!
final deviceCalendarPlugin = DeviceCalendarPlugin(shouldInitTimezone: false)

問題

timezone と device_calendar を併用した所、アプリ起動時に タイムゾーン を Asia/Tokyo で初期化しているのに、他の場所でtz.localにアクセスすると UTC になっていました。

/// タイムゾーン初期化処理
Future<void> _setupTimezones() async {
  tz.initializeTimeZones();
  final locationName = await FlutterTimezone.getLocalTimezone();
  final location = tz.timeZoneDatabase.getLocation(locationName);
  tz.setLocalLocation(location);
  print('tz.local: ${tz.local}'); // tz.local: Asia/Tokyo
}

/// アプリ内のどこかの関数
void somePlace() {
  print('tz.local: ${tz.local}'); // tz.local: UTC
}

原因

原因としては、DeviceCalendarPluginshouldInitTimezone: trueで初期化すると、DeviceCalendarPlugin内でも タイムゾーン の初期化が実行され、その際に tz.localが UTC として初期化されてしまうことでした。

device_calendar.dart
factory DeviceCalendarPlugin({bool shouldInitTimezone = true}) {
  if (shouldInitTimezone) {
    tz.initializeTimeZones(); // <- ここでタイムゾーン初期化されtz.localがUTCに
  }
  return _instance;
}
https://github.com/builttoroam/device_calendar/blob/a6352f60480e8ff92bd058af52768d079a9c4cc1/lib/src/device_calendar.dart#L25-L30

解決策

DeviceCalendarPlugin を初期化する際に、shouldInitTimezone: falseとして初期化しましょう。

final deviceCalendarPlugin = DeviceCalendarPlugin(shouldInitTimezone: false)

備考

グローバル変数はいつの間にか他から上書きされてしまうこともあり、やっぱり怖いですね、、
調査に意外と時間がかかったので、誰かにお役に立てれば幸いです 🙌

GitHubで編集を提案

Discussion