From 4ddf92aadb9ee2616d3e391557ef4eb076d63160 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Tue, 17 Feb 2015 16:09:16 -0500 Subject: [PATCH] JSON: Return ISO8601 dates in calendar components --- .../Appointments/iCalEntityObject+SOGo.h | 6 ++ .../Appointments/iCalEntityObject+SOGo.m | 64 +++++++++++++-- SoObjects/Appointments/iCalEvent+SOGo.m | 77 +++++-------------- .../iCalRepeatableEntityObject+SOGo.m | 18 ++++- UI/Scheduler/UIxAppointmentEditor.m | 25 +----- 5 files changed, 101 insertions(+), 89 deletions(-) diff --git a/SoObjects/Appointments/iCalEntityObject+SOGo.h b/SoObjects/Appointments/iCalEntityObject+SOGo.h index 02de57912..88e7d3b24 100644 --- a/SoObjects/Appointments/iCalEntityObject+SOGo.h +++ b/SoObjects/Appointments/iCalEntityObject+SOGo.h @@ -53,6 +53,12 @@ extern NSNumber *iCalDistantFutureNumber; - (int) priorityNumber; - (NSDictionary *) createdBy; +- (NSCalendarDate *) dateFromString: (NSString *) dateString + inContext: (WOContext *) context; +- (void) adjustDate: (NSCalendarDate **) date + withTimeString: (NSString *) timeString + inContext: (WOContext *) context; + - (NSNumber *) quickRecordDateAsNumber: (NSCalendarDate *) _date withOffset: (int) offset forAllDay: (BOOL) allDay; diff --git a/SoObjects/Appointments/iCalEntityObject+SOGo.m b/SoObjects/Appointments/iCalEntityObject+SOGo.m index a3ffd4c05..837f94849 100644 --- a/SoObjects/Appointments/iCalEntityObject+SOGo.m +++ b/SoObjects/Appointments/iCalEntityObject+SOGo.m @@ -92,17 +92,19 @@ NSNumber *iCalDistantFutureNumber = nil; data = [NSMutableDictionary dictionaryWithObjectsAndKeys: [[self tag] lowercaseString], @"component", [self summary], @"summary", - [self priority], @"priority", nil]; + value = [self priority]; + if ([value length]) [data setObject: value forKey: @"priority"]; + value = [self location]; - if (value) [data setObject: value forKey: @"location"]; + if ([value length]) [data setObject: value forKey: @"location"]; value = [self comment]; - if (value) [data setObject: value forKey: @"comment"]; + if ([value length]) [data setObject: value forKey: @"comment"]; value = [self attach]; - if (value) [data setObject: [value absoluteString] forKey: @"attachUrl"]; + if (value && (value = [value absoluteString]) && [value length]) [data setObject: value forKey: @"attachUrl"]; value = [self accessClass]; if (value) [data setObject: [value lowercaseString] forKey: @"classification"]; @@ -124,7 +126,7 @@ NSNumber *iCalDistantFutureNumber = nil; // Organizer organizer = [self organizer]; - if (organizer) + if ([[organizer email] length]) { organizerData = [NSMutableDictionary dictionaryWithObjectsAndKeys: [organizer rfc822Email], @"email", @@ -212,6 +214,58 @@ NSNumber *iCalDistantFutureNumber = nil; return data; } +// From [UIxDatePicker takeValuesFromRequest:inContext:] +- (NSCalendarDate *) dateFromString: (NSString *) dateString + inContext: (WOContext *) context +{ + NSInteger dateTZOffset, userTZOffset; + NSTimeZone *systemTZ, *userTZ; + SOGoUserDefaults *ud; + NSCalendarDate *date; + + date = [NSCalendarDate dateWithString: dateString + calendarFormat: @"%Y-%m-%d"]; + if (!date) + [self warnWithFormat: @"Could not parse dateString: '%@'", dateString]; + + // We must adjust the date timezone because "dateWithString:..." uses the + // system timezone, which can be different from the user's. */ + ud = [[context activeUser] userDefaults]; + systemTZ = [date timeZone]; + dateTZOffset = [systemTZ secondsFromGMTForDate: date]; + userTZ = [ud timeZone]; + userTZOffset = [userTZ secondsFromGMTForDate: date]; + if (dateTZOffset != userTZOffset) + date = [date dateByAddingYears: 0 months: 0 days: 0 + hours: 0 minutes: 0 + seconds: (dateTZOffset - userTZOffset)]; + [date setTimeZone: userTZ]; + + return date; +} + +// From [UIxTimeDatePicker takeValuesFromRequest:inContext:] +- (void) adjustDate: (NSCalendarDate **) date + withTimeString: (NSString *) timeString + inContext: (WOContext *) context +{ + unsigned _year, _month, _day, _hour, _minute; + SOGoUserDefaults *ud; + NSArray *_time; + + _year = [*date yearOfCommonEra]; + _month = [*date monthOfYear]; + _day = [*date dayOfMonth]; + _time = [timeString componentsSeparatedByString: @":"]; + _hour = [[_time objectAtIndex: 0] intValue]; + _minute = [[_time objectAtIndex: 1] intValue]; + + ud = [[context activeUser] userDefaults]; + *date = [NSCalendarDate dateWithYear: _year month: _month day: _day + hour: _hour minute: _minute second: 0 + timeZone: [ud timeZone]]; +} + - (void) _setAttendees: (NSArray *) attendees { NSMutableArray *newAttendees; diff --git a/SoObjects/Appointments/iCalEvent+SOGo.m b/SoObjects/Appointments/iCalEvent+SOGo.m index 25249435c..c8a4f0c3b 100644 --- a/SoObjects/Appointments/iCalEvent+SOGo.m +++ b/SoObjects/Appointments/iCalEvent+SOGo.m @@ -42,6 +42,8 @@ #import #import +#import + #import "SOGoAppointmentFolder.h" #import "iCalRepeatableEntityObject+SOGo.h" @@ -319,58 +321,6 @@ } } -// From [UIxDatePicker takeValuesFromRequest:inContext:] -- (NSCalendarDate *) _dateFromString: (NSString *) dateString - inContext: (WOContext *) context -{ - NSInteger dateTZOffset, userTZOffset; - NSTimeZone *systemTZ, *userTZ; - SOGoUserDefaults *ud; - NSCalendarDate *date; - - date = [NSCalendarDate dateWithString: dateString - calendarFormat: @"%Y-%m-%d"]; - if (!date) - [self warnWithFormat: @"Could not parse dateString: '%@'", dateString]; - - // We must adjust the date timezone because "dateWithString:..." uses the - // system timezone, which can be different from the user's. */ - ud = [[context activeUser] userDefaults]; - systemTZ = [date timeZone]; - dateTZOffset = [systemTZ secondsFromGMTForDate: date]; - userTZ = [ud timeZone]; - userTZOffset = [userTZ secondsFromGMTForDate: date]; - if (dateTZOffset != userTZOffset) - date = [date dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: (dateTZOffset - userTZOffset)]; - [date setTimeZone: userTZ]; - - return date; -} - -// From [UIxTimeDatePicker takeValuesFromRequest:inContext:] -- (void) _adjustDate: (NSCalendarDate **) date - withTimeString: (NSString *) timeString - inContext: (WOContext *) context -{ - unsigned _year, _month, _day, _hour, _minute; - SOGoUserDefaults *ud; - NSArray *_time; - - _year = [*date yearOfCommonEra]; - _month = [*date monthOfYear]; - _day = [*date dayOfMonth]; - _time = [timeString componentsSeparatedByString: @":"]; - _hour = [[_time objectAtIndex: 0] intValue]; - _minute = [[_time objectAtIndex: 1] intValue]; - - ud = [[context activeUser] userDefaults]; - *date = [NSCalendarDate dateWithYear: _year month: _month day: _day - hour: _hour minute: _minute second: 0 - timeZone: [ud timeZone]]; -} - /** * @see [iCalRepeatableEntityObject+SOGo attributes] * @see [iCalEntityObject+SOGo attributes] @@ -378,9 +328,22 @@ */ - (NSDictionary *) attributesInContext: (WOContext *) context { + NSCalendarDate *eventStartDate, *eventEndDate; NSMutableDictionary *data; + NSTimeZone *timeZone; + SOGoUserDefaults *ud; - data = [NSMutableDictionary dictionaryWithDictionary: [super attributes]]; + ud = [[context activeUser] userDefaults]; + timeZone = [ud timeZone]; + eventStartDate = [self startDate]; + eventEndDate = [self endDate]; + [eventStartDate setTimeZone: timeZone]; + [eventEndDate setTimeZone: timeZone]; + + data = [NSMutableDictionary dictionaryWithDictionary: [super attributesInContext: context]]; + + [data setObject: [eventStartDate iso8601DateString] forKey: @"startDate"]; + [data setObject: [eventEndDate iso8601DateString] forKey: @"endDate"]; [data setObject: [NSNumber numberWithBool: [self isAllDay]] forKey: @"isAllDay"]; [data setObject: [NSNumber numberWithBool: ![self isOpaque]] forKey: @"isTransparent"]; @@ -412,19 +375,19 @@ // Handle start/end dates o = [data objectForKey: @"startDate"]; if ([o isKindOfClass: [NSString class]] && [o length]) - aptStartDate = [self _dateFromString: o inContext: context]; + aptStartDate = [self dateFromString: o inContext: context]; o = [data objectForKey: @"startTime"]; if ([o isKindOfClass: [NSString class]] && [o length]) - [self _adjustDate: &aptStartDate withTimeString: o inContext: context]; + [self adjustDate: &aptStartDate withTimeString: o inContext: context]; o = [data objectForKey: @"endDate"]; if ([o isKindOfClass: [NSString class]] && [o length]) - aptEndDate = [self _dateFromString: o inContext: context]; + aptEndDate = [self dateFromString: o inContext: context]; o = [data objectForKey: @"endTime"]; if ([o isKindOfClass: [NSString class]] && [o length]) - [self _adjustDate: &aptEndDate withTimeString: o inContext: context]; + [self adjustDate: &aptEndDate withTimeString: o inContext: context]; o = [data objectForKey: @"isTransparent"]; if ([o isKindOfClass: [NSNumber class]]) diff --git a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m index 43e42a7ab..66753eae1 100644 --- a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m +++ b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m @@ -41,6 +41,8 @@ #import #import +#import + #import "iCalRepeatableEntityObject+SOGo.h" @implementation iCalRepeatableEntityObject (SOGoExtensions) @@ -82,12 +84,15 @@ */ - (NSDictionary *) attributesInContext: (WOContext *) context { - NSMutableDictionary *data, *repeat; NSArray *rules; + NSCalendarDate *untilDate; + NSMutableDictionary *data, *repeat; NSString *frequency; + NSTimeZone *timeZone; + SOGoUserDefaults *ud; iCalRecurrenceRule *rule; - data = [NSMutableDictionary dictionaryWithDictionary: [super attributes]]; + data = [NSMutableDictionary dictionaryWithDictionary: [super attributesInContext: context]]; rules = [self recurrenceRules]; if ([rules count] > 0) @@ -100,8 +105,13 @@ [repeat setObject: [NSNumber numberWithInt: [rule repeatInterval]] forKey: @"interval"]; if ([rule repeatCount]) [repeat setObject: [NSNumber numberWithInt: [rule repeatCount]] forKey: @"count"]; - if ([rule untilDate]) - [repeat setObject: [NSNumber numberWithUnsignedInt: [[rule untilDate] timeIntervalSince1970]] forKey: @"until"]; + if ((untilDate = [rule untilDate])) + { + ud = [[context activeUser] userDefaults]; + timeZone = [ud timeZone]; + [untilDate setTimeZone: timeZone]; + [repeat setObject: [untilDate iso8601DateString] forKey: @"until"]; + } if ([[rule byDay] length]) [repeat setObject: [[rule byDayMask] asRuleArray] forKey: @"days"]; if ([[rule byMonthDay] count]) diff --git a/UI/Scheduler/UIxAppointmentEditor.m b/UI/Scheduler/UIxAppointmentEditor.m index d90a045ae..cde1f41b9 100644 --- a/UI/Scheduler/UIxAppointmentEditor.m +++ b/UI/Scheduler/UIxAppointmentEditor.m @@ -45,6 +45,7 @@ #import #import +#import #import #import #import @@ -56,7 +57,6 @@ #import #import #import -#import #import #import #import @@ -92,23 +92,6 @@ return (iCalEvent *) component; } -- (NSString *) _dateString: (NSCalendarDate *) date -{ - char buf[22]; - NSNumber *day, *month, *year; - - day = [NSNumber numberWithInt: [date dayOfMonth]]; - month = [NSNumber numberWithInt: [date monthOfYear]]; - year = [NSNumber numberWithInt: [date yearOfCommonEra]]; - - sprintf(buf, "%04d-%02d-%02d", - [year intValue], - [month intValue], - [day intValue]); - - return [NSString stringWithCString:buf]; -} - /* - (NSCalendarDate *) newStartDate { @@ -634,8 +617,6 @@ BOOL resetAlarm; unsigned int snoozeAlarm; - // [self component]; - // [self componentCalendar]; event = [self event]; ud = [[context activeUser] userDefaults]; @@ -683,16 +664,14 @@ [co nameInContainer], @"id", [componentCalendar nameInContainer], @"pid", [componentCalendar displayName], @"calendar", - [self _dateString: eventStartDate], @"startDate", [dateFormatter formattedDate: eventStartDate], @"localizedStartDate", [dateFormatter formattedTime: eventStartDate], @"startTime", - [self _dateString: eventEndDate], @"endDate", [dateFormatter formattedDate: eventEndDate], @"localizedEndDate", [dateFormatter formattedTime: eventEndDate], @"endTime", nil]; // Add attributes from iCalEvent+SOGo, iCalEntityObject+SOGo and iCalRepeatableEntityObject+SOGo - [data addEntriesFromDictionary: [event attributes]]; + [data addEntriesFromDictionary: [event attributesInContext: context]]; // Return JSON representation return [self responseWithStatus: 200 andJSONRepresentation: data];