如何在flutter中将DateTime转换为TZDateTime?

6ie5vjzr  于 2022-11-25  发布在  Flutter
关注(0)|答案(4)|浏览(269)

我尝试使用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);
zysjyyx4

zysjyyx41#

确实,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);
  }
}

使用这个类,你就可以开始了。

n3ipq98p

n3ipq98p2#

我刚刚也尝试过解决同样的问题,要理解这个问题,我们需要对平台渠道有一个基本的了解。
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或一个helper文件中完成。

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

要从一个普通的dateTime创建一个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。希望这有帮助!:)

shstlldc

shstlldc3#

我也遇到了同样的问题,并试图找到解决方案,但一些解决方案要么是过时的,要么是使用不同的包。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)时,这对我有效,我不确定负时差的国家。

jm2pwxwz

jm2pwxwz4#

日期时间至TZDate时间:

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

...

DateTime dt = DateTime.now(); //Or whatever DateTime you want
final tzdatetime = tz.TZDateTime.from(dt, tz.local); //could be var instead of final

相关问题