devinross / tapkulibrary

tap + haiku = tapku, a well crafted open source iOS framework
http://devinross.com/tapku/documentation
MIT License
3.9k stars 653 forks source link

TKCalendarView - Dates shift on TimeZone change #254

Open DrBeak1 opened 11 years ago

DrBeak1 commented 11 years ago

I have a database filled with dates in the format of yyyy-MM-dd. When the calendar loads everything looks as it should - dots are where they should be, events appear when the appropriate date tile is tapped.

Then, if I navigate to Settings and change the timezone to say Tokyo (I am in California), then reload the calendar all stays the same. Dots don't shift everything is OK. Then if I restart the app, (i.e., stop, run in xcode) starting with my Timezone set to Tokyo, again everything initially loads as expected. BUT if I then go back to Settings and set the Timezone back to auto (Cupertino) and go back into my app, all of the dots shift forward by a day.

What I've found is that instead of starting at 9/1/2013 (which is the correct date for today) Tapku is starting at 8/31/2013 - thinking that is today, which is incorrect - and ultimately resulting in this shift of things forward because it's starting at this one day back so any event stored on 9/1/2013 now gets put on the calendar tile for 9/2/2013 because tile 9/1/2013 is treated as the tile for 8/31/2013. (Wow, that's confusing to read, sorry).

I cannot figure out why this happens -- or if it's something I'm doing or if it is a Tapku bug.

Any insight is greatly appreciated

Here is my code that populates the calendar -

-(NSArray *)calendarMonthView:(TKCalendarMonthView *)monthView marksFromDate:(NSDate *)startDate toDate:(NSDate *)lastDate
{
    return [self populateCalendarThroughStartDate:startDate endDate:lastDate];
}

-(NSArray *)populateCalendarThroughStartDate:(NSDate *)start endDate:(NSDate *)end
{
    NSLog(@"populateCalendarThroughStartDate:endDate");

    self.eventsForCalendarMonth = nil;
    self.eventsForCalendarMonth = [[Database sharedDatabase] currentEventsBetweenStartDate:start endDate:end];
    NSMutableArray *dates = [[Database sharedDatabase] simplifiedEventDatesBetweenStartDate:start endDate:end];

    NSDateFormatter *simplifiedFormat = [[NSDateFormatter alloc] init];
    [simplifiedFormat setDateFormat:@"yyyy-MM-dd"];

    NSMutableArray *marks = [NSMutableArray array];

    while (YES) {
        // If the date is in the data array, add it to the marks array, else don't
        NSString *simplifiedStart = [simplifiedFormat stringFromDate:start];

        if ([dates containsObject:simplifiedStart]) {
            NSLog(@"match: %@", simplifiedStart);
            [marks addObject:[NSNumber numberWithBool:YES]];
        } else {
            [marks addObject:[NSNumber numberWithBool:NO]];
        }

        if ([start compare:end]==NSOrderedDescending) break;

        NSDateComponents *info = [start dateComponentsWithTimeZone:[NSTimeZone defaultTimeZone]];
        info.day++;
        start = [NSDate dateWithDateComponents:info];

    }

    return marks;
}

UPDATE: I just noticed that even with no changes on my part - when I tap september 1st on the calendar it registers as august 31st in didSelectDate: method.

When my timezone is set to that of Tokyo (GMT+0900) tapku thinks that the first of this month is August 31.

DrBeak1 commented 11 years ago

What I had to do to fix this was change all of my dates timezones to [NSTimeZone timeZoneForSecondsFromGMT:0] when doing any kind of comparisons.