6

I'd like to make a countdown to the next full hour. It's pretty easy to countdown to a specific time, like:

NSDate *midnight = [NSDate dateWithNaturalLanguageString:@"midnight tomorrow"]; 

how do I define an NSDate for "the beginning of every hour"?

Thanks!

EDIT: This is what I have currently. Having trouble integrating the solutions in to my code. Any help would be greatly appreciated. :)

-(void)updateLabel {
NSDate *now = [NSDate date];

NSDate *midnight = [NSDate dateWithNaturalLanguageString:@"midnight tomorrow"]; 

//num of seconds between mid and now
NSTimeInterval timeInt = [midnight timeIntervalSinceDate:now];
int hour = (int) timeInt/3600;
int min = ((int) timeInt % 3600) / 60;
int sec = (int) timeInt % 60;
countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, min,sec];
}  
Abizern
  • 146,289
  • 39
  • 203
  • 257
dot
  • 2,823
  • 7
  • 38
  • 52

6 Answers6

17

As +dateWithNaturalLanguageString is available on MacOS SDK only and your're targeting iPhone you'll need to make a method of your own. I think NSCalendar class can help you:

- (NSDate*) nextHourDate:(NSDate*)inDate{
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *comps = [calendar components: NSEraCalendarUnit|NSYearCalendarUnit| NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit fromDate: inDate];
    [comps setHour: [comps hour]+1]; // Here you may also need to check if it's the last hour of the day
    return [calendar dateFromComponents:comps];
}

I have not checked this code but it (at least this approach) must work.

Chuck
  • 234,037
  • 30
  • 302
  • 389
Vladimir
  • 170,431
  • 36
  • 387
  • 313
  • The code given will currently work (even if the next hour is midnight), but I think you should technically use NSCalendar's `dateByAddingComponents:toDate:` rather than manually adding the components. NSCalendar is the right answer, though. – Chuck Feb 22 '10 at 07:42
  • 1
    Yes dateByAddingComponents:toDate looks more appropriate, but you still need to reset minute and second components to 0 somehow? – Vladimir Feb 22 '10 at 07:50
  • What doesn't work exactly? I've just run this code - it works ok for me (still don't know if it will work in case next hour is midnight) – Vladimir Feb 22 '10 at 08:08
  • hi vladimir.. I've added some details to my original question. Thansk! – dot Feb 22 '10 at 08:47
  • replace dateWithNaturalLanguageString call with call to nextHourDate ? – Vladimir Feb 22 '10 at 08:58
7

Using DateComponents and Date, you get it by adding a negative amount of minutes and one hour to the given date.

Swift3 (as an extension):

extension Date {
    public var nextHour: Date {
        let calendar = Calendar.current
        let minutes = calendar.component(.minute, from: self)
        let components = DateComponents(hour: 1, minute: -minutes)
        return calendar.date(byAdding: components, to: self) ?? self
    }
}

Use it with let nextHourDate = myDate.nextHour

See Apple Date and Time Programming Guide for reference.

===========================================================================

ObjectiveC (as a static method):

+ (NSDate *)nextHourDate:(NSDate *)date{
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [calendar components:NSMinuteCalendarUnit|NSHourCalendarUnit fromDate:date];
    components.minute = -components.minute;
    components.hour = 1;
    return [calendar dateByAddingComponents:components toDate:date options:0];
}

And call it with :

[YourClass nextHourDate:yourDate];
Dulgan
  • 6,674
  • 3
  • 41
  • 46
6

The simplest way probably to manipulate timestamp, round it to the beginning of current hour and add 1 hour

- (NSDate*)nextHourDateForDate:(NSDate*)date {
    NSTimeInterval timestamp = [date timeIntervalSince1970];
    NSTimeInterval current = timestamp - fmod(timestamp, 3600);
    NSTimeInterval next = current + 3600;

    return [NSDate dateWithTimeIntervalSince1970:next];
}
pronebird
  • 12,068
  • 5
  • 54
  • 82
3

You might want to check this out. Erica Sadun posted some extensions to NSDate.

http://github.com/erica/NSDate-Extensions

xyzzycoder
  • 1,831
  • 13
  • 19
1

I think this would work (note: very briefly tested)

NSDateFormatter *currentSecondFormatter = [[NSDateFormatter alloc] init];
[currentSecondFormatter setDateFormat:@"ss"];
NSDateFormatter *currentMinuteFormatter = [[NSDateFormatter alloc] init];
[currentMinuteFormatter setDateFormat:@"mm"];

// get next hour from now
int timeUntilNextHour = ( (60 - [[currentMinuteFormatter stringFromDate:[NSDate date]] integerValue]) * 60) -  [[currentSecondFormatter stringFromDate:[NSDate date]] integerValue];
Davy Smith
  • 11
  • 1
0

Maybe this can be helpful

@implementation NSDate (DB_Extension)

- (NSTimeInterval)db_secondsForNextHour {

NSDateFormatter *minutesFormatter = [[NSDateFormatter alloc] init];
[minutesFormatter setDateFormat:@"mm"];

NSDateFormatter *secondsFormatter = [[NSDateFormatter alloc] init];
[secondsFormatter setDateFormat:@"ss.SSS"];

NSTimeInterval secondsForNextHour = (60.0 - [[minutesFormatter stringFromDate:self] doubleValue])*60 - [[secondsFormatter stringFromDate:self] doubleValue];

return secondsForNextHour;

}

DigitalBrain_DEV
  • 1,093
  • 13
  • 27