2007-01-31 18:11:29 +01:00
|
|
|
/*
|
|
|
|
Copyright (C) 2000-2005 SKYRIX Software AG
|
|
|
|
|
|
|
|
This file is part of SOPE.
|
|
|
|
|
|
|
|
SOPE is free software; you can redistribute it and/or modify it under
|
|
|
|
the terms of the GNU Lesser General Public License as published by the
|
|
|
|
Free Software Foundation; either version 2, or (at your option) any
|
|
|
|
later version.
|
|
|
|
|
|
|
|
SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
|
|
License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
|
|
License along with SOPE; see the file COPYING. If not, write to the
|
|
|
|
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2007-06-07 18:17:51 +02:00
|
|
|
#import <Foundation/NSDate.h>
|
|
|
|
#import <Foundation/NSDictionary.h>
|
|
|
|
#import <Foundation/NSString.h>
|
|
|
|
#import <Foundation/NSTimeZone.h>
|
|
|
|
#import <Foundation/NSUserDefaults.h>
|
|
|
|
|
|
|
|
#import <NGExtensions/NSCalendarDate+misc.h>
|
|
|
|
#import <NGExtensions/NSObject+Logs.h>
|
|
|
|
|
|
|
|
#import "iCalDateHolder.h"
|
|
|
|
#import "iCalObject.h"
|
2007-01-31 18:11:29 +01:00
|
|
|
|
|
|
|
@interface NSTimeZone(iCalTimeZone)
|
|
|
|
|
|
|
|
+ (NSTimeZone *)timeZoneWithICalId:(NSString *)_tz;
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation iCalDateHolder
|
|
|
|
|
|
|
|
static NSTimeZone *gmt = nil;
|
|
|
|
|
|
|
|
+ (void)initialize {
|
|
|
|
if (gmt == nil)
|
|
|
|
gmt = [[NSTimeZone timeZoneWithName:@"GMT"] retain];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)dealloc {
|
|
|
|
[self->tzid release];
|
|
|
|
[self->string release];
|
|
|
|
[self->tag release];
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* accessors */
|
|
|
|
|
|
|
|
- (void)setString:(NSString *)_value {
|
|
|
|
ASSIGNCOPY(self->string, _value);
|
|
|
|
}
|
|
|
|
- (NSString *)string {
|
|
|
|
return self->string;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setTag:(NSString *)_value {
|
|
|
|
ASSIGNCOPY(self->tag, _value);
|
|
|
|
}
|
|
|
|
- (NSString *)tag {
|
|
|
|
return self->tag;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setTzid:(NSString *)_value {
|
|
|
|
ASSIGNCOPY(self->tzid, _value);
|
|
|
|
}
|
|
|
|
- (NSString *)tzid {
|
|
|
|
return self->tzid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* mapping to Foundation */
|
|
|
|
|
|
|
|
- (NSTimeZone *)timeZone {
|
|
|
|
// TODO: lookup tzid in iCalCalendar !
|
|
|
|
NSString *s;
|
|
|
|
|
|
|
|
s = [self tzid];
|
|
|
|
|
|
|
|
/* a hack */
|
|
|
|
if ([s hasPrefix:@"/softwarestudio.org"]) {
|
|
|
|
NSRange r;
|
|
|
|
|
|
|
|
r = [s rangeOfString:@"Europe/"];
|
|
|
|
if (r.length > 0)
|
|
|
|
s = [s substringFromIndex:r.location];
|
|
|
|
}
|
|
|
|
return [NSTimeZone timeZoneWithICalId:s];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* decoding */
|
|
|
|
|
|
|
|
- (id)awakeAfterUsingSaxDecoder:(id)_decoder {
|
|
|
|
NSCalendarDate *date = nil;
|
|
|
|
NSString *s;
|
|
|
|
NSTimeZone *tz;
|
|
|
|
|
|
|
|
s = self->string;
|
|
|
|
if ([s length] < 5) {
|
|
|
|
[self logWithFormat:@"tag %@: got an weird date string '%@' ?!",
|
|
|
|
self->tag, s];
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* calculate timezone */
|
|
|
|
|
|
|
|
if ([self->string hasSuffix:@"Z"]) {
|
|
|
|
/* zulu time, eg 20021009T094500Z */
|
|
|
|
tz = gmt;
|
|
|
|
s = [s substringToIndex:([s length] - 1)];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
tz = [self timeZone];
|
|
|
|
|
|
|
|
/*
|
|
|
|
012345678901234
|
|
|
|
20021009T094500 - 15 chars
|
|
|
|
20021009T0945 - 13 chars
|
|
|
|
991009T0945 - 11 chars
|
|
|
|
|
|
|
|
20031111 - 8 chars
|
|
|
|
*/
|
|
|
|
if ([s rangeOfString:@"T"].length == 0 && [s length] == 8) {
|
|
|
|
/* hm, maybe a date without a time? like an allday event! */
|
|
|
|
int year, month, day;
|
2007-11-03 04:17:55 +01:00
|
|
|
char *buf;
|
|
|
|
|
|
|
|
buf = strdup([s cStringUsingEncoding: NSASCIIStringEncoding]);
|
2007-01-31 18:11:29 +01:00
|
|
|
|
2007-11-03 04:17:55 +01:00
|
|
|
day = atoi(buf + 6);
|
|
|
|
buf[6] = '\0';
|
|
|
|
month = atoi(buf + 4);
|
|
|
|
buf[4] = '\0';
|
|
|
|
year = atoi(buf);
|
|
|
|
free (buf);
|
|
|
|
|
2007-01-31 18:11:29 +01:00
|
|
|
date = [NSCalendarDate dateWithYear:year month:month day:day
|
|
|
|
hour:0 minute:0 second:0
|
|
|
|
timeZone:tz];
|
|
|
|
}
|
|
|
|
else if ([s length] == 15) {
|
|
|
|
int year, month, day, hour, minute, second;
|
|
|
|
char buf[24];
|
|
|
|
[s getCString:&(buf[0])];
|
|
|
|
|
|
|
|
second = atoi(&(buf[13])); buf[13] = '\0';
|
|
|
|
minute = atoi(&(buf[11])); buf[11] = '\0';
|
|
|
|
hour = atoi(&(buf[9])); buf[9] = '\0';
|
|
|
|
day = atoi(&(buf[6])); buf[6] = '\0';
|
|
|
|
month = atoi(&(buf[4])); buf[4] = '\0';
|
|
|
|
year = atoi(&(buf[0]));
|
|
|
|
|
|
|
|
date = [NSCalendarDate dateWithYear:year month:month day:day
|
|
|
|
hour:hour minute:minute second:second
|
|
|
|
timeZone:tz];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
NSLog(@"%s: unknown date format (%@) ???", __PRETTY_FUNCTION__, s);
|
|
|
|
|
|
|
|
if (date == nil)
|
|
|
|
NSLog(@"couldn't convert string '%@' to date (format '%@') ..", s);
|
|
|
|
|
|
|
|
return date;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* description */
|
|
|
|
|
|
|
|
- (void)appendAttributesToDescription:(NSMutableString *)ms {
|
|
|
|
if (self->tag) [ms appendFormat:@" %@", self->tag];
|
|
|
|
if (self->string) [ms appendFormat:@" '%@'", self->string];
|
|
|
|
if (self->tzid) [ms appendFormat:@" tz=%@", self->tzid];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *)description {
|
|
|
|
NSMutableString *ms;
|
|
|
|
|
|
|
|
ms = [NSMutableString stringWithCapacity:128];
|
|
|
|
[ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])];
|
|
|
|
[self appendAttributesToDescription:ms];
|
|
|
|
[ms appendString:@">"];
|
|
|
|
return ms;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end /* iCalDateHolder */
|
|
|
|
|
|
|
|
@implementation NSTimeZone(iCalTimeZone)
|
|
|
|
|
|
|
|
static NSMutableDictionary *idToTz = nil; // THREAD
|
|
|
|
|
|
|
|
+ (NSTimeZone *)timeZoneWithICalId:(NSString *)_tzid {
|
|
|
|
static NSString *iCalDefaultTZ = nil;
|
|
|
|
NSTimeZone *tz;
|
|
|
|
|
|
|
|
if (idToTz == nil)
|
|
|
|
idToTz = [[NSMutableDictionary alloc] initWithCapacity:16];
|
|
|
|
|
|
|
|
if ([_tzid length] == 0) {
|
|
|
|
|
|
|
|
tz = [iCalObject iCalDefaultTimeZone];
|
|
|
|
if (tz != nil) return tz;
|
|
|
|
|
|
|
|
if (iCalDefaultTZ == nil) {
|
|
|
|
NSString *defTz;
|
|
|
|
NSUserDefaults *ud;
|
|
|
|
// TODO: take a default timeZone
|
|
|
|
ud = [NSUserDefaults standardUserDefaults];
|
|
|
|
defTz = [ud stringForKey:@"iCalTimeZoneName"];
|
|
|
|
if ([defTz length] == 0)
|
|
|
|
defTz = [ud stringForKey:@"TimeZoneName"];
|
|
|
|
if ([defTz length] == 0)
|
|
|
|
defTz = [ud stringForKey:@"TimeZone"];
|
|
|
|
if ([defTz length] == 0)
|
|
|
|
defTz = @"GMT";
|
|
|
|
iCalDefaultTZ = [defTz retain];
|
|
|
|
}
|
|
|
|
|
|
|
|
_tzid = iCalDefaultTZ;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([_tzid length] == 0)
|
|
|
|
_tzid = @"GMT";
|
|
|
|
|
|
|
|
tz = [idToTz objectForKey:_tzid];
|
|
|
|
if (tz == nil) tz = [NSTimeZone timeZoneWithName:_tzid];
|
|
|
|
if (tz == nil) tz = [NSTimeZone timeZoneWithAbbreviation:_tzid];
|
|
|
|
|
|
|
|
if (tz == nil) {
|
|
|
|
NSLog(@"couldn't map timezone id %@", _tzid);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tz) [idToTz setObject:tz forKey:_tzid];
|
|
|
|
return tz;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end /* NSTimeZone(iCalTimeZone) */
|