views:

149

answers:

5

I've got a string representation of a time, like "11:13 AM." This was produced using an NSDateFormatter and the stringFromDate: method.

I'd like to compare this time to the current time, but when I use the dateFromString: method to turn the string back into a date, a year, month and day are added - which I don't want. I just need to know if right now is < or > the time stored in the string.

What's going to be the best way to handle that? Thanks in advance for your help.

A: 

If the string was originally created from an NSDate, then you'll want to use that original NSDate to compare against [NSDate date] using NSDate's compare: method (or some variant, such as earlierDate: or laterDate:).

Dave DeLong
I don't have the original NSDate instance; I create the date string from a date picker value, then save the string, because all I care about is the time value. When my user taps a button, I need to check the current time value against the stored string's time value and figure out which one is earlier/later/current. I'm thinking now that I need to use something like NSCalendar's dateFromComponents: method and pass in the time values to create the appropriate NSData objects, and then run the compare: method.
Andy
@Andy what's wrong with `NSDate * pickedDate = [myDatePicker date];`?
Dave DeLong
I think most of my problem stems from the fact that I'm using the picked date for two fundamentally different things: one, to record a time for comparison with another time at some later date, and two, to display the selected value to the user in the user interface after the time is selected. I'm going to try a couple of these suggestions, and I'll report back a little later on the winning solution.
Andy
+3  A: 

If I understand the problem correctly, you’re using the dateFromString: method of NSDateFormatter. This is giving you the correct time, but with a default date of January 1, 1970, which is useless to compare against the current date/time.

This is easy to solve. Use setDefaultDate: to set the default date to today.

NSDate *now = [NSDate date];

NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:@"hh:mm a"];
[formatter setDefaultDate:now];

NSDate *theDate = [formatter dateFromString:@"11:13 AM"];
NSComparisonResult theResult = [theDate compare:now];
Nate
+2  A: 

Can you reuse the string formatter that you used to create the string? So, let's say you created the string like this:

NSDateFormatter *formatter = [[[NSDateFormatter alloc] init];
[formatter setDateFormat:@"HH:mm a"];
NSString *dateAsString = [formatter stringFromDate:[NSDate date]];

You can get an NSDate like this:

NSDateFormatter *formatter = [[[NSDateFormatter alloc] init];
[formatter setDateFormat:@"HH:mm a"];
NSDate *date = [formatter dateFromString:dateAsString];

The day, month, year and timezone information will not be kept, but you'll have an NSDate object with the values of 1/1/1970 and GMT for the timezone offset.

At this point you can use the compare: (which is typically reserved for sorting operations) or the laterDate: or earlierDate: methods.

Be careful using NSDateFormatter like this, as you may run into issues with internationalization.

If you need to add information about the current date to the date you get from dateFromString:, such as the month day and year, you'll need to use NSCalendar's dateByAddingComponents:toDate:options: method.

Jamie Pinkham
+2  A: 

Instead of using the string representation, use the NSDate you got from the picker. You can convert that hour/min/sec using NSDateComponents, then also convert [NSDate date] to NSDateComponents. Compare the hours/minutes/seconds of the two sets of components.

EDIT -- use a utility function for things like this that converts the hr/min/sec components of NSDate into a secondsOfTheDay (seconds since midnight).

You can directly use two time of day values since they are both seconds since midnight. Simple integers can be easily compared and stored and manipulated. You don't have to use NSDate all the time.

//----------------------------------------------------------------------------
// extracts hour/minutes/seconds from NSDate, converts to seconds since midnight
//----------------------------------------------------------------------------
unsigned secondOfTheDay( NSDate* time )
{
    NSCalendar* curCalendar = [NSCalendar currentCalendar];
    const unsigned units    = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
    NSDateComponents* comps = [curCalendar components:units fromDate:time];
    int hour = [comps hour];
    int min  = [comps minute];
    int sec  = [comps second];

    return ((hour * 60) + min) * 60 + sec;
}
progrmr
This seems like the most logical way to do it.
Chuck
Yep, this ended up being the solution (although the others mentioned here would probably have worked, too). I ended up adding another attribute to my Core Data entity to hold the date as an NSDate instance, then decomposed it to components and compared that to the components gotten from the current date. Works like a charm, but the code is butt-ugly. Thank god for code-folding.
Andy
A: 

You should use 24-hour based NSDateFormatter and compare as strings ("09:00am" > "08:00pm", but "09:00" < "20:00") . But in general it is right to operate with NSDate instances instead of strings

vaddieg