【问题标题】:How to convert DateTime to TZDateTime in flutter?如何在颤动中将 DateTime 转换为 TZDateTime?
【发布时间】:2021-01-26 00:51:40
【问题描述】:

我正在尝试使用 flutter_local_notifications 包通过我的应用程序推送本地通知,并且在 FlutterNotificationsPlugin 上,“.schedule”已被弃用,我尝试使用“.zonedSchedule”,但它需要 TZDateTime 值。

var androidDetails = AndroidNotificationDetails(t.id, "Task Notifier",
        "Notifies if you have a task scheduled at a particular time");
    var generalNotificationDetails =
        NotificationDetails(android: androidDetails);
    var now = DateTime.now();
    var scheduledTime = DateTime(
            now.year, now.month, _dayTasks.date.day, t.time.hour, t.time.minute)
        .subtract(Duration(minutes: 5));
    //use zonedSchedule once you figure out how to convert datetime to TZdatetime
    // await notifications.zonedSchedule(
    //     0, "Task", t.description, scheduledTime, generalNotificationDetails,
    //     androidAllowWhileIdle: true,
    //     uiLocalNotificationDateInterpretation:
    //         UILocalNotificationDateInterpretation.wallClockTime);
    await notifications.schedule(0, "Ideal Day Task", t.description,
        scheduledTime, generalNotificationDetails);

【问题讨论】:

标签: android flutter datetime flutter-notification


【解决方案1】:

我也遇到了同样的问题并试图找到解决方案,但有些解决方案要么已过时,要么正在使用不同的软件包。 zonedSchedule() 函数需要 TZDateTime。所以在这里我们可以

Duration offsetTime= DateTime.now().timeZoneOffset;

这将为我们提供您的机器时间和 UTC 之间的差异,然后我们将从本地时间中减去它(默认为 UTC)

import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz; 
.
.
.
Future initializetimezone() async {
    tz.initializeTimeZones();
  }

Future<void> scheduleNotification()async{
await initializetimezone();
var androidChannel = AndroidNotificationDetails(
      'App',
      "Notifications",
      'Customize',
      importance: Importance.max,
      priority: Priority.high,
      playSound: true,
      enableLights: true,
      ongoing: false,
      visibility: NotificationVisibility.public,
    );
var iosChannel = IOSNotificationDetails();
var platfromChannel =
    NotificationDetails(android: androidChannel, iOS: iosChannel);
// year, month, etc can manually entered or you can use 
// DateTime.now() also for current time in local machine.
tz.TZDateTime zonedTime = tz.TZDateTime.local(year,month,day,hour,
                          minute).subtract(offsetTime);
 await flutterLocalNotificationsPlugin.zonedSchedule(
      0,
      'Some Notification',
      'Description',
      zonedTime ,
      platfromChannel,
      uiLocalNotificationDateInterpretation:
          UILocalNotificationDateInterpretation.absoluteTime,
      payload: 'Payload',
      androidAllowWhileIdle: true,
    );
}

我希望这会有所帮助。当 UTC 和本地机器之间的时差为正(+5:30:00.000000)时,这对我有用,我不确定负时差国家/地区。

【讨论】:

    【解决方案2】:

    确实, zonedSchedule() 需要 TZDateTime 值。我采用的方法是利用另一个包将原始 DateTime 值转换为 TZDateTime 值。下面是我使用的一个实现的摘录。看到第五行了吗?它涉及函数 TZDateTime.from()。它采用您最初可能使用的 DateTime 并将其转换为 TZDateTime。但是,它需要您当前的位置。这就是 TimeZone 类的用武之地。

        import 'package:timezone/timezone.dart' as tz;
        :
        :
        :
    
        final timeZone = TimeZone();
    
        // The device's timezone.
        String timeZoneName = await timeZone.getTimeZoneName();
    
        // Find the 'current location'
        final location = await timeZone.getLocation(timeZoneName);
    
        final scheduledDate = tz.TZDateTime.from(dateTime, location);
    
        try {
          await _flutterLocalNotificationsPlugin.zonedSchedule(
            id,
            title,
            body,
            scheduledDate,
            platformChannelSpecifics,
            androidAllowWhileIdle: androidAllowWhileIdle,
            payload: payload,
            uiLocalNotificationDateInterpretation:
                uiLocalNotificationDateInterpretation,
          );
        } catch (ex) {
          id = -1;
        }
        return id;
    

    我很快就编写了 TimeZone 类。此类与另一个插件 (flutter_native_timezone) 一起使用,该插件查找设备的“当前位置”并提供该区域设置的标准名称:

    import 'package:timezone/data/latest.dart';
    import 'package:timezone/timezone.dart' as t;
    import 'package:flutter_native_timezone/flutter_native_timezone.dart';
    
    class TimeZone {
      factory TimeZone() => _this ?? TimeZone._();
    
      TimeZone._() {
        initializeTimeZones();
      }
      static TimeZone _this;
    
      Future<String> getTimeZoneName() async => FlutterNativeTimezone.getLocalTimezone();
    
      Future<t.Location> getLocation([String timeZoneName]) async {
        if(timeZoneName == null || timeZoneName.isEmpty){
          timeZoneName = await getTimeZoneName();
        }
        return t.getLocation(timeZoneName);
      }
    }
    

    使用该课程,您就可以开始了。

    【讨论】:

    • _this 将始终保持为空,不是吗?
    • 我讨厌这个。 DateTime 中有时区...The function 'TimeZone' isn't defined...
    【解决方案3】:

    我刚刚尝试解决同样的问题。要理解这一点,我们需要对平台渠道有一个基本的了解。

    https://flutter.dev/docs/development/platform-integration/platform-channels?tab=android-channel-kotlin-tab

    一旦我们理解了这一点,示例中的代码应该会变得更容易理解: https://github.com/MaikuB/flutter_local_notifications/blob/1fe78b9d129d674cd97cfba49734577b24c56925/flutter_local_notifications/example/android/app/src/main/java/com/dexterous/flutterlocalnotificationsexample/MainActivity.java

    实践中的概念:

    首先,我们需要像这样导入 tz。这可以在您的 main.dart 或帮助文件中完成。

    import 'package:timezone/data/latest.dart' as tz;
    import 'package:timezone/timezone.dart' as tz;
    

    要从普通日期时间创建TZDateTime,我们需要通过平台通道查询来使用设备时区。

    Future<void> configureLocalTimeZone() async {
      tz.initializeTimeZones();
      final String timeZoneName = await platform.invokeMethod('getTimeZoneName');
      tz.setLocalLocation(tz.getLocation(timeZoneName));
    }
    

    其中getTimeZoneName在平台特定实现中实现。

    请务必在下一步之前致电configureLocalTimeZone

    当我们想从 DateTime 对象创建 TZDateTime 时,我们通常可以这样做

    var time = tz.TZDateTime.from(
        scheduledNotificationDateTime,
        tz.local,
    );
    

    这里的示例代码展示了完整的实现: https://github.com/MaikuB/flutter_local_notifications/blob/1fe78b9d129d674cd97cfba49734577b24c56925/flutter_local_notifications/example/lib/main.dart

    在我非常简单的工作流程中,我没有考虑不同的边缘情况,所以 YMMV。 希望这可以帮助! :)

    【讨论】:

    • 你知道为什么我们有 TZDateTime 而 Datetime 里面有 TZ 吗?
    • @OliverDixon 因为DateTime只能代表UTC或本地时区,不能代表指定时区。
    猜你喜欢
    • 1970-01-01
    • 2018-10-16
    • 2022-01-25
    • 2019-08-15
    • 2021-12-30
    • 1970-01-01
    • 2020-07-09
    • 2021-07-19
    • 2020-04-16
    相关资源
    最近更新 更多