如何创建代表下一个指定日期时间的完整 NSDate 对象?
Posted
技术标签:
【中文标题】如何创建代表下一个指定日期时间的完整 NSDate 对象?【英文标题】:How can I create a complete NSDate object that represents the next specified day time? 【发布时间】:2010-08-11 04:22:25 【问题描述】:我可能没有把这个标题说得足够清楚,但是如果用户指定了下午 2:30 的时间,而现在是下午 2:00,那么我需要一个 NSDate 对象来表示当天的时间为下午 2:30 .如果用户指定了下午 2:30 的时间并且当前是下午 3:00,那么我需要一个 NSDate 对象来表示明天的时间为下午 2:30。类似于闹钟的工作原理。
我已经写了这段代码,但它太长了,感觉很笨拙,我觉得它应该更简单,但我是 ios 开发和这个特定 API 的新手。
非常感谢您的帮助!
【问题讨论】:
【参考方案1】:您是否已经有一个 NSDate 代表用户选择的日期/时间?如果是这样,将其与现在进行比较(通过earlierDate:
或laterDate:
)并在一天后创建一个新的(通过dateWithTimeInterval:sinceDate:
或initWithTimeInterval:sinceDate:
)是一件非常简单的事情。
类似这样的:
// Assume dateTarget is an NSDate representing the date/time the user picked.
// Is it earlier than now?
if( [dateTarget earlierDate:[NSDate date]] == dateTarget )
// dateTarget is earlier than now.
// Add 1 day to it.
NSDate* newDate = [[NSDate alloc]initWithTimeInterval:60*60*24 sinceDate:dateTarget];
[dateTarget release];
dateTarget = newDate;
// dateTarget is now either the original time, or if that time passed, the same time tomorrow.
NSLog( @"dateTarget = %@", dateTarget );
【讨论】:
【参考方案2】:我相信,如果您添加的时间间隔会在夏令时日期前后出现混乱。增加一天的秒数将在一天后结束,但会提前或推迟一个小时。我很确定我以前遇到过这种情况,但我猜你可以轻松测试。
另一种方法是使用 NSDateComponents:
// using while will be inefficient when the targetDate is more than a few days in the past
while ([targetDate compare:[NSDate date]] == NSOrderedAscending)
NSCalendar *calendar = [NSCalendar currentCalendar];
NSInteger units = NSYearCalendarUnit |
NSMonthCalendarUnit |
NSDayCalendarUnit |
NSHourCalendarUnit |
NSMinuteCalendarUnit |
NSSecondCalendarUnit;
NSDateComponents *comps = [calendar components:units fromDate:targetDate];
[comps setDay:[comps day] + 1]; // if day is 32 for instance, it'll automatically roll over to the next month
NSDate *targetDate = [calendar dateFromComponents:comps];
以上绝不是一个理想的解决方案(例如,如果您保留它,它会泄漏 targetDate),但主要是为了向您展示如何使用 NSDateComponents 为 NSDate 添加 1 天。
【讨论】:
【参考方案3】:假设用户使用UIDatePicker
选择日期,我会这样做:
NSDate * selectedDate = ...; //2:30pm
NSDate * selectedComponents = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:selectedDate];
NSDate * now = [NSDate date];
NSDate * nowComponents = [[NSCalendar currentCalendar] components:NSUIntegerMax fromDate:now];
[nowComponents setHour:[selectedComponents hour]];
[nowComponents setMinute:[selectedComponents minute]];
NSDate * targetDate = [[NSCalendar currentCalendar] dateFromComponents:nowComponents];
if ([[now laterDate:targetDate] isEqual:now])
//in a comparison between now and the target date, the target date has already passed
[nowComponents setDay:[nowComponents day]+1];
targetDate = [[NSCalendar currentCalendar] dateFromComponents:nowComponents];
//target date is now at the appropriate 2:30pm
旁注:由于NSCalendarUnit
是NSUInteger
的位域类型定义,我传入NSUIntegerMax
以检索所有可能的日历单位。这样我就不必有大量的按位 OR 语句。
【讨论】:
给你的问题:如果你现在做Components setDay: day + 1,那一天是否重要,比如32?例如,如果 day 是一个月的最后一天?还是一切都会自己解决? @SeanDanzeiser-dateFromComponents:
将处理单元翻转。【参考方案4】:
如果你从用户那里得到 userDate 和 nowDate = [NSDate date]
,那么
NSComparisonResult diff = [userDate compare: nowDate];
如果 diff 是NSOrderedDescending
,那么 userDate 比 nowDate 晚,你设置了今天的闹钟。如果是NSOrderedAscending
,那么你设置明天的闹钟。你可以测试NSOrderedSame
,但它永远不会。
您不想确定今天是哪一天,所以在我看来,添加 NSTimeInterval
的差异加上 24 * 60 * 60(如果闹钟是明天)或只是差异(如果闹钟是今天)就足够了。
我不知道为什么每个人都在尝试制作闹钟。据我所知,这是不可能的。
【讨论】:
有了iOS 4和本地通知,闹钟就可以搞定了。 你不应该使用 24 * 60 * 60 来表示一天,使用 NSDateComponents 和 NSCalendar 来添加 1 天。如果你使用硬编码的时间间隔,你最终会遇到一堆边缘情况,例如如果夏令时结束,您的“明天”时间将减少一个小时。以上是关于如何创建代表下一个指定日期时间的完整 NSDate 对象?的主要内容,如果未能解决你的问题,请参考以下文章
如何创建过去的新 NSDate 对象,例如比另一个日期早 1 秒?