iPhone: Find current date to 60 days in future - iphone

I am using the following code to find from current date+time to 30 days future. It works fine. But, i want now the end date should be 60 days, not 30 days. How can i change the below code to get upto 60 days? I tried changing end date to [currentDateComponents month]+1, but its not working. Any help please?
NSDate *date = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *currentDateComponents = [gregorian components:( NSWeekdayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSWeekCalendarUnit) fromDate:date];
NSLog(#"- current components year = %d , month = %d , week = % d, weekday = %d", [currentDateComponents year], [currentDateComponents month], [currentDateComponents week], [currentDateComponents weekday]);
NSArray* calendars = [[CalCalendarStore defaultCalendarStore] calendars];
NSLog(#"calendars.count: %ld", [calendars count]);
debug(#"LogMsg:%# Date:%#", #"Start looking for new events for pushing iCal to OfferSlot", [NSDate date]);
// 30 days any new or modified calendar (iCal) events will be pushed here to OfferSlot
NSInteger year = [[NSCalendarDate date]yearOfCommonEra];
NSDate *startdate = [NSCalendarDate dateWithYear:year month:[currentDateComponents month] day:1 hour:0 minute:0 second:0 timeZone:nil];
NSDate *enddate = [NSCalendarDate dateWithYear:year month:[currentDateComponents month] day:31 hour:23 minute:59 second:59 timeZone:nil];

Your code does not always do what you describe in the text. It creates two dates, one at the beginning of the current month, one at the end of the month (if the month has 31 days, if it has less than 31 days your endDate will be in the next month). If you run the code on the 1st of each month it will create a NSDate that is 30 days in the future, but only on the 1st of each month.
if you really want to get the NSDate that is 60 days from now use this code:
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *sixtyDaysOffset = [[NSDateComponents alloc] init];
sixtyDaysOffset.day = 60;
NSDate *sixtyDaysFromNow = [calendar dateByAddingComponents:sixtyDaysOffset toDate:[NSDate date] options:0];

Related

Find difference between two dates is exactly 1 year

This is my code and it perfectly returns number of days and months between two dates. i want to validate this like the difference between two dates should be exactly one year.like if u select july 29 2013 as start date and july 30 2014 as end date it should not be allowed to execute more.please help thanks in advance.
NSString *sta = txtStartdate.text; // This is the start date
NSString *en = txtEnddate.text; //this is end date
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:#"dd/MM/yyyy"];
NSDate *startDat = [f dateFromString:sta];
NSDate *endDat = [f dateFromString:en];
[f release];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit | NSYearCalendarUnit ;
NSDateComponents *components = [gregorian components:unitFlags
fromDate:startDat
toDate:endDat options:0];
NSInteger months = [components month];
NSInteger days = [components day];
NSInteger years = [components year];
NSLog(#"Number of months %d",months);
NSLog(#"Number of days %d",days);
NSLog(#"Number of years %d",years);
[gregorian release];
if(years < 1 )// This code works fine...i've edited it.. #wain helped
{
//
}
Add NSYearCalendarUnit to unitFlags, then when you have obtained the components you can request the year. This will deal with leap years better than you trying to count months and days or calculate the end date (unless you use the components to add a single year to the date to get the end date).

Get the first day and last day of a week

I am using this method to get the current week first and last days:
NSDate *weekDate = [NSDate date];
NSCalendar *myCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *currentComps = [myCalendar components:( NSYearCalendarUnit | NSMonthCalendarUnit | NSWeekOfYearCalendarUnit | NSWeekdayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:weekDate];
int ff = currentComps.weekOfYear;
NSLog(#"1 %d", ff);
[currentComps setWeekday:1]; // 1: sunday
NSDate *firstDayOfTheWeek = [myCalendar dateFromComponents:currentComps];
[currentComps setWeekday:7]; // 7: saturday
NSDate *lastDayOfTheWeek = [myCalendar dateFromComponents:currentComps];
NSDateFormatter *myDateFormatter = [[NSDateFormatter alloc] init];
myDateFormatter.dateFormat = #"dd/MM/yyyy";
NSString *firstStr = [myDateFormatter stringFromDate:firstDayOfTheWeek];
NSString *secondStr = [myDateFormatter stringFromDate:lastDayOfTheWeek];
NSLog(#"first - %# \nlast - %#", firstStr, secondStr);
And i want to know what i should change in this to get the next week first and last day and two weeks from now to?
To get the next week, add 7 days to firstDayOfTheWeek and then lastDayOfTheWeek.
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:7];
NSDate *firstDayOfNextWeek = [myCalendar dateByAddingComponents:comps toDate:firstDayOfTheWeek options:0];
This code assumes a 7-day week. Ideally you would replace this assumption with code that gets the actual length of the week.
Side Note: Your code assume the week starts on Sunday. Many locales start their week on others days such as Monday. Change:
[currentComps setWeekday:1];
to:
[currentComps setWeekday:[myCalendar firstWeekday]];
I would then change your calculation of lastDayOfTheWeek to simply add 6 days to firstDayOfWeek.
Use Below code which returns index of current current weekly days. For example if its today is saturday than it will give you 7 means last day of week.
-(int)currentdayweeklynumber{
NSDate *CurrentDate = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd"];// you can use your format.
//Week Start Date
NSCalendar *gregorian = [[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorian components:NSWeekdayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:CurrentDate];
int dayofweek = [[[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:CurrentDate] weekday];
NSLog(#" dayofweek=%d",dayofweek);
return dayofweek;
}
Using this number you add or subtract to get first or last of week. You can also use this get next week start and end date by just simple calculation.

How can we get Next Date From Entered Date based on given repeate period ?

I am new to iPhone.
I want to find out the next date from given date based on repeat period.
For example :
I want function as follows ...
given date : 31'May 2011 and Repeat : Monthly given as argument then the next date should be returned 31'July 2011 (as June don't have 31st day)
And function should be smart enough to to calculate next leap year day also, if given date : 29'Feb 2008 and Repeat : Yearly given as argument then the next date should be returned 29'Feb 2012 (The next leap year day)
And so on repeat option can be one of these : Daily, Weekly(On selected day of week), Monthly, Yearly, None(No repeat at all)
// start by retrieving day, weekday, month and year components for yourDate
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *todayComponents = [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) yourDate];
NSInteger theDay = [todayComponents day];
NSInteger theMonth = [todayComponents month];
NSInteger theYear = [todayComponents year];
// now build a NSDate object for yourDate using these components
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:theDay];
[components setMonth:theMonth];
[components setYear:theYear];
NSDate *thisDate = [gregorian dateFromComponents:components];
[components release];
// now build a NSDate object for the next day
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setDay:1];
NSDate *nextDate = [gregorian dateByAddingComponents:offsetComponents toDate: yourDate options:0];
[offsetComponents release];
[gregorian release];
This is copied from How can i get next date using NSDate? and the credit goes to #Massimo Cafaro for this answer.
To get tomorrow's date use the dateByAddingTimeInterval method.
// Start with today
NSDate *today = [NSDate date];
// Add on the number of seconds in a day
NSTimeInterval oneDay = 60 * 60 * 24;
NSDate *tomorrow = [today dateByAddingTimeInterval:oneDay];
It's pretty simple to extend that to a week etc
NSTimeInterval oneWeek = oneDay * 7;
NSDate *nextWeek = [today dateByAddingTimeInterval:oneWeek];
try this :-
- (NSDate *)dateFromDaysOffset:(NSInteger)daysOffset
{
// start by retrieving day, weekday, month and year components for yourDate
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setDay:daysOffset];
NSDate *offsetDate = [gregorian dateByAddingComponents:offsetComponents toDate:self options:0];
[offsetComponents release];
[gregorian release];
return offsetDate;
}

iPhone SDK, how to get NSDate object of coming friday's 20:00?

Does anyone know how to get the NSDate of the coming friday's 20:00 ?
Yes, this article teaches you how to get the current week's Sunday.
I quickly adapted it to get friday at 20:00 (Assuming a Gregorian calendar)
NSDate *today = [[NSDate alloc] init];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
// Get the weekday component of the current date
NSDateComponents *weekdayComponents = [gregorian components:NSWeekdayCalendarUnit fromDate:today];
/*
Create a date components to represent the number of days to add to the current date.
The weekday value for Friday in the Gregorian calendar is 6, so add the difference between 6 and today to get the number of days to add.
Actually, on Saturday that will give you -1, so you want to subtract from 13 then take modulo 7
*/
NSDateComponents *componentsToAdd = [[NSDateComponents alloc] init];
[componentsToAdd setDay: (13 - [weekdayComponents weekday]) % 7];
NSDate *friday = [gregorian dateByAddingComponents:componentsToAdd toDate:today options:0];
/*
friday now has the same hour, minute, and second as the original date (today).
To normalize to midnight, extract the year, month, and day components and create a new date from those components.
*/
NSDateComponents *components =
[gregorian components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
fromDate: friday];
// And to set the time to 20:00
[components setHour:22];
friday = [gregorian dateFromComponents:components];

iPhone - get number of days between two dates

I'm writing a GTD app for the iPhone. For the due tasks, I want to display something like "Due tomorrow" or "Due yesterday" or "Due July 18th". Obviously, I need to display "Tomorrow" even if the task is less than 24 hours away (e.g. the user checks at 11pm on Saturday and sees there's a task on Sunday at 8am). So, I wrote a method to get the number of days in between two dates. Here's the code...
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd-HH-mm"];
NSDate *nowDate = [dateFormatter dateFromString:#"2010-01-01-15-00"];
NSDate *dueDate = [dateFormatter dateFromString:#"2010-01-02-14-00"];
NSLog(#"NSDate *nowDate = %#", nowDate);
NSLog(#"NSDate *dueDate = %#", dueDate);
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *differenceComponents = [calendar components:(NSDayCalendarUnit)
fromDate:nowDate
toDate:dueDate
options:0];
NSLog(#"Days between dates: %d", [differenceComponents day]);
... and here's the output:
NSDate *nowDate = 2010-01-01 15:00:00 -0700
NSDate *dueDate = 2010-01-02 14:00:00 -0700
Days between dates: 0
As you can see, the method returns incorrect results. It should have returned 1 as the number of days between the two days. What am I doing wrong here?
EDIT: I wrote another method. I haven't done extensive unit tests, but so far it seems to work:
+ (NSInteger)daysFromDate:(NSDate *)fromDate inTimeZone:(NSTimeZone *)fromTimeZone untilDate:(NSDate *)toDate inTimeZone:(NSTimeZone *)toTimeZone {
NSCalendar *calendar = [NSCalendar currentCalendar];
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
[calendar setTimeZone:fromTimeZone];
NSDateComponents *fromDateComponents = [calendar components:unitFlags fromDate:fromDate];
[calendar setTimeZone:toTimeZone];
NSDateComponents *toDateComponents = [calendar components:unitFlags fromDate:toDate];
[calendar setTimeZone:[NSTimeZone defaultTimeZone]];
NSDate *adjustedFromDate = [calendar dateFromComponents:fromDateComponents];
NSDate *adjustedToDate = [calendar dateFromComponents:toDateComponents];
NSTimeInterval timeIntervalBetweenDates = [adjustedToDate timeIntervalSinceDate:adjustedFromDate];
NSInteger daysBetweenDates = (NSInteger)(timeIntervalBetweenDates / (60.0 * 60.0 * 24.0));
NSDateComponents *midnightBeforeFromDateComponents = [[NSDateComponents alloc] init];
[midnightBeforeFromDateComponents setYear:[fromDateComponents year]];
[midnightBeforeFromDateComponents setMonth:[fromDateComponents month]];
[midnightBeforeFromDateComponents setDay:[fromDateComponents day]];
NSDate *midnightBeforeFromDate = [calendar dateFromComponents:midnightBeforeFromDateComponents];
[midnightBeforeFromDateComponents release];
NSDate *midnightAfterFromDate = [[NSDate alloc] initWithTimeInterval:(60.0 * 60.0 * 24.0)
sinceDate:midnightBeforeFromDate];
NSTimeInterval timeIntervalBetweenToDateAndMidnightBeforeFromDate = [adjustedToDate timeIntervalSinceDate:midnightBeforeFromDate];
NSTimeInterval timeIntervalBetweenToDateAndMidnightAfterFromDate = [adjustedToDate timeIntervalSinceDate:midnightAfterFromDate];
if (timeIntervalBetweenToDateAndMidnightBeforeFromDate < 0.0) {
// toDate is before the midnight before fromDate
timeIntervalBetweenToDateAndMidnightBeforeFromDate -= daysBetweenDates * 60.0 * 60.0 * 24.0;
if (timeIntervalBetweenToDateAndMidnightBeforeFromDate < 0.0)
daysBetweenDates -= 1;
}
else if (timeIntervalBetweenToDateAndMidnightAfterFromDate >= 0.0) {
// toDate is after the midnight after fromDate
timeIntervalBetweenToDateAndMidnightAfterFromDate -= daysBetweenDates * 60.0 * 60.0 * 24.0;
if (timeIntervalBetweenToDateAndMidnightAfterFromDate >= 0.0)
daysBetweenDates += 1;
}
[midnightAfterFromDate release];
return daysBetweenDates;
}
From the docs for components:fromDate:toDate:options::
The result is lossy if there is not a small enough unit requested to hold the full precision of the difference.
Since the difference is less than a full day, it correctly returns a result of 0 days.
If all you care about is tomorrow or yesterday vs. a specific date, then you can save yourself a lot of work and just test whether the dates are only one calendar day apart.
To do that, compare the dates to find which is earlier and which is later (and if they compare equal, bail out with that result), then test whether 1 day after the earlier date produces a date with the same year, month, and day-of-month as the later date.
If you really do want to know exactly how many calendar days there are from one date to the other:
Send the calendar a components:fromDate: message to get the year, month, and day-of-the-month of the first date.
Same as #1, but for the second date.
If the two dates are in the same year and month, subtract one day-of-month from the other and pass to abs (see abs(3)) to take the absolute value.
If they are not in the same year and month, test whether they are in adjacent months (e.g., December 2010 to January 2011, or June 2010 to July 2010). If they are, add the number of days in the earlier date's month (which you can obtain by sending the calendar a rangeOfUnit:inUnit:forDate: message, passing NSDayCalendarUnit and NSMonthCalendarUnit, respectively) to the day-of-month of the later date, then compare that result to the earlier date's day-of-month.
For example, when comparing 2010-12-31 to 2011-01-01, you would first determine that these are in adjacent months, then add 31 (number of days in 2010-12) to 1 (day-of-month of 2011-01-01), then subtract 31 (day-of-month of 2010-12-31) from that sum. Since the difference is 1, the earlier date is one day before the later date.
When comparing 2010-12-30 to 2011-01-02, you would determine that they are in adjacent months, then add 31 (days in 2010-12) to 2 (day-of-month of 2011-01-02), then subtract 30 (day-of-month of 2010-12-30) from that sum. 33 minus 30 is 3, so these dates are three calendar days apart.
Either way, I strongly suggest writing unit tests at least for this code. I've found that date-handling code is among the most likely to have subtle bugs that only manifest, say, twice a year.
One thing you might try is using rangeOfUnit: to zero out hours, minutes and seconds from the start and end dates.
NSCalendar *calendar = [NSCalendar currentCalendar];
NSCalendarUnit range = NSDayCalendarUnit;
NSDateComponents *comps = [[NSDateComponents alloc] init];
NSDate *start = [NSDate date];
NSDate *end;
[comps setDay:1];
[calendar rangeOfUnit:range startDate:&start interval:nil forDate:start];
end = [calendar dateByAddingComponents:comps toDate:start options:0];
In this example start will be 2010-06-19 00:00:00 -0400, end will be 2010-06-20 00:00:00 -0400. I'd imagine this would work better with NSCalendar's comparison methods, although I haven't tested it myself.
I am using this piece of code, it is working very well:
- (NSInteger)daysToDate:(NSDate*)date
{
if(date == nil) {
return NSNotFound;
}
NSUInteger otherDay = [[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitEra forDate:date];
NSUInteger currentDay = [[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitEra forDate:self];
return (otherDay-currentDay);
}
Here is the function I've used in the past
its defined in a category on NSDate
- (int) daysToDate:(NSDate*) endDate
{
//dates needed to be reset to represent only yyyy-mm-dd to get correct number of days between two days.
NSDateFormatter *temp = [[NSDateFormatter alloc] init];
[temp setDateFormat:#"yyyy-MM-dd"];
NSDate *stDt = [temp dateFromString:[temp stringFromDate:self]];
NSDate *endDt = [temp dateFromString:[temp stringFromDate:endDate]];
[temp release];
unsigned int unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit;
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [gregorian components:unitFlags fromDate:stDt toDate:endDt options:0];
int days = [comps day];
[gregorian release];
return days;
}
-(NSInteger)daysBetweenTwoDates:(NSDate*)fromDateTime andDate:(NSDate*)toDateTime
{
NSDate *fromDate;
NSDate *toDate;
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&fromDate
interval:NULL forDate:fromDateTime];
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&toDate
interval:NULL forDate:toDateTime];
NSDateComponents *difference = [calendar components:NSDayCalendarUnit
fromDate:fromDate toDate:toDate options:0];
return [difference day];
}