3
votes

I need to make entries in the iPhone calendar, using EventKit framework.

Since my app should be international, I need to take care of differnt timezones. What I am doing right now:

An event should start at 6:00 am. Therefore I am creating a NSDate object with this code:

[NSDate dateWithString:[NSString stringWithFormat:@"%d-%d-%d %d:%d:00 +0000",year,month,day,hour,minute]];

What I get is a NSDate object with 06:00 am and timezone GMT.

When using this NSDate as startDate of the event, I want to use the systems timezone, to make sure that the event is really shown as 06:00 am in the calendar.

Therefore I use this code:

+(NSDate*) convertToSystemTimezone:(NSDate*)sourceDate
{   
    NSTimeZone* sourceTimeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
    NSTimeZone* destinationTimeZone = [NSTimeZone systemTimeZone];  
    NSInteger sourceGMTOffset = [sourceTimeZone secondsFromGMTForDate:sourceDate];
    NSInteger destinationGMTOffset = [destinationTimeZone secondsFromGMTForDate:sourceDate];
    NSTimeInterval interval = destinationGMTOffset - sourceGMTOffset;   
    NSDate* destinationDate = [[[NSDate alloc] initWithTimeInterval:interval sinceDate:sourceDate] autorelease];         
    return destinationDate; 
}

As example, I change my devices timezone to NEW YORK. If I debug into the code, It correctly recognizes the timezone and an offset of -14400 seconds. So my start and end NSDate objects seems to be correct.

If I look into the calendar, the app created an event, that does not start at 06:00 am, but at 04:00 am.

What am I doing wrong ??

EDIT: My code to create the event:

Example for creating an event from 06:00 am to 08:00 am

int year=2011;
int month=6;
int day=26;
int hour=6;
int minute=0;

NSDate *startDate = [NSDate dateWithString:[NSString stringWithFormat:@"%d-%d-%d %d:%d:00 +0000",year,month,day,hour, minute];  
startDate=[self convertToSystemTimezone:startDate];

NSDate *endDate = [NSDate dateWithString:[NSString stringWithFormat:@"%d-%d-%d %d:%d:00 +0000",year,month,day,8, minute];   
endDate=[self convertToSystemTimezone:endDate];     

EKEventStore *eventDB = [[EKEventStore alloc] init];
EKEvent *myEvent  = [EKEvent eventWithEventStore:eventDB];      
myEvent.title  = @"Testevent";
myEvent.startDate = startDate;
myEvent.endDate   = endDate;
myEvent.allDay = NO;
[myEvent setCalendar:[eventDB defaultCalendarForNewEvents]];
NSError *err;                   
[eventDB saveEvent:myEvent span:EKSpanThisEvent error:&err];
[eventDB release];

The deletion of the existing events is not shown, but this is tested and works.

1

1 Answers

2
votes

If you want to retain the time for the system time zone then do this,

+(NSDate*) convertToSystemTimezone:(NSDate*)sourceDate {
    NSCalendar * calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
    [calendar setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];

    NSUInteger flags = (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit );
    NSDateComponents * dateComponents = [calendar components:flags fromDate:sourceDate];

    [calendar setTimeZone:[NSTimeZone systemTimeZone]];
    NSDate * myDate = [calendar dateFromComponents:dateComponents];

    return myDate;
}

But I think you should be looking at localTimeZone and not systemTimeZone. If it is the other, you can just change it in the snippet above.

EDIT

Why do you need to get the date in GMT and then convert it? Can't you directly do this?

NSCalendar * calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];

NSDateComponents * dateComponents = [[[NSDateComponents alloc] init] autorelease];
[dateComponents setYear:2011];
[dateComponents setMonth:6];
[dateComponents setDay:26];
[dateComponents setHour:6];
[dateComponents setMinute:0];

NSDate * startDate = [calendar dateFromComponents:dateComponents];

[dateComponents setHour:8];
NSDate * endDate = [calendar dateFromComponents:dateComponents];

followed by creating and saving the EKEvent instance.