Josh Kahane
Josh Kahane

Reputation: 17169

Time Left Until Date (At Midnight?)

I have some code which works out the time from today until a given date, this date being one the user has chosen from a date picker.

I will post the code below, but first my issue. I have a label which updates with the months, days, hours etc left until the selected date. However, when it gets down to the day before the selected date it goes weird.

I would have assumed (probably wrongly) and want it to countdown to midnight, so as soon as the selected day its, I change that my label to whatever I like. Instead, it says there is still 24 hours left about 4 hours prior to midnight of the selected date.

I just want it to countdown to midnight.

systemCalendar = [NSCalendar currentCalendar];
    unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
    components = [systemCalendar components:unitFlags
                                   fromDate:[NSDate date]
                                     toDate:[[NSUserDefaults standardUserDefaults] objectForKey:@"dateSaved"]
                                    options:0];

if (![[NSUserDefaults standardUserDefaults] objectForKey:@"dateSaved"]) 
    {
        dateLbl.text = @"You haven't chosen a date yet.";
    }
    else
    {
        //Plural string variations
        NSString *seconds = @"Seconds";
        NSString *minutes = @"Minutes";
        NSString *hours = @"Hours";
        NSString *days = @"Days";
        NSString *months = @"Months";
        NSString *years = @"Years";

        //No time left until wedding day
        if ([components year] <= 0 && [components month] <= 0 && [components day] <= 0 && [components hour] <= 0 && [components minute] <= 0 && [components second] <= 0)
        {
            dateLbl.text = @"It's Your Day!";
        }
        //Hours left until day
        else if ([components year] <= 0 && [components month] <= 0 && [components day] <= 0 && ([components hour] > 0 || [components minute] > 0 || [components second] > 0))
        {
            if ([components hour] > 1) hours = @"Hours";
            else hours = @"Hour";

            if ([components minute] > 1) minutes = @"Minutes";
            else minutes = @"Minute";

            if ([components second] > 1) seconds = @"Seconds";
            else seconds = @"Second";

            dateLbl.text = [NSString stringWithFormat:@"%i %@, %i %@, %i %@ Until Your Day", [components hour], hours, [components minute], minutes, [components second], seconds];
            //dateLbl.text = @"Tomorrow is your day!";
        }
        //Days left until day
        else if ([components year] <= 0 && [components month] <= 0 && [components day] > 0)
        {
            if ([components day] > 1) days = @"Days";
            else days = @"Day";

            dateLbl.text = [NSString stringWithFormat:@"%i %@ Until Your Day", [components day], days];
        }
        //Months left until day
        else if ([components year] <= 0 && [components month] > 0)
        {
            if ([components month] > 1) months = @"Months";
            else months = @"Month";

            if ([components day] > 1) days = @"Days";
            else days = @"Day";

            dateLbl.text = [NSString stringWithFormat:@"%i %@, %i %@ Until Your Day", [components month], months, [components day], days];
        }
        //Years left until day
        else if ([components year] > 0)
        {
            if ([components year] > 1) years = @"Years";
            else years = @"Year";

            if ([components month] > 1) months = @"Months";
            else months = @"Month";

            if ([components day] > 1) days = @"Days";
            else days = @"Day";

            dateLbl.text = [NSString stringWithFormat:@"%i %@, %i %@, %i %@ Until Your Day", [components year], years, [components month], months, [components day], days];
        }
    }

Upvotes: 0

Views: 916

Answers (2)

Vadym
Vadym

Reputation: 1077

There is almost the same solution by Keith Lazuka:

NSDateAdditions.h and NSDateAdditions.m

But it contains also other useful methods:

- (NSDate *)cc_dateByMovingToBeginningOfDay;
- (NSDate *)cc_dateByMovingToEndOfDay;
- (NSDate *)cc_dateByMovingToFirstDayOfTheMonth;
- (NSDate *)cc_dateByMovingToFirstDayOfThePreviousMonth;
- (NSDate *)cc_dateByMovingToFirstDayOfTheFollowingMonth;
- (NSDateComponents *)cc_componentsForMonthDayAndYear;
- (NSUInteger)cc_weekday;
- (NSUInteger)cc_numberOfDaysInMonth;

Upvotes: 0

Josh Kahane
Josh Kahane

Reputation: 17169

Turns out I need to reset the date hours, minutes and seconds to 0, so that the date is at midnight when I save it.

So when saving the date from my date picker I do this:

NSDateComponents *components = [[NSCalendar currentCalendar] components:NSIntegerMax fromDate:[datePicker date]];
    //Reset date components
    [components setHour:0];
    [components setMinute:0];
    [components setSecond:0];
    //Create new date with components reset for midnight of selected day
    NSDate *midnight = [[NSCalendar currentCalendar] dateFromComponents:components];

So now I have the date which I selected with the hours, minute and seconds set to midnight, so the countdown runs to the correct time.

Found the solution to do so here:

How to retrieve number of hours past midnight from an NSDate object?

Upvotes: 2

Related Questions