0

The logic for my problem is a mouthful and I have already come up with a solution. My solution is posted below. I am looking to see if someone can come up with a more efficient / simpler solution.

The method is supposed to return the next, future from now, occurring weekday given a date. Time should be preserved between the input date and the output date.

For all examples, today is Friday May 8, 2015, 4:00 PM: All inputs and outputs are in 2015:

+---------------------------+---------------------------+
|           Input           |          Output           |
+---------------------------+---------------------------+
| Tuesday April 7, 3:00 PM  | Monday May 11, 3:00 PM    |
| Thursday May 7, 3:00 PM   | Monday May 11, 3:00 PM    |
| Thursday May 7, 5:00 PM   | Friday May 8, 5:00 PM     |
| Tuesday May 12, 3:00 PM   | Wednesday May 13, 3:00 PM |
| Saturday June 20, 3:00 PM | Monday June 22, 3:00 PM   |
+---------------------------+---------------------------+

Here is some pseudo code for the logic:

do {
    date += 1 day;
} while(date.isWeekend || date.isInThePast)

Here is the solution I came up with, avoiding the use of loops to keep efficiency in mind:

- (NSDate *)nextWeekDayInFuture {
    NSDate *now = [NSDate date];
    NSDate *nextWeekDaydate;
    NSCalendar *calendar = [NSCalendar currentCalendar];
    nextWeekDaydate = [self dateByAddingDays:1]; // custom method, adds 1 day

    if ([nextWeekDaydate isLessThan:now]) {
        NSDateComponents *nowComponents = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:now];
        NSDateComponents *dateComponents = [calendar components:(NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond) fromDate:nextWeekDaydate];

        [nowComponents setHour:dateComponents.hour];
        [nowComponents setMinute:dateComponents.minute];
        [nowComponents setSecond:dateComponents.second];

        nextWeekDaydate = [calendar dateFromComponents:nowComponents];
        if ([nextWeekDaydate isLessThan:now]) {
            nextWeekDaydate = [nextWeekDaydate dateByAddingDays:1];
        }
    }

    NSDateComponents *components = [calendar components:NSCalendarUnitWeekday fromDate:nextWeekDaydate];
    if (components.weekday == Saturday) {
        nextWeekDaydate = [nextWeekDaydate dateByAddingDays:2];
    } else if (components.weekday == Sunday) {
        nextWeekDaydate = [nextWeekDaydate dateByAddingDays:1];
    }

    return nextWeekDaydate;
}

Use the input / output table from above to test your logic before posting a solution.

Kris Gellci
  • 9,539
  • 6
  • 40
  • 47
  • How does an input of Tuesday April 7 give an output of Monday in May? Why not Wednesday April 8? Same thing for the second line - why not Friday May 8 – Paulw11 May 08 '15 at 22:05
  • Notice the following, "For all examples, today is Friday May 8, 2015, 4:00 PM: All inputs and outputs are in 2015:". One of the requirements is that it has to be in the future from today, the returned date can not be in the past. – Kris Gellci May 08 '15 at 22:16
  • 1
    I'm voting to close this question as off-topic because it belongs on codereview.stackexchange.com. – rmaddy May 08 '15 at 22:27
  • @maddy If you head over to http://stackoverflow.com/help/on-topic you can see that it abides by the on-topic section. Just because it also conforms to another on-topic section on a related site, does not mean it does not conform to the one on this site. – Kris Gellci May 08 '15 at 22:41

1 Answers1

0

There's no reason not to place the logic in a loop, since at most it will loop twice (If the current day is Saturday).

Here is a solution for working out if a current day is a weekend: How to find weekday from today's date using NSDate?

- (NSInteger)isWeekend:(NSDate*)inDate
{
    NSCalendar* cal = [NSCalendar currentCalendar];
    NSDateComponents* comp = [cal components:kCFCalendarUnitWeekday fromDate:inDate];
    return [comp weekday];
}

We can then call this method, checking the returned NSInteger to see if it is sat or sun and run it again:

NSDate *now = [NSDate date];
now = [now dateByAddingTimeInterval:60*60*24]; // Add 1 day's worth.

NSInteger curDay = [self isWeekend:now];

while ((curDay == 6) || (curDay == 1)) // Sat or Sund.
{
    now = [now dateByAddingTimeInterval:60*60*24]; // Add 1 day's worth.
    curDay = [self isWeekend:now];
}

If you really want to remove the loop, you can check if it's Sat and add 2 days worth, or if it's Sun and add 1 days worth.

NSDate *now = [NSDate date];
now = [now dateByAddingTimeInterval:60*60*24]; // Add 1 day's worth.
NSInteger curDay = [self isWeekend:now];

if (curDay == 6) // Sat
{
    now = [now dateByAddingTimeInterval:60*60*24*2]; // Add 2 day's worth.
}
else if (curDay == 1) // Sun
{
    now = [now dateByAddingTimeInterval:60*60*24]; // Add 1 day's worth.
}
Community
  • 1
  • 1
Sam
  • 320
  • 1
  • 5
  • You are ignoring the input for the problem. The current date is only half the problem. The other half is the date that I want the next weekday from. If the date that I want the next weekday from is a month into the future, I would expect to get back a date from there, not a date which is based off of today. Example, current date is Friday May 8, 2015, 4:00 PM, Input is Saturday June 20, 3:00 PM, Output should be Monday June 22, 3:00 PM. Your algorithm does not account for the input and would return to me Monday May 11. – Kris Gellci May 11 '15 at 19:40
  • This will work with any provided date, I just used the date "now" as an example (NSDate *now = [NSDate date];). Your question states that you already have a date in the future, and u simply want to find out the next weekday from that date. It is trivial to replace my NSDate *now, with any NSDate that you have created elsewhere. The algorithm is not responsible for creating the input to the problem description as well as the solution. – Sam May 12 '15 at 15:39
  • I will try to simplify the problem. There are two inputs. The date today and the date that is passed in. The problem is to get the next weekday based on those inputs. Which is why I specified in my original post that today is Friday May 8, 2015, 4:00 PM and then I gave several inputs, some in the past and some in the future. If you read the question thoroughly, you will have a better understanding of the problem, currently you do not understand the actual problem. – Kris Gellci May 12 '15 at 17:37