Reputation: 9064
Given some startDate, I would like to degenerate x number of consecutive days after this startDate. I'm attempting to use the following code:
// Generate dates
self.days = [[NSMutableArray alloc] init];
NSDate *startDate = [NSDate date];
NSCalendar *theCalendar = [NSCalendar currentCalendar];
NSDateComponents *dayComponent = [[NSDateComponents alloc] init];
dayComponent.day = 1;
for (int i = 1; i < self.mygoal.goalDays; i++) {
[self.days addObject:startDate];
startDate = [theCalendar dateByAddingComponents:dayComponent toDate:startDate options:0];
}
Question: Is the reassignment of startDate ok, given that I'm adding the same object to self.days?
Upvotes: 0
Views: 80
Reputation: 52227
Creating a sequence of dates is not as trivial as it sounds. Actually it is covered in the great WWDC2011 video «Performing Calendar Calculations».
You are adding in every loop a day to the last date. But actually this will fail in timezones with DST if the time is in the hour that is changed for the day of switching and for any following days as the dates will be nil.
If you instead change the date components i the loop and add it to the original satrtdate, it will only effect the day of DST-switching.
To also handle that you can set the hour of the start date to something safe — as noon — as all switches are performed at night hours.
With all this in mind I would use something like this to create a sequence of days with times set to start of day:
NSUInteger numberOfDays = 10;
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *startDate = [cal dateFromComponents:({
NSDateComponents *comps = [[NSDateComponents alloc] init];
comps.year = 2015;
comps.month = 1;
comps.day = 2;
comps.hour = 12; // for DST-safety
comps;
})];
NSMutableArray *dates = [@[] mutableCopy];
for (NSUInteger i =0 ; i < numberOfDays; ++i) {
NSDateComponents *comps = [[NSDateComponents alloc] init];
comps.day = i;
NSDate *date = [cal dateByAddingComponents:comps
toDate:startDate
options:0];
// set date to beginning of day
[cal rangeOfUnit:NSCalendarUnitDay
startDate:&date
interval:NULL
forDate:date];
[dates addObject:date];
}
So, yes, reassignment is technically OK, but in this particular case it is might cause unexpected trouble.
Upvotes: 3
Reputation: 2616
It's fine because you're not actually adding the same object. dateByAddingComponents: returns a new object, so when you assign it to startDate you are replacing the reference to your old object to a reference to the new one
Upvotes: 0