如何创建一个完整的 NSDate 对象来表示下一个指定的日期时间?

发布于 2024-09-13 23:56:16 字数 250 浏览 8 评论 0原文

我可能没有把这个标题说得足够清楚,但如果用户指定时间为下午 2:30,而当前是下午 2:00,那么我需要一个 NSDate 对象来表示当天的时间为下午 2:30。如果用户指定时间为下午 2:30,而当前是下午 3:00,那么我需要一个 NSDate 对象来表示明天的时间为下午 2:30。类似于闹钟的工作原理。

我已经写了这段代码,但它太长了,而且感觉很混乱,我觉得它应该更简单,但我对 iOS 开发和这个特定的 API 很陌生。

预先非常感谢您的帮助!

I probably didn't word that title clearly enough, but if the user specifies a time of 2:30pm and it's currently 2:00pm, then I need an NSDate object that represents the current day with a time of 2:30pm. If the user specifies a time of 2:30pm and it's currently 3:00pm, then I need an NSDate object that represents tomorrow with a time of 2:30pm. Similar to how an alarm clock would work.

I already wrote this code, but it's embarrassingly long and it feels really kludgy and I feel like it should be more simple, but I'm new to iOS development and this specific API.

Thanks so much in advance for your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

黄昏下泛黄的笔记 2024-09-20 23:56:16

您是否已经有一个代表用户选择的日期/时间的 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 );

Do you already have an NSDate representing the date/time the user picked? If so, it's a pretty simple matter to compare it to now (via earlierDate: or laterDate:), and create a new one a day later (via dateWithTimeInterval:sinceDate: or initWithTimeInterval:sinceDate:).

Something like this:

// 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 );
囍孤女 2024-09-20 23:56:16

我相信,如果您添加一个会扰乱夏令时日期的时间间隔。一天加上几秒,就会在一天后结束,但会提前或晚一个小时。我很确定我以前遇到过这个,但我想你可以很容易地测试一下。

另一种方法是使用 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 将 1 天添加到 NSDate。

If you add a time interval that messes up around the daylight savings dates, I believe. Adding seconds for one day will then end up a day after but an hour earlier or later. I'm pretty sure I ran into this before, but you can test that easily, I guess.

Another way would be to use 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];
}

The above is by no means an ideal solution (it'll leak targetDate if you retained it, for instance), but is mainly meant to show you how to add 1 day to a NSDate using NSDateComponents.

茶底世界 2024-09-20 23:56:16

假设用户使用 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

旁注:因为 NSCalendarUnitNSUInteger 的位字段类型定义code> 中,我传入 NSUIntegerMax 来检索所有可能的日历单位。这样我就不必有大量的按位或语句。

Assuming that the user is using a UIDatePicker to select the date, here's what I would do:

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

Side note: since the NSCalendarUnit is a bitfield typedef for NSUInteger, I pass in NSUIntegerMax to retrieve all possible calendar units. That way I don't have to have a massive bitwise OR statement.

江南月 2024-09-20 23:56:16

如果您从用户处获取 userDate,并且 nowDate = [NSDate date] ,那么

NSComparisonResult diff = [userDate compare: nowDate];

如果 diff 为 NSOrderedDescending ,则 userDate 晚于 nowDate,并且您为今天。如果是 NSOrderedAscending,那么您就设置了明天的闹钟。您可以测试 NSOrderedSame,但它永远不会。

您想避免必须确定今天是哪一天,所以在我看来,添加一个 NSTimeInterval 的差异加上 24 * 60 * 60 (如果闹钟是明天)或者只是差异(如果闹钟是今天的话)就足够了。

我不知道为什么大家都在尝试做闹钟。据我所知,这是不可能的。

If you get userDate from the user, and nowDate = [NSDate date] , then

NSComparisonResult diff = [userDate compare: nowDate];

If the diff is NSOrderedDescending, then userDate is later than nowDate, and you set the alarm for today. If it's NSOrderedAscending, then you set the alarm for tomorrow. You can test for NSOrderedSame, but it will never be.

You'd like to avoid having to determine what day it is, so it seems to me that adding an NSTimeInterval of the difference plus 24 * 60 * 60 (if the alarm is tomorrow) or just the difference (if the alarm is today) would suffice.

I don't know why everyone is trying to make alarm clocks. It can't be done, as best I can tell.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文