ios - get in between dates (in actual date, not number of days) - ios

I have two date string and I wanted to get the in between dates.
For example,
NSString *startDate = #"25-01-2014";
NSString *endDate = #"02-02-2014";
In between dates will be (26-01-2014, 27-01-2014, 28-01-2014.......)
preferably include startDate and endDate as well. Most of the question I managed to find asked for number of days. But I needed it to be actual date. Is there anyway that I can get the in between dates?
NSString *start = #"2010-09-01";
NSString *end = #"2010-12-05";
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:#"yyyy-MM-dd"];
NSDate *startDate = [f dateFromString:start];
NSDate *endDate = [f dateFromString:end];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorianCalendar components:NSDayCalendarUnit
fromDate:startDate
toDate:endDate
options:0];
NSLog(#"Difference in date components: %d", components.day);
I managed to find this which only returns number of days difference.

NSString *start = #"2010-09-01";
NSString *end = #"2010-12-05";
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:#"yyyy-MM-dd"];
NSDate *startDate = [f dateFromString:start];
NSDate *endDate = [f dateFromString:end];
NSMutableArray *dates = [#[startDate] mutableCopy];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorianCalendar components:NSDayCalendarUnit
fromDate:startDate
toDate:endDate
options:0];
for (int i = 1; i < components.day; ++i) {
NSDateComponents *newComponents = [NSDateComponents new];
newComponents.day = i;
NSDate *date = [gregorianCalendar dateByAddingComponents:newComponents
toDate:startDate
options:0];
[dates addObject:date];
}
[dates addObject:endDate];
The array dates now contains the list of dates between startDate and endDate, including those, for midnight in the timezone of the device.
Note, that on some timezones this might cause trouble, as the switch from and to Daylight Saving Time might occur at that moment, see WWDC 2011 Video "Session 117 - Performing Calendar Calculations" for further information. One trick is to shift the hour to a save time, i.e. noon, do the calculation and than subtract 12 hours.

Ok, you're most of the way there. You have a date formatter that converts the date strings to NSDates. You have the number of days between the dates. Now you need to loop from the start date for that many days, adding a variable number of days to the start date.
The method you need is dateByAddingComponents:toDate:options:.
Something like this (goes immediately after your code) :
int days = components.day;
NSDateComponents *daysToAdd = [[NSDateComponents alloc] init];
for (int count = 0; count <= days; count++)
{
daysToAdd.day = count;
NSDate *loopDate = [gregorianCalendar dateByAddingComponents: daysToAdd
toDate: startDate
options: 0 ];
NSLog(#"Day %d = %#", count+1, [f stringFromDate: loopDate]);
}
I haven't tested it, but that's the basic idea...
The code above should include both the start and end dates.
If you don't want to include the start date, make the loop start at count = 1 instead of count = 0.
If you don't want to include the end date, make the loop check count < days.

A little late but found a fix to the 'TIMEZONE' time issue that vikingosegundo talked about in his answer. I simply converted the NSDate to an NSString by calling a stringFromDate method on the formatter *f in your for loop...
for (int i = iStart; i < components.day; ++i) {
NSDateComponents *newComponents = [NSDateComponents new];
newComponents.day = i;
newComponents.hour = 0;
newComponents.minute = 0;
newComponents.second = 0;
NSDate *date = [gregorianCalendar dateByAddingComponents:newComponents
toDate:startDate
options:0];
// THIS IS THE CODE I ADDED TO MINE //
// convert NSDate to string calling on *f (NSDateformatter)
NSString *string = [f stringFromDate:date];
// split the string to separate year, month, etc...
NSArray *array = [string componentsSeparatedByString:#"-"];
// create second NSString withFormat and only add the variable from the date that you find pertinent
NSString *sDateNew = [NSString stringWithFormat:#"%#-%#-%#",array[0],array[1],array[2]];
// then simply add the sDateNew string to dates array
[dates addObject:sDateNew];
}
I think this should be put into the comment section of your answer vikingsegundo but it would not let me.

Related

how to calculate difference between two times in different dates in iOS?

starttime= 23:00 pm
end time= 5:00 am
I need the summing time of the start time to end time
i am trying this code but it is not helpful to me
NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:#"HH"];
NSDate *currentTime = [NSDate date];
NSDate *openTime = [formatter dateFromString:start];
NSDate *closeTime = [formatter dateFromString:end ];
NSCalendar *calender = [NSCalendar currentCalendar];
NSDateComponents *currentTimeComponents = [calender components:NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit fromDate:currentTime];
NSDateComponents *openTimeComponents = [calender components:NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit fromDate:openTime];
NSDateComponents *closeTimeComponents = [calender components:NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit fromDate:closeTime];
NSUInteger currentTimeSeconds = currentTimeComponents.hour;
NSUInteger openTimeSeconds = openTimeComponents.hour;
NSUInteger closeTimeSeconds = closeTimeComponents.hour;
if (currentTimeSeconds>openTimeSeconds && currentTimeSeconds<closeTimeSeconds) {
NSLog(#"Time Between Open and Close Time %lu",(unsigned long)currentTimeSeconds);
}
and it shows 0 hors.
please help me some one?
thanks in advance
If possible, I'd look at using libs/frameworks to accomplish that through their APIs. For example, I've done date operations using DateTools

Create new array entries for repeating dates

i am parsing a .ics file and i got a property called rrule. The objects i successfully parsed and added in my array are objects with multiple properties.
The rrule property (which is one of the properties of the object) is a NSString and gives the following information:Rrule:FREQ=WEEKLY;UNTIL=20140322;INTERVAL=1;BYDAY=FR
Now i want to add another object in the array with the same information for every new entry until the "UNTIL DATE" is reached, only the startDate and endDate should change. In the above example for a start on the 28. Feb there would be added objects for the 7.3 and 14.3 and 21.3. The 22.3 is a saturday and after this day there are no other fridays that should be added. The hour, minutes and seconds also should stay just the same.
Anyone who can help me with that ? I managed to parse the information from the .ics file but i struggle with implementing this one so i can really use the information i parsed.
The other properties of an object from the array are called:
NSString *summary, NSString *location, NSDate *startDate, NSDate *endDate, NSString *rrule, NSString *category, BOOL isExam
EDIT:
Ok here is what i have tried based on your answer (sbooth):
NSDictionary *stringToNumber = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:2],#"MO",
[NSNumber numberWithInt:3],#"TU",
[NSNumber numberWithInt:4],#"WE",
[NSNumber numberWithInt:5],#"TH",
[NSNumber numberWithInt:6],#"FR",
[NSNumber numberWithInt:7],#"SA",
[NSNumber numberWithInt:1],#"SU",
nil];
for(DECalEntry *entry in planEntries) {
if(entry.rrule.length > 1) { //rrule is not empty
NSDateComponents *week = [[NSDateComponents alloc]init];
[week setWeek:1];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comp = [[NSDateComponents alloc] init];
NSNumber *number = [stringToNumber objectForKey:[self stringBetweenString:#"BYDAY=" andString:#"" andString:entry.rrule]];
[comp setWeekday:[number intValue]];
NSDate *newStartDate = [gregorian dateByAddingComponents:comp toDate:entry.startDate options:0];
NSDate *newEndDate = [gregorian dateByAddingComponents:comp toDate:entry.endDate options:0];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"yyyyMMdd"];
NSDate *untilDate = [df dateFromString: [self stringBetweenString:#"UNTIL=" andString:#";" andString:entry.rrule]];
while([newStartDate compare:untilDate] == NSOrderedAscending) {
DECalEntry *newEntry = [[DECalEntry alloc]init];
newEntry.summary = entry.summary;
newEntry.location = entry.location;
newEntry.isExam = entry.isExam;
newEntry.rrule = #"";
newEntry.startDate = newStartDate;
newEntry.endDate = newEndDate;
newEntry.category = entry.category;
[self.helpArray addObject:newEntry];
newStartDate =[gregorian dateByAddingComponents:comp toDate:newStartDate options:0];
newEndDate =[gregorian dateByAddingComponents:comp toDate:newEndDate options:0];
}
}
if([self.helpArray count] > 0) {
for(DECalEntry *entries in self.helpArray) {
[planEntries addObject:entries];
}
}
and the stringBetweenSting method:
-(NSString*)stringBetweenString:(NSString*)start andString:(NSString*)end andString:(NSString *)string{
NSScanner* scanner = [NSScanner scannerWithString:string];
[scanner setCharactersToBeSkipped:nil];
[scanner scanUpToString:start intoString:NULL];
if ([scanner scanString:start intoString:NULL]) {
NSString* result = nil;
if ([scanner scanUpToString:end intoString:&result]) {
return result;
}
}
return nil;
}
EDIT2: Ok i finally got it working. The problem was, that there was one rule with a daily frequence, not weekly. That caused the while loop to never terminate. Now everything is working, thanks again !
You can do this using NSDateComponents and NSDate. The first step is to parse the rule into the appropriate NSDateComponents to be added to the start date. I don't know the full syntax of the rules you're using but for the example you gave the components would consist of one week since the frequency is weekly:
NSDateComponents *week = [[NSDateComponents alloc] init];
[dc setWeek:1];
Since you already know when the interval starts the starting date for calculations should be the first Friday after startDate. To find the first Friday after an arbitrary date using the Gregorian calendar:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *fri = [[NSDateComponents alloc] init];
[fri setWeekday:6];
NSDate *firstFridayFollowing = [gregorian dateByAddingDateComponents:fri toDate:startDate options:0];
Once you know the first friday you can add weeks to it:
NSDate *oneWeekLater = [gregorian dateByAddingDateComponents:week toDate:firstFridayFollowing options:0];
It is then simple to do that until the next generated date is later than your end date.

get days part from a date interval

I want to get day parts from a date interval.
For example I have a date interval 21/12/2013 to 28/12/2013.
Now I want to get all day part from this interval like as 21,22,23,24,25,26,27,28.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *gmt = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
[dateFormatter setTimeZone:gmt];
[dateFormatter setDateFormat:#"MMM dd, yyyy"];
NSString *date_str=[NSString stringWithFormat:#"%#",from_date];
NSLog(#"%#",date_str);
NSString *date_str1=[NSString stringWithFormat:#"%#",to_date];
NSLog(#"%#",date_str1);
NSDate *starting_date = [dateFormatter dateFromString:date_str];
NSDate *end_date = [dateFormatter dateFromString:date_str1];
NSCalendar *gregorian = [[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger unitFlags = NSDayCalendarUnit;
NSDateComponents *components = [gregorian components:unitFlags fromDate:starting_date toDate:end_date options:0];
NSInteger days = [components day];
That code giving total no of days.
How can i get this output?
Thanks
Continuing from your code and assuming,
NSString *date_str=[NSString stringWithFormat:#"%#",#"December 21, 2013"];
NSString *date_str1=[NSString stringWithFormat:#"%#",#"December 28, 2013"];
If you need it within the same month, it can be in this way,
NSDateComponents *component1 = [gregorian components:unitFlags fromDate:starting_date];
NSDateComponents *component2 = [gregorian components:unitFlags fromDate:end_date];
for (int i = component1.day; i <= component2.day; i++) {
NSLog(#"%i", i);
}
But if your dates expand between different months, then you have to add checking for month components in the loop.
I will continue on your code, with some dirty code of mine, but it gets the job done if what you provided is your date format:
NSArray *begining_day = [date_str componentsSeparatedByString:#"/"];
NSMutableArray *part_days = [[NSMutableArray alloc] init];
for (int i = 0; i < days; i++) {
[part_days addObject:([begining_day[0] integerValue] + i)];
}
Now part_days will have your days, BUT! You have to handle the end of each month.
I'm 100% sure you'll find better solutions, but I thought I could share the first thing I thought of, you might benefit from it.
You can try below code:
NSArray *array = [[NSArray alloc] initWithObjects:#"1/12/14",#"2/12/14",#"3/12/14",#"4/12/14",#"5/12/14", nil];
for (int i = 0; i < [array count]; i++) {
NSArray *myArray = [[array objectAtIndex:i] componentsSeparatedByString:#"/"];
[dayArray addObject:[myArray objectAtIndex:0]];
}
NSLog(#"%#",dayArray);
You can incrementally add 24 hours to your startDate until you pass your endDate. Using NSDateComponents you can pick out the day. Instead of logging them with NSLog just store them in a string or array.
NSDate *startDate = [NSDate dateWithTimeIntervalSinceReferenceDate:300000000];
NSDate *endDate = [NSDate dateWithTimeIntervalSinceReferenceDate:302000000];
for (NSDate *nextDate = startDate; [nextDate compare:endDate] < 0; nextDate = [nextDate dateByAddingTimeInterval:24*60*60] ) {
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:nextDate];
NSInteger day = [components day];
NSLog(#"day %li", (long)day);
}

How to make another array containing number of days remain

I have array which is like as below
_combinedBirthdates(
"03/12/2013",
"03/12/2013",
"08/13/1990",
"12/09/1989",
"02/06",
"09/08",
"03/02/1990",
"08/22/1989",
"03/02",
"05/13",
"10/16",
"07/08",
"08/31/1990",
"04/14/1992",
"12/15/1905",
"08/14/1989",
"10/07/1987",
"07/25",
"07/17/1989",
"03/24/1987",
"07/28/1988",
"01/21/1990",
"10/13"
)
all elements are NSString in above NSArray.
How can I make another array which contains number of days remain for particular date
something like this
_newlymadeArray(
"125",
"200",
"50",
"500",
"125",
and so on
)
Use this algorithm:
Obtain the current year
Convert each date from your array to a date in the current year. For example, "03/02/1990" becomes "03/02/2013"
If the date from the step 2 is before the current date, advance its year by one (i.e. "03/02/2013" becomes "03/02/2014")
Using a technique from this question, find the number of days till the date from step 3. It will be less than the number of days in a year.
unsigned int unitFlags = NSDayCalendarUnit;
NSCalendar *currCalendar = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
NSMutableArray * _newlymadeArray = [[NSMutableArray alloc] init];
for (NSString * str in _combinedBirthdates){
NSDate * toDate = [dateFormatter dateFromString:str];
NSDateComponents *daysInfo = [currCalendar components:unitFlags fromDate:[NSDate date] toDate:toDate options:0];
int days = [daysInfo day];
[_newlymadeArray addObject:[NSString stringWithFormat:#"%d",days]];
}
You need to iterate through the first array and get the date in NSDate and use the info to get the difference in days from the current date to the next date in the array.
You will have to add the necessary checks and this is untested code.
Try this code snap.
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setTimeZone:[NSTimeZone localTimeZone]];
[formatter setDateFormat:#"MM/dd/yyyy"];
NSDate *currentDate = [formatter dateFromString:#"03/12/2013"];
NSTimeInterval srcInterval = [currentDate timeIntervalSince1970];
NSArray *_combinedBirthdates = #[#"03/15/2013", #"05/15/2013"];
NSMutableArray *_newlymadeArray = [NSMutableArray array];
const NSInteger SECONDS_PER_DAY = 60 * 60 * 24;
for (NSString *one in _combinedBirthdates) {
NSDate *destDate = [formatter dateFromString:one];
NSTimeInterval destInterval = [destDate timeIntervalSince1970];
NSInteger diff = (destInterval - srcInterval) / SECONDS_PER_DAY;
[_newlymadeArray addObject:[NSString stringWithFormat:#"%d", diff]];
}
That's it! :)

UIPickerView With Custom Dates

I cannot use a UIDatePicker. I just want to throw that out at the very beginning before all the commenters tell me to just use a UIDatePicker. I want to have a Picker Wheel that shows all the day of the year, leading up to today, and display it as Day: 1/Jan 1, Day: 2/Jan 2 and so on. Here is what I have so far, which detects what day 'number' of the year it is, and populates the PickerWheel with all the dates leading up to today:
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSDate *today = [NSDate date];
NSInteger dc = [currentCalendar ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSYearCalendarUnit
forDate:today];
options = [[NSMutableArray alloc]init];
for (int index = 1; index <= dc; index++)
{
NSString *pickerItemTitle = [NSString stringWithFormat: #"Day: %d", index];
[options addObject: pickerItemTitle];
}
What can I do to make it also match up the NSInteger with the date, and have that be part of the pickerItemTitle as well?
Got it figured out. Added some code to form a date based off integer of day into the loop. Now, the viewWillAppear method that sets the array for the uipickerview looks like this:
- (void)viewWillAppear:(BOOL)animated
{
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSDate *today = [NSDate date];
NSInteger dc = [currentCalendar ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSYearCalendarUnit
forDate:today];
options = [[NSMutableArray alloc]init];
for (int index = 1; index <= dc; index++)
{
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:index];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:components];
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:#"MMM dd"];
NSString *articleDateString = [formatter stringFromDate:date];
NSString *pickerItemTitle = [NSString stringWithFormat: #"Day: %d/%#", index, articleDateString];
[options addObject: pickerItemTitle];
}
[super viewWillAppear:YES];
}

Resources