This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I calculate the difference between two dates?
NSDate, comparing two dates
I have got two dates. How to check if theres a difference of 30 days in between them?
I actually have an In-App purchase which needs to be disabled after every 30-days of purchase.
When the user buys the feature, the Date is saved and so I need to check the dates. If 30-days have passed, I need to disable the feature again.
You can convert both dates to seconds with timeIntervalSince1970 and then check if difference is bigger than 2592000 (30*24*60*60 which is 30 days * 24 hours * 60 minutes * 60 seconds).
NSTimeInterval difference = [date1 timeIntervalSince1970] - [date2 timeIntervalSince1970];
if(difference >2592000)
{
//do your stuff here
}
EDIT:
For more compact version you can use - (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate
NSTimeInterval difference = [date1 timeIntervalSinceDate:date2];
if(difference >2592000)
{
//do your stuff here
}
Provide the start and end NSDate in following manner:
NSDate *date_Start;
NSDate *date_End;
NSCalendar *cal=[NSCalendar currentCalendar];
NSDateComponents *components=[cal components:NSDayCalendarUnit fromDate:date_Start toDate:date_End options:0];
int days=[components day];
if(days>30){
//Your code here
}
You could create a date which is +30days from now :
NSDate *thrityDaysPlus = [[NSDate date] dateByAddingTimeInterval:3600*24*30]
and then simply compare it to your saved date
if ([date1 compare:date2] == NSOrderedDescending) {
NSLog(#"date1 is later than date2");
} else if ([date1 compare:date2] == NSOrderedAscending) {
NSLog(#"date1 is earlier than date2");
} else {
NSLog(#"dates are the same");
}
Related
I've done this hundreds of times with PHP, but now I'm learning xcode and I can't figure it out. I'm trying to display a Unix Timestamp on a tableView cell like this -> "10 minutes 24 seconds ago", "4 hours, 2 minutes ago" or "2 days 4 hours ago". Any ideas?
I ran into the same thing, heres what I came up with for unix timestamps:
-(NSString *)timeSinceNow:(float)timestamp{
NSMutableString *time = [[NSMutableString alloc]init];
NSTimeInterval ti = [[NSDate date] timeIntervalSince1970];
float diff = ti - timestamp;
//days
if (diff<60*60*24*365) {
[time appendString:[NSString stringWithFormat:#"%d day", (int)floor(diff/(60*60*24))]];
}
//hours
if (diff<60*60*24) {
[time appendString:[NSString stringWithFormat:#"%d hour", (int)floor(diff/(60*60))]];
}
//minutes
if (diff<60*60) {
[time appendString:[NSString stringWithFormat:#"%d minute", (int)floor(diff/(60))]];
}
//seconds
if (diff<60) {
[time appendString:[NSString stringWithFormat:#"%d second", (int)floor(diff)]];
}
//years
if (diff>=60*60*24*365) {
[time appendString:[NSString stringWithFormat:#"%d year", (int)floor(diff/(60*60*24*365))]];
}
//check if its not singular (plural) - add 's' if so
if (![[time substringToIndex:2] isEqualToString:#"1 "]) {
[time appendString:#"s"];
}
return time;
}
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/Reference/Reference.html#//apple_ref/occ/instm/NSDateFormatter/setDoesRelativeDateFormatting:
this one has a simple example.
NSDate *now = [NSDate date];
should do build the difference to something and and then bind it to the cell
Try this third party library: https://github.com/billgarrison/SORelativeDateTransformer
You can install it via CocoaPods, or using the instructions in the README.
If you'd like to roll your own solution, you can get the number of seconds since the current time by using +[NSDate dateWithTimeIntervalSinceReferenceDate:], passing in a reference date of the current time, +[NSDate date]. By dividing the result using the appropriate units, you should be able to get the level of granularity you desire.
SORelativeDateTransformer takes that a step further, by allowing for localization with some clever use of -[NSBundle localizedStringForKey:value:table:].
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Determine if current local time is between two times (ignoring the date portion)
In iOS, how can I do the following:
I have two NSDate objects that represent the opening and closing times for a store. The times within these objects are accurate but the date is unspecified (the store opens and closes at the same time regardless of the date). How can I check if the current time falls between in this time frame?
Note, if it would help for the opening and closing times to be in another format other than NSDate objects, I'm fine with that. Currently, I'm just reading in a date string such as "12:30" from a file and using date formatter to create a matching NSDate object.
Update: Note that this solution is specific to your case and assumes that store opening hours don't span two days. For example it won't work if the opening hour goes from Monday 9pm to Tuesday 10am. Since 10pm is after 9pm but not before 10am (within a day). So keep that in mind.
I cooked up a function which will tell you if the time of one date is between two other dates (it ignores the year, month and day). There's also a second helper function which gives you a new NSDate with the year, month and day components "neutralized" (eg. set to some static value).
The idea is to set the year, month and day components to be the same between all dates so that the comparison will only rely on the time.
I'm not sure if it's the most efficient approach, but it works.
- (NSDate *)dateByNeutralizingDateComponentsOfDate:(NSDate *)originalDate {
NSCalendar *gregorian = [[[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
// Get the components for this date
NSDateComponents *components = [gregorian components: (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate: originalDate];
// Set the year, month and day to some values (the values are arbitrary)
[components setYear:2000];
[components setMonth:1];
[components setDay:1];
return [gregorian dateFromComponents:components];
}
- (BOOL)isTimeOfDate:(NSDate *)targetDate betweenStartDate:(NSDate *)startDate andEndDate:(NSDate *)endDate {
if (!targetDate || !startDate || !endDate) {
return NO;
}
// Make sure all the dates have the same date component.
NSDate *newStartDate = [self dateByNeutralizingDateComponentsOfDate:startDate];
NSDate *newEndDate = [self dateByNeutralizingDateComponentsOfDate:endDate];
NSDate *newTargetDate = [self dateByNeutralizingDateComponentsOfDate:targetDate];
// Compare the target with the start and end dates
NSComparisonResult compareTargetToStart = [newTargetDate compare:newStartDate];
NSComparisonResult compareTargetToEnd = [newTargetDate compare:newEndDate];
return (compareTargetToStart == NSOrderedDescending && compareTargetToEnd == NSOrderedAscending);
}
I used this code to test it. You can see that the year, month and days are set to some random values and don't affect the time checking.
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"yyyy:MM:dd HH:mm:ss"];
NSDate *openingDate = [dateFormatter dateFromString:#"2012:03:12 12:30:12"];
NSDate *closingDate = [dateFormatter dateFromString:#"1983:11:01 17:12:00"];
NSDate *targetDate = [dateFormatter dateFromString:#"2034:09:24 14:15:54"];
if ([self isTimeOfDate:targetDate betweenStartDate:openingDate andEndDate:closingDate]) {
NSLog(#"TARGET IS INSIDE!");
}else {
NSLog(#"TARGET IS NOT INSIDE!");
}
I am working on an iphone app for class and my group is having some time trouble.
The idea we are working with is that we have a scheduled event (say 2:00pm) and we want to know if we are within a certain amount of time from the scheduled time (say +/- 15 minutes). So for this example if the event was at 2pm, if this event was called from 1:45-2:15pm the method would return true/yes, and otherwise, it would return false/no.
I know how to current time/date, but how do I do the part with checking to see if it is within a certain range of time from the event time?
?
So what I am going for would be a method similar to the following with currentTime getting a NSDate object for the current time and classStartTime getting a NSDate object for the start time of the class:
- (BOOL)dateInRange:(NSDate*)currentTime inRangeOf:(NSDate*)classStartTime
{
if([currentTime <= [classStartTime dateByAddingTimeInterval:60*15]] && [currentTime >= [classStartTime dateByAddingTimeInterval:-(60*15)]])
{
return TRUE;
}
else{
return FALSE;
}
}
I know this doesn't work. How do I get the comparison part of the if statement to work properly
I guess, your time is a NSDate. You could use TimeIntervalSinceDate: with the start time of your interval and check if the result is positive and smaller than your interval length.
Use NSDate and NSDateComponents. I don't have a Mac nearby, so the following code will probably have errors in it.
NSCalendar *gregorian = [[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar];
int comp = NSHourCalendarUnit | NSMinuteCalendarUnit;
NSDateComponents *theDateComponents = [gregorian components:comp fromDate:[NSDate date]];
int hour = [theDateComponents hour];
int minute = [theDateComponents minute];
if ((hour == 13 && minute >= 45) || (hour == 14 && minute <= 15)) {
//do your stuff
}
Hope it helps
Find a start date and and end date with
+ (id)dateWithTimeInterval:(NSTimeInterval)seconds sinceDate:(NSDate *)date
then use the compare method to check that the date you are checking falls within your dates...
I must be missing something small her but can't figure it out. Trying to create a date for comparison, but I can't seem to offset currentDate from GMT to EST:
// current date (gmt) //
NSDate *currentDate = [NSDate date];
NSTimeZone *currentDateTimeZone = [NSTimeZone timeZoneWithAbbreviation:#"EST"];
NSDateFormatter *currentDateFormat = [[NSDateFormatter alloc]init];
[currentDateFormat setTimeZone:currentDateTimeZone];
[currentDateFormat setDateFormat:#"yyyy-MM-dd HH:mm:ss zzz"];
NSString *currentDateString = [currentDateFormat stringFromDate:currentDate];
NSLog(#"currentDateString: %#", currentDateString); // returns 2011-01-05 13:30:30 EST
NSDate *currentDateWithOffset = [currentDateFormat dateFromString:currentDateString];
NSLog(#"currentDateWithOffset: %#", currentDateWithOffset); // returns 2011-01-05 18:30:30 +0000
Thanks!
Edit:
I'm calling a method in a separate class (trying to make this portable) using the following line:
[Expiration expires:[[NSDate alloc] initWithString:#"2011-01-07 12:00:00 +0000"] within:1.0]
in the expires method, I have these lines:
NSComparisonResult comparison = [currentDateWithOffset compare:expires]; // check for a fixed date to disable the demo
double withinRange = [installDate timeIntervalSinceDate:currentDateWithOffset]; // check for number of seconds between "within" and the install date
I'm then comparing these two values like so:
if(withinRange >= within && withinRange > 0.0) {
// app is expired //
}
else {
// app is still enabled (so far...) //
if(comparison == NSOrderedDescending || comparison == NSOrderedSame) {
// app is expired //
}
else {
// app is still enabled //
}
}
Does this help? Thanks for your patience!
Edit:
Here's the entire expires:within method as it currently stands...
+(BOOL)expire:(NSDate*)expires within:(double)within {
// default expired value //
BOOL expired = NO;
// convert within value from days to seconds //
within *= 24.0 * 60.0 * 60.0;
// current date (gmt) //
NSDate *currentDate = [NSDate date];
// install date //
NSDate *installDate = [[NSUserDefaults standardUserDefaults]objectForKey:#"installDate"];
// check for a value in installDate //
if (nil == installDate) {
// app is running for the first time //
[[NSUserDefaults standardUserDefaults]setObject:currentDate forKey:#"installDate"];
[[NSUserDefaults standardUserDefaults]synchronize];
installDate = currentDate;
}
if([installDate timeIntervalSinceNow] < (-within)) {
expired = YES;
}
else {
if([expires timeIntervalSinceNow] < 0) {
expired = YES;
}
}
NSLog(#"installDate:%#", installDate);
NSLog(#"expires:%#", expires);
NSLog(#"currentDate:%#", currentDate);
return expired;
}
I'm then calling it from another class with
message.text = (YES == [Expiration expire:[[NSDate alloc] initWithString:#"2011-01-07 12:00:00 -0500"] within:(0.015625/2)]) ? #"This App is Expired" : #"This App is Active";
When running in the simulator (fresh app install), NSLog displayed this...
[Session started at 2011-01-06 10:43:46 -0500.]
2011-01-06 10:43:48.146 TimeBasedDemo[14717:207] installDate:2011-01-06 15:43:48 +0000
2011-01-06 10:43:48.147 TimeBasedDemo[14717:207] expires:2011-01-07 17:00:00 +0000
2011-01-06 10:43:48.147 TimeBasedDemo[14717:207] currentDate:2011-01-06 15:43:48 +0000
None of these answers gave me an NSDate object with the current, local date. So here's how I did it:
NSDate *currentDateWithOffset = [NSDate dateWithTimeIntervalSinceNow:[[NSTimeZone localTimeZone] secondsFromGMT]];
An NSDate object represents an instant in time irrespective of time zone and calendar considerations. Time zone info is relevant when you print or parse a date, but it is not stored within the NSDate.
Say you are creating your expiration date like this:
NSDate *exp=[[NSDate alloc] initWithString:#"2011-01-07 12:00:00 +0000"]
That says you want the expiration to occur at noon GMT, on the 7th Jan. If you want it to expire at noon EST, create it with -0500 instead. What you should not have to do is mess with the current time when you do a comparison.
An easy way just to see if the time has passed is then
if ([exp timeIntervalSinceNow]<0) { /* it's expired */ }
and you can see if within seconds have passed since the install date like this:
if ([installDate timeIntervalSinceNow]<(-within)]) { /* it's expired */}
In Cocoa, NSDate is an abstract representation of a date with no time zone information applied. Note that currentDateWithOffset is the same date as the date string, just in a different time zone (five hours ahead). This is expected behavior, as NSDate does not persist the time zone used to create it.
I tinkered around a bit more and found a way to 'cheat' the offset to suit my needs. From other reading, I'm guessing that NSCalendar might be a better long term-solution, but for now I ended up changing
NSDate *currentDateWithOffset = [currentDateFormat dateFromString:currentDateString];
to
NSDate *currentDateWithOffset = [[NSDate alloc] initWithString:[NSString stringWithFormat:#"%# +0000", currentDateString]];
That got me the results I needed and works in the later comparisons I'm using. Thanks for the background info all!
I have two dates in format(MM/dd/yyyy hh:mm:ss:SS). For the both dates I have converted the two dates to strings by using (stringFromDate) method. But I could not get the difference between them and show them in my console. Please give me an idea how I should get it?
Thank you.
Example
NSDate *today = [NSDate date];
NSTimeInterval dateTime;
if ([visitDate isEqualToDate:today]) //visitDate is a NSDate
{
NSLog (#"Dates are equal");
}
dateTime = ([visitDate timeIntervalSinceDate:today] / 86400);
if(dateTime < 0) //Check if visit date is a past date, dateTime returns - val
{
NSLog (#"Past Date");
}
else
{
NSLog (#"Future Date");
}
Keep the dates as dates, get the difference between them, then print the difference.
From the docs on NSCalendar and assuming gregorian is an NSCalendar:
NSDate *startDate = ...;
NSDate *endDate = ...;
unsigned int unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *comps = [gregorian components:unitFlags fromDate:startDate toDate:endDate options:0];
int months = [comps month];
int days = [comps day];
Generally I see day delta calculations handled by converting day/year values into flat days (usually days since some starting epoch, like 01/01/1970).
To aid in this, I've found it helpful to create a table of days into the year that each month starts. Here's a class I used for this recently.
namespace {
// Helper class for figuring out things like day of year
class month_database {
public:
month_database () {
days_into_year[0] = 0;
for (int i=0; i<11; i++) {
days_into_year[i+1] = days_into_year[i] + days_in_month[i];
}
};
// Return the start day of the year for the given month (January = month 1).
int start_day (int month, int year) const {
// Account for leap years. Actually, this doesn't get the year 1900 or 2100 right,
// but should be good enough for a while.
if ( (year % 4) == 0 && month > 2) {
return days_into_year[month-1] + 1;
} else {
return days_into_year[month-1];
}
}
private:
static int const days_in_month[12];
// # of days into the year the previous month ends
int days_into_year[12];
};
// 30 days has September, April, June, and November...
int const month_database::days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
month_database month;
}
As you can see from the start_day method, the main issue you are going to be wrestling with is how many leap days are contained in your range. Within our epoch the calculation I used there is good enough. The actual rule for which years contain leap days is discussed here.
February 29 in the Gregorian calendar,
the most widely used today, is a date
that occurs only once every four
years, in years evenly divisible by 4,
such as 1976, 1996, 2000, 2004, 2008,
2012 or 2016 (with the exception of
century years not divisible by 400,
such as 1900).
If you just want the difference in days, you can do this. (Based on mihir mehta's answer.)
const NSTimeInterval kSecondsPerDay = 60 * 60 * 24;
- (NSInteger)daysUntilDate:(NSDate *)anotherDate {
NSTimeInterval secondsUntilExpired = [self timeIntervalSinceDate:anotherDate];
NSTimeInterval days = secondsUntilExpired / kSecondsPerDay;
return (NSInteger)days;
}