Ben*_*ynn 21 datetime ios uilocalnotification
来自文档:
fireDate中指定的日期将根据此属性的值进行解释.如果指定nil(默认值),则开火日期将被解释为绝对GMT时间,适用于倒数计时器等情况.如果为此属性分配有效的NSTimeZone对象,则开火日期将被解释为当时区发生变化时自动调整的挂钟时间; 适用于这种情况的一个例子是闹钟.
假设我在明天GMT(绝对时间)中午安排本地通知.我计划在西雅图下午1点(太平洋时间,格林威治标准时间-8),然后立即前往芝加哥,到达晚上11点(中部时间,格林威治标准时间-6).我的设备从太平洋时间调整到中部时间.请帮助我了解在以下三种情况下我的通知何时发生:
brn*_*nes 43
我刚刚在iOS 6.1.3上运行了一些测试.这是我得到的:
我在西雅图,下午1点(太平洋夏令时,格林威治标准时间-7).我创建了一个NSDate:
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
// 2013-08-31 @ 12:00:00 (noon)
dateComponents.year = 2013;
dateComponents.month = 8;
dateComponents.day = 31;
dateComponents.hour = 12;
dateComponents.minute = 0;
dateComponents.second = 0;
NSDate *fireDate = [gregorianCalendar dateFromComponents:dateComponents];
Run Code Online (Sandbox Code Playgroud)
我现在有
fireDate = 2013-08-31 19:00:00 +0000 (2013-08-31 12:00:00 -0700)
Run Code Online (Sandbox Code Playgroud)
然后我创建并安排了通知:
notification1 = [[UILocalNotification alloc] init];
notification1.fireDate = fireDate;
// notification1.timeZone is nil by default
NSLog(@"%@", notification1);
notification2 = [[UILocalNotification alloc] init];
notification2.fireDate = fireDate;
notification2.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
NSLog(@"%@", notification2);
notification3 = [[UILocalNotification alloc] init];
notification3.fireDate = fireDate;
notification3.timeZone = [NSTimeZone defaultTimeZone];
NSLog(@"%@", notification3);
Run Code Online (Sandbox Code Playgroud)
刚刚在西雅图(太平洋夏令时,GMT-7)创建的通知的日志:
notification1:
fire date = Saturday, August 31, 2013, 12:00:00 PM Pacific Daylight Time,
time zone = (null),
next fire date = Saturday, August 31, 2013, 12:00:00 PM Pacific Daylight Time
notification2:
fire date = Saturday, August 31, 2013, 7:00:00 PM GMT,
time zone = GMT (GMT) offset 0,
next fire date = Saturday, August 31, 2013, 7:00:00 PM Pacific Daylight Time
notification3:
fire date = Saturday, August 31, 2013, 12:00:00 PM Pacific Daylight Time,
time zone = US/Pacific (PDT) offset -25200 (Daylight),
next fire date = Saturday, August 31, 2013, 12:00:00 PM Pacific Daylight Time
Run Code Online (Sandbox Code Playgroud)
我将手机的时区更改为芝加哥,现在是下午3:00(中部夏令时,GMT-5).
芝加哥的通知日志(中部夏令时,GMT-5)
notification1:
fire date = Saturday, August 31, 2013, 2:00:00 PM Central Daylight Time,
time zone = (null),
next fire date = Saturday, August 31, 2013, 2:00:00 PM Central Daylight Time
notification2:
fire date = Saturday, August 31, 2013, 7:00:00 PM GMT,
time zone = GMT (GMT) offset 0,
next fire date = Saturday, August 31, 2013, 7:00:00 PM Central Daylight Time
notification3:
fire date = Saturday, August 31, 2013, 12:00:00 PM Pacific Daylight Time,
time zone = US/Pacific (PDT) offset -25200 (Daylight),
next fire date = Saturday, August 31, 2013, 12:00:00 PM Central Daylight Time
Run Code Online (Sandbox Code Playgroud)
结论:
timeZone为零时,开火日期会及时修复.这意味着通知将在GMT-7中午12:00,格林威治标准时间-5:00 PM或格林尼治标准时间7:00触发.timeZone设置为GMT时,将根据GMT时间计算开火日期,如果用户转到另一个时区,则会自动更新.在此示例中,时间12:00 GMT-7被转换为格林威治标准时间19:00,并且通知设置为当地时间19:00,无论我们是什么时区(格林尼治标准时间19:00,格林威治标准时间19:00 19:00或19:00 GMT-7).timeZone设置为本地时区(太平洋夏令时,GMT-7)时,将计算当地时间的开火日期,如果用户转到另一个时区,则会自动更新.在此示例中,时间是格林威治标准时间-7:00,因此通知将在当地时间12:00开始,无论我们是什么时区(格林尼治标准时间12:00,格林威治标准时间12:00或格林威治标准时间12:00) 7).iOS 13 上带有 UNCalendarNotificationTrigger 的 Swift 5.2
我使用 @brnunes 代码作为灵感,用UNCalendarNotificationTrigger.
TimeZone.autoupdatingCurrent如果您想在当地时间发送通知,请使用。示例:您安排在下午 6 点 GMT 发送通知,然后将设备上的时区更改为 CET,通知仍将安排在下午 6 点在您的设备上。
如果您想要及时固定的开火日期,请使用任何其他时区,例如TimeZone.current或。TimeZone.init(abbreviation: "GMT")示例:您安排在东部夏令时间下午 2 点 (EDT GMT-4) 发送通知,然后将设备上的时区更改为 CEST (GMT+2),现在设备上的通知将安排在下午 8 点。这就像格林威治标准时间下午 6 点开会一样。会议时间不变,只是 EDT 为下午 2 点,CEST 为晚上 8 点。
我使用以下代码来添加通知:
func addNotification(identifier: String, timeZone: TimeZone?) {
let content = UNMutableNotificationContent()
content.title = "Title \(identifier)"
content.body = "Body"
let trigger = UNCalendarNotificationTrigger(
dateMatching: DateComponents(
calendar: Calendar.current,
timeZone: timeZone,
year: 2020,
month: 04,
day: 01,
hour: 18,
minute: 30,
second: 0),
repeats: false)
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
UNUserNotificationCenter
.current()
.add(request) { _ in
print("Scheduled \(identifier)")
}
}
Run Code Online (Sandbox Code Playgroud)
我添加了四个不同的通知。
addNotification(identifier: "1", timeZone: nil)
addNotification(identifier: "2", timeZone: TimeZone.init(abbreviation: "GMT")!)
addNotification(identifier: "3", timeZone: TimeZone.autoupdatingCurrent)
addNotification(identifier: "4", timeZone: TimeZone.current)
Run Code Online (Sandbox Code Playgroud)
我使用以下代码来打印预定的请求。
UNUserNotificationCenter.current().getPendingNotificationRequests(completionHandler: { notificationRequests in
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .medium
dateFormatter.timeZone = TimeZone.current
print(TimeZone.current)
notificationRequests.forEach({
let nextTriggerDate = ($0.trigger as! UNCalendarNotificationTrigger).nextTriggerDate()!
print("\($0.identifier): \(dateFormatter.string(from: nextTriggerDate)) (\(nextTriggerDate))")
})
})
Run Code Online (Sandbox Code Playgroud)
首先,我使用 CEST (GMT+2) 运行代码。然后,我进入 iOS 设置并将时区更改为迈阿密,EDT (GMT-4)。这是结果。
Europe/Berlin (current)
1: 1. Apr 2020 at 18:30:00 (2020-04-01 16:30:00 +0000)
2: 1. Apr 2020 at 20:30:00 (2020-04-01 18:30:00 +0000)
3: 1. Apr 2020 at 18:30:00 (2020-04-01 16:30:00 +0000)
4: 1. Apr 2020 at 18:30:00 (2020-04-01 16:30:00 +0000)
US/Eastern (current)
1: 1. Apr 2020 at 12:30:00 (2020-04-01 16:30:00 +0000)
2: 1. Apr 2020 at 14:30:00 (2020-04-01 18:30:00 +0000)
3: 1. Apr 2020 at 18:30:00 (2020-04-01 22:30:00 +0000)
4: 1. Apr 2020 at 12:30:00 (2020-04-01 16:30:00 +0000)
Run Code Online (Sandbox Code Playgroud)
正如您在 1、2 和 4 中看到的,时间日期永远不会改变。两次都是2020-04-01 16:30:00 +0000、2020-04-01 18:30:00 +0000和2020-04-01 16:30:00 +0000 。仅触发通知时的当地时间发生变化并更新。
使用 3 时,实际日期从2020-04-01 16:30:00 +0000更改为2020-04-01 22:30:00 +0000。然而,当地时间并没有改变,仍然是18:30:00。
UILocalNotification正如您在这里所看到的,@brnunes 的答案中时区的工作方式与和有所不同UNCalendarNotifactionTrigger。他在第二个结论中表示,会UILocalNotifictions针对不同时区自动更新。有了UNCalendarNotificationTrigger,情况就不再是这样了。正如 @Nicolas Buquet 所指出的,TimeZone.autoupdatingCurrent相当于defaultTimeZone.
| 归档时间: |
|
| 查看次数: |
5693 次 |
| 最近记录: |