Math issue using timeIntervalSince 1970 - iphone

I am trying to find how many milliseconds into the current day we are. I can't find a method to return the time in milliseconds ignoring date, so I figured I could calculate it off of the value returned by timeIntervalSince 1970 method.
I did this:
NSLog(#"%f", [[NSDate date] timeIntervalSince1970]);
2013-05-21 16:29:09.453 TestApp[13951:c07] 1369171749.453490
Now my assumption is that, since there are 86,400 seconds in a day I could divide this value by 86400 and get how many days have elapsed since 1970. Doing this gives me 15846.8952483 days. Now, if my assumption holds, I am 89.52483% through the current day. So multiple 24 hours by 86.52659% would give me a current time of the 21.4859592 hour or about 09:29 PM. As you can see from my NSLog this is about 5 hours from the real time, but I believe the interval returned is GMT so this would be 5 hours ahead of my time zone.
So I figured, well what the heck, I'll just roll with it and see what happens.
I cut off the decimal places by doing:
float timeSince1970 = [[NSDate date] timeIntervalSince1970]/86400.0;
timeSince1970 = timeSince1970 - (int)timeSince1970
Then calculate the milliseconds that have taken place thus far today:
int timeNow = timeSince1970 * 86400000;
NSLog(#"%i", timeNow);
2013-05-21 16:33:37.793 TestApp[14009:c07] 77625000
Then I convert the milliseconds (which still seem appropriate) to NSDate:
NSString *timeString = [NSString stringWithFormat:#"%d", timeNow];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"A"]
NSDate *dateNow = [dateFormatter dateFromString:timeString];
NSLog(#"%#", dateNow);
2013-05-21 16:29:09.455 TestApp[13951:c07] 2000-01-02 03:29:00 +0000
And there is my problem. Rather than returning a 2000-01-01 date with some hours and minutes attached, it is returning a 2000-01-02 date. Why!?
EDIT
I got it working by "removing" the extra 5 hours I noted in the above with:
int timeNow = (timeSince1970 * 86400000) - (5 * 60 * 60 * 1000);
I don't understand why this is necessary though. If someone can explain I'd greatly appreciate it.
EDIT 2
Perhaps I should be asking a more elementary question about how to accomplish the task I'm trying to accomplish. I care about times (for example, 4pm is important but I could care less about the date). I've been storing these in NSDates created by:
[dateFormatter setDateFormat:#"hh:mm a"];
[dateFormatter dateFromString#"04:00 PM"];
All this seems to be going fine. Now I want to compare current time to my saved time and find out if it is NSOrderedAscending or NSOrderedDescending and respond accordingly. Is there a better way to be accomplishing this?

You need to use NSCalendar to generate NSDateComponents based on right now, then set the starting hour, minute, and second all to 0. That will give you the beginning of today. Then you can use NSDate's -timeIntervalSinceNow method to get back the time elapsed between now and your start date.
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *now = [NSDate date];
// BUILD UP NSDate OBJECT FOR THE BEGINNING OF TODAY
NSDateComponents *comps = [cal components: (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate: now];
comps.hour = 0;
comps.minute = 0;
comps.second = 0;
// USE CALENDAR TO GENERATE NEW DATE FROM COMPONENTS
NSDate *startOfToday = [cal dateFromComponents: comps];
// YOUR ELAPSED TIME
NSLog(#"%f", [startOfToday timeIntervalSinceNow]);
Edit 1
If you're just looking to compare some NSDateObjects you can see if the time interval between then and now is negative. If so, that date is in the past.
NSDate *saveDate = [modelObject lastSaveDate];
NSTimeInterval difference = [saveDate timeIntervalSinceNow];
BOOL firstDateIsInPast = difference < 0;
if (firstDateIsInPast) {
NSLog(#"Save date is in the past");
}
You could also use compare:.
NSDate* then = [NSDate distantPast];
NSDate* now = [NSDate date];
[then compare: now]; // NSOrderedAscending

The part of your question that says that you want to calculate "how many milliseconds into the current day we are" and then "4pm is important but I could care less about the date" makes it not answerable.
This is because "today" there could have been a time change, which changes the number of milliseconds since midnight (by adding or subtracting an hour, for instance, or a leap second at the end of a year, etc....) and if you don't have the date, you can't determine the number of milliseconds accurately.
Now, to address your edited question: If we assume today's date, then you need to use the time that you have stored and combine it with today's date to get a "specific point in time" which you can compare to the current date and time:
NSString *storedTime = #"04:00 PM";
// Use your current calendar
NSCalendar *cal = [NSCalendar currentCalendar];
// Create a date from the stored time
NSDateFormatter *dateFormatter = [NSDateFormatter new];
[dateFormatter setDateFormat:#"hh:mm a"];
NSDate *storedDate = [dateFormatter dateFromString:storedTime];
// Break it up into its components (ie hours and minutes)
NSDateComponents *storedDateComps = [cal components:NSHourCalendarUnit | NSMinuteCalendarUnit
fromDate:storedDate];
// Now we get the current date/time:
NSDate *currentDateAndTime = [NSDate date];
// Break it up into its components (the date portions)
NSDateComponents *todayComps = [cal components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
fromDate:currentDateAndTime];
// Combine with your stored time
todayComps.hour = storedDateComps.hour;
todayComps.minute = storedDateComps.minute;
// Create a date from the comps.
// This will give us today's date, with the time that was stored
NSDate *currentDateWithStoredTime = [cal dateFromComponents:todayComps];
// Now, we have the current date and the stored value as a date, so it is simply a matter of comparing them:
NSComparisonResult result = [currentDateAndTime compare:currentDateWithStoredTime];

it is returning a 2000-01-02 date. Why!?
Because your dateFormatter uses the current system locale's timezone.
If you insert ...
dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
... your date formatter will interpret the string correctly. But why not creating the date directly:
NSDate *dateNow = [NSDate dateWithTimeIntervalSinceReferenceDate:timeNow];

Related

NSDateComponent setHour is not setting correctly [duplicate]

This question already has an answer here:
sethours in NSDateComponents
(1 answer)
Closed 9 years ago.
I am trying to create a date with the time set to 12:00:01 am. Seconds and minutes set to their values correctly but the hour value always goes to whatever i set the value, + 4. Why 4? What is so special about that value? The minute and second values set to what I want correctly but it appears the hours value simply adds rather than replaces.
here is the code,
NSDate *now = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:now];
[components setHour:0];
[components setMinute:0];
[components setSecond:1];
NSDate *compareTime = [calendar dateFromComponents:components];
NSLog(#"compareTime: %#", compareTime);
NSLog(#"currentTime: %#", now);
output is :
compareTime: 2013-05-17 04:00:01 +0000
currentTime: 2013-05-17 15:00:37 +0000
EST is 4 hours ahead of GMT, hence your offset. Here's some code we use to create dates plus and minus the current time in the local time zone.
- (NSDate *) getDateWithHoursOffset : (int) aHourInt
{
CFGregorianDate gregorianStartDate, gregorianEndDate;
CFGregorianUnits startUnits = { 0,0,0, aHourInt,0,0 }; //2 hours before
CFGregorianUnits endUnits = { 0,0,0, 8,0,0 }; //5 hours ahead
CFTimeZoneRef timeZone = CFTimeZoneCopySystem();
gregorianStartDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeAddGregorianUnits(CFAbsoluteTimeGetCurrent(), timeZone, startUnits),timeZone);
gregorianStartDate.minute = 0;
gregorianStartDate.second = 0;
gregorianEndDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeAddGregorianUnits(CFAbsoluteTimeGetCurrent(), timeZone, endUnits),timeZone);
gregorianEndDate.minute = 0;
gregorianEndDate.second = 0;
NSDate* startDate = [NSDate dateWithTimeIntervalSinceReferenceDate:CFGregorianDateGetAbsoluteTime(gregorianStartDate, timeZone)];
CFRelease(timeZone);
return startDate;
}
NSDates exist independently of timezones. If you need the date to display 12:00:01 in the application, you should use a NSDateFormatter.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterFullStyle];
NSLog(#"formattedTime: %#", [dateFormatter stringFromDate:compareTime]);
This returns:
formattedTime: 12:00:01 AM Central Daylight Time
The problem is that your dates are correct but they're being logged in UTC relative to your device's time zone and that seems confusing. (It is, at first)
Your compare time is correct. It is set to midnight your time and outputted as UTC and if you're EST midnight would be 4am UTC:
compareTime: 2013-05-17 04:00:01 +0000
Current time is also correct, and again it is UTC time relative to your device's time zone:
currentTime: 2013-05-17 15:00:37 +0000
Your times are correct, its the output that is deceiving you.
This code (shamefully stolen from a thread listed below) should output compareTime's UTC date as 00:00:01 +0000. Though for date calculations UTC should be fine.
NSTimeZone* sourceTimeZone = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
NSTimeZone* destinationTimeZone = [NSTimeZone systemTimeZone];
NSInteger sourceGMTOffset = [sourceTimeZone secondsFromGMTForDate:sourceDate];
NSInteger destinationGMTOffset = [destinationTimeZone secondsFromGMTForDate:sourceDate];
NSTimeInterval interval = destinationGMTOffset - sourceGMTOffset;
NSDate* destinationDate = [[NSDate alloc] initWithTimeInterval:interval sinceDate:compareTime];
Here are a few S.O. threads to help further explain:
Does [NSDate date] return the local date and time?
Why isn't my time zone being saved into my NSDate?
NSDate is not returning my local Time zone /default time zone of device

NSDate troubles - or how to ignore date/timezone?

Alright I've given up on this. Here's what I'm trying to do: I have a sunrise, sunset, and the current time in a certain timezone. I want to know if it's day or night by figuring out if the current time lies between the sunrise and the sunset times.
Here's what I have:
NSLog(#"%# - %# - %#",currTime,sunrise,sunset);
NSDateFormatter *formatter1 = [[NSDateFormatter alloc]init];
NSDateFormatter *formatter2 = [[NSDateFormatter alloc]init];
[formatter1 setDateFormat:#"hh:mm a"];
[formatter2 setDateFormat:#"EEE, dd MMM yyyy h:mm a z"];
NSDate *rise = [formatter1 dateFromString:sunrise];
NSDate *set = [formatter1 dateFromString:sunset];
NSDate *time = [formatter2 dateFromString:currTime];
[formatter1 release];
[formatter2 release];
unsigned int flags = NSHourCalendarUnit | NSMinuteCalendarUnit;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components1 = [calendar components:flags fromDate:rise];
NSDateComponents *components2 = [calendar components:flags fromDate:set];
NSDateComponents *components3 = [calendar components:flags fromDate:time];
NSDate *Sunrise = [calendar dateFromComponents:components1];
NSDate *Sunset = [calendar dateFromComponents:components2];
NSDate *Time = [calendar dateFromComponents:components3];
NSLog(#"\nSunrise: %# \nSunset:%# \nTime:%#",rise,set,time);
NSLog(#"\nSunrise: %# \nSunset:%# \nTime:%#",Sunrise,Sunset,Time);
Here's the first output:
Fri, 10 Jun 2011 4:00 am SAST - 7:46 am - 5:41 pm
And here's the second (before making it only concerned about the time, not date)
Sunrise: 1969-12-31 22:46:00 +0000
Sunset: 1970-01-01 08:41:00 +0000
Time: 2011-06-10 02:00:00 +0000
And finally here is the last output (notice how the times are messed up?):
Sunrise: 0001-12-31 22:27:01 +0000
Sunset: 0001-01-01 08:22:01 +0000
Time: 0001-01-01 01:41:01 +0000
So I wanted to pop those resulting dates into my method that checks whether it's in between the dates:
+(BOOL)date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate {
return (([date compare:beginDate] != NSOrderedAscending) && ([date compare:endDate] != NSOrderedDescending));
}
However, until I get the date problem figured out that method won't work. :/ I need help! What am I doing wrong?
Ok, so I gave up on trying to get NSDates to work for me. The timezone issues just killed my brain for the weekend. Anyway, I decided to use BoopMeister suggestion, but it doesn't work quite like I expect. Here's an example:
Using the setup from above, I added these lines:
NSInteger riseHour = [components1 hour];
NSInteger setHour = [components2 hour];
NSInteger timeHour = [components3 hour];
NSLog(#"Rise: %i Set: %i Time: %i",riseHour,setHour,timeHour);
Now, when I plug in these variables:
Current time: Fri, 10 Jun 2011 9:07 am CDT
Sunrise: 6:33 am
Sunset: 8:32 pm
However, when I output the strings from the methods above here's what I get:
Rise: 6 Set: 20 Time: 23
What the?
I would use the components you already have and not make new dates.
Starting at this point in your code:
NSDateComponents *riseComponents = [calendar components:flags fromDate:rise];
NSDateComponents *setComponents = [calendar components:flags fromDate:set];
NSDateComponents *timeComponents = [calendar components:flags fromDate:time];
And then something like
NSInteger riseHour = [riseComponents hour];
NSInteger setHour = [setComponents hour];
NSInteger timeHour = [timeComponents hour];
// Do some checks here
// If necessary do the same for the minutes ([components minute])
Comparing dates has been a performance issue in my app and since you already have the dateComponents it would be faster to make your own check and use the NSIntegers.
Okay, so as can be seen in the question, it gives the numerical presentation of the hours. Same works for the minutes. Build your checks after that.
What probably is the problem with the current time, is the calendar you use. It automatically converts the time to the time in the timezone of the calendar you use. You can also create a calendar with a string representation of the timezone. It's in the API of NSCalendar I think. Then after you made that calendar, then use that one for the current time.
One of the key things about NSDate is that it is in GMT. Always. However when you log it, it prints according to the user's locale.
Now when you do,
NSDateFormatter *formatter1 = [[NSDateFormatter alloc]init];
[formatter1 setDateFormat:#"hh:mm a"];
NSDate *rise = [formatter1 dateFromString:sunrise];
NSDate *set = [formatter1 dateFromString:sunset];
[formatter1 release];
You are just providing information about hour, minute and whether it is AM/PM. How is it to know which day the time belongs to. It fills this lack of information by defaulting to 01/01/1970 and timezone based on the user's locale. You do provide the timezone information in the current time which might or might not be the same as the user's locale.
To fix this, you must generate a string that includes the date and timezone info for the sunset time and pass it to the date formatter with the correct format to get the date. I am assuming you must've this (or how else will you know that it is the sunset or sunrise time for that day?). Since you know the place you should be able to get the timezone info as well. Once you've the correct information to build the dates with, every comparison method that you've used will work.

iPhone: How to get date and time from number of seconds?

I have time in seconds 1303093926 and I want to get date and time like
Sat, 09 Oct 2010 18:14:50 +0000
NSDate has a conversion method:
double seconds = 1303093926;
NSTimeInterval timeInterval = (NSTimeInterval)seconds;
NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
You can then use the NSDateFormatter class to convert the NSDate to a string in the format you want.
NSDate has several methods for creating date objects from second values. NSDate has four methods for doing exactly what you want:
+ (id)dateWithTimeInterval:(NSTimeInterval)seconds sinceDate:(NSDate *)date: If your number of seconds is based on some arbitrary date, you would use this method.
+ (id)dateWithTimeIntervalSince1970:seconds: If your number of seconds is based on the time since 1970, then you would use this method.
+ (id)dateWithTimeIntervalSinceNow:(NSTimeInterval)seconds: If the number of seconds is relative to the current time, use this. (Negative seconds are for dates prior to "now".)
+ (id)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)seconds: If you know that your number of seconds is relative to the predefined "reference date", (1 January 2001, GMT) then you should use this method.
Another approach, is to use NSDateComponents to build your date object. From the NSDateComponents documentation:
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:6];
[comps setMonth:5];
[comps setYear:2004];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:comps];
You can do the same with your number of seconds, using basic arithmetic to convert the seconds into years, months, days, hours, minutes and seconds.

NSDate best practice in creating a date with no time element

I am writing an app which uses core-data to store my data. Included in this is a date field of which I am only interested in the date not the time.
I need to select records based on the date (not time) and so I have created a category on NSDate to return a date, normalised to a set time as follows:
+ (NSDate *)dateWithNoTime:(NSDate *)dateTime {
if( dateTime == nil ) {
dateTime = [NSDate date];
}
NSDateComponents* comps = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:dateTime];
NSDate *dateOnly = [[NSCalendar currentCalendar] dateFromComponents:comps];
[dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)]; // Push to Middle of day.
return dateOnly;
}
I then use this when I add data to the core-data store (I have a setter which uses this method to set the primitive date value) and then I use this method to create a date that I use to compare the dates when performing a fetch request. So in theory this should always work - ie pick out the dates I'm looking for.
I'm slightly nervous though as I'm not totally sure what effect changing time-zone or locale will have. Will it still work ?
What is considered best practice when storing and searching on a date only when you aren't interested in the time.
Cheers.
EDIT
After reading the discussion recommended I think that I should modify my code to be as follows. The thinking being that if I ensure that I push it to a specific calendar system and a specific timezone (UTC) then the dates should always be the same regardless of where you are when you set the date and when you read the date. Any comments on this new code appreciated.
+ (NSDate *)dateWithNoTime:(NSDate *)dateTime {
if( dateTime == nil ) {
dateTime = [NSDate date];
}
NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
[calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
fromDate:dateTime];
NSDate *dateOnly = [calendar dateFromComponents:components];
[dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)]; // Push to Middle of day.
return dateOnly;
}
You have a few issues to deal with here. First, as you noted, timezones. You also need to worry about daylight savings, which change the concept of “midday.”
Take a look at this discussion on CocoaDev where an Apple Engineer gives some answers and discusses some best practices.
A simpler solution is to use a predicate that looks for dates within a certain range.
Use NSCalendarComponent to create a start date and an end date for you "day" and then include those in the predicate.
NSPredicate *p=[NSPredicate predicateWithFormat:#"$# <= date <= $#",startDate,endDate];
That will provide the maximum flexibility without to much complexity. Date and time programing is deceptively complex. Be prepared to do some work.
I also ended up in a scenario where I needed to have an NSDate to compare a date without taking into consideration time.
I hade a filter mechanisme and as part of the UI, if the user chose today the minimum date as start date and the end date as today, I would display "All time periods" as opposed to a string in the format:
1/5/2006 - 24/12/2009
So I needed to take todays date using +date of NSDate, and compare it to the end date. That end date came from a UIDatePicker set to without time, but +date returned the date and time of right now.
So I wrote this short handy method, it receives a date object, uses NSDateComponents and the NSCalendar class to extract the day, month and year.
These 3 parameters are then used to create a new NSDate using NSDateFormatter's -dateFromString: method, the result is an NSDate corresponding to the same "date" (in the traditional human concept) as the parameter date but without time.
- (NSDate *)strictDateFromDate:(NSDate *)date{
NSUInteger flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *components = [[NSCalendar currentCalendar] components:flags
fromDate:[NSDate date]];
NSString *stringDate = [NSString stringWithFormat:#"%d/%d/%d", components.day, components.month, components.year];
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
formatter.dateFormat = #"dd/MM/yyyy";
return [formatter dateFromString:stringDate];
}
I hope you can use and enjoy this function in future.

Determine if current local time is between two times (ignoring the date portion)

Considering that there is no NSTime in Cocoa-Touch (Objective-C on iPhone), and given two times as NSStrings and a timezone as an NSString, how can you calculate whether or not the current LOCAL time is between these two times. Keep in mind that the date in the time strings do NOT matter, and are filled with dummy dates.
For example:
TimeZone: Pacific Time (US & Canada)
Start Time: 2000-01-01T10:00:00Z
End Time: 2000-01-01T17:00:00Z
Local Time: now
How do you confirm whether or not local time is between the time range specified (ensuring to convert the start/end times to the proper timezone first)?
The biggest problem with this seems to come from the fact that the times may span two days (originally they might not, but when you do the timezone conversion, after that they might). So if we're to ignore the given date information completely, some assumptions have to be made with how to handle these date spans. Your question isn't exact on how to deal with this (i.e. I don't know exactly what you'd like to achieve) so here's just one way to go about it, which might not be exactly what you're after, but hopefully it will guide you in the right direction:
Parse the given strings to NSDate objects, ignoring the date information (result: times are handled such that they're assumed to be for the same day) and performing the time zone conversion
Get the time interval from the earlier NSDate to the later NSDate
Create NSDate objects for "today at the earlier given time" and "yesterday at the earlier given time"
Compare the time intervals from these two NSDates till the current date/time to the time interval between the two given date/times
Also note that time zone strings in the format you gave ("Pacific Time (US & Canada)") will not be understood by NSTimeZone so you'll need to do some conversion there.
Here's a code example (I wrote this on OS X since I don't have the iPhone SDK so hopefully all the used APIs will be available on iPhone as well):
- (BOOL)checkTimes
{
// won't work:
//NSString *tzs = #"Pacific Time (US & Canada)";
//
// will work (need to translate given timezone information
// to abbreviations accepted by NSTimeZone -- won't cover
// that here):
NSString *tzs = #"PST";
NSString *ds1 = #"2000-01-01T10:00:00Z";
NSString *ds2 = #"2000-01-01T17:00:00Z";
// remove dates from given strings (requirement was to ignore
// the dates completely)
ds1 = [ds1 substringFromIndex:11];
ds2 = [ds2 substringFromIndex:11];
// remove the UTC time zone designator from the end (don't know
// what it's doing there since the time zone is given as a
// separate field but I'll assume for the sake of this example
// that the time zone designator for the given dates will
// always be 'Z' and we'll always ignore it)
ds1 = [ds1 substringToIndex:8];
ds2 = [ds2 substringToIndex:8];
// parse given dates into NSDate objects
NSDateFormatter *df = [[[NSDateFormatter alloc] init] autorelease];
[df setDateFormat:#"HH:mm:ss"];
[df setTimeZone:[NSTimeZone timeZoneWithAbbreviation:tzs]];
NSDate *date1 = [df dateFromString:ds1];
NSDate *date2 = [df dateFromString:ds2];
// get time interval from earlier to later given date
NSDate *earlierDate = date1;
NSTimeInterval ti = [date2 timeIntervalSinceDate:date1];
if (ti < 0)
{
earlierDate = date2;
ti = [date1 timeIntervalSinceDate:date2];
}
// get current date/time
NSDate *now = [NSDate date];
// create an NSDate for today at the earlier given time
NSDateComponents *todayDateComps = [[NSCalendar currentCalendar]
components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
fromDate:now];
NSDateComponents *earlierTimeComps = [[NSCalendar currentCalendar]
components:NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit
fromDate:earlierDate];
NSDateComponents *todayEarlierTimeComps = [[[NSDateComponents alloc] init] autorelease];
[todayEarlierTimeComps setYear:[todayDateComps year]];
[todayEarlierTimeComps setMonth:[todayDateComps month]];
[todayEarlierTimeComps setDay:[todayDateComps day]];
[todayEarlierTimeComps setHour:[earlierTimeComps hour]];
[todayEarlierTimeComps setMinute:[earlierTimeComps minute]];
[todayEarlierTimeComps setSecond:[earlierTimeComps second]];
NSDate *todayEarlierTime = [[NSCalendar currentCalendar]
dateFromComponents:todayEarlierTimeComps];
// create an NSDate for yesterday at the earlier given time
NSDateComponents *minusOneDayComps = [[[NSDateComponents alloc] init] autorelease];
[minusOneDayComps setDay:-1];
NSDate *yesterday = [[NSCalendar currentCalendar]
dateByAddingComponents:minusOneDayComps
toDate:now
options:0];
NSDateComponents *yesterdayDateComps = [[NSCalendar currentCalendar]
components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
fromDate:yesterday];
NSDateComponents *yesterdayEarlierTimeComps = [[[NSDateComponents alloc] init] autorelease];
[yesterdayEarlierTimeComps setYear:[yesterdayDateComps year]];
[yesterdayEarlierTimeComps setMonth:[yesterdayDateComps month]];
[yesterdayEarlierTimeComps setDay:[yesterdayDateComps day]];
[yesterdayEarlierTimeComps setHour:[earlierTimeComps hour]];
[yesterdayEarlierTimeComps setMinute:[earlierTimeComps minute]];
[yesterdayEarlierTimeComps setSecond:[earlierTimeComps second]];
NSDate *yesterdayEarlierTime = [[NSCalendar currentCalendar]
dateFromComponents:yesterdayEarlierTimeComps];
// check time interval from [today at the earlier given time] to [now]
NSTimeInterval ti_todayEarlierTimeTillNow = [now timeIntervalSinceDate:todayEarlierTime];
if (0 <= ti_todayEarlierTimeTillNow && ti_todayEarlierTimeTillNow <= ti)
return YES;
// check time interval from [yesterday at the earlier given time] to [now]
NSTimeInterval ti_yesterdayEarlierTimeTillNow = [now timeIntervalSinceDate:yesterdayEarlierTime];
if (0 <= ti_yesterdayEarlierTimeTillNow && ti_yesterdayEarlierTimeTillNow <= ti)
return YES;
return NO;
}
You should be able to do what you are wanting to do with a combination of NSDate, and NSDateFormatter.
NSDateFormatter has a dateFromString: method which will let you convert your strings into NSDate objects, then you can use the compare: method of NSDate to compare the two against [NSDate date] which will have the current time.
(NSDate encompasses both date and time)
You should probably look at NSCalendar and NSDateComponents. I'm using them to do some date math for an iPhone app. I don't see a builtin method to do what you want directly, but you can figure it out by breaking it into pieces I expect?