]> err.no Git - scalable-opengroupware.org/blob - SOPE/NGCards/iCalDateHolder.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1229 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / SOPE / NGCards / iCalDateHolder.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with SOPE; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #import <Foundation/NSDate.h>
23 #import <Foundation/NSDictionary.h>
24 #import <Foundation/NSString.h>
25 #import <Foundation/NSTimeZone.h>
26 #import <Foundation/NSUserDefaults.h>
27
28 #import <NGExtensions/NSCalendarDate+misc.h>
29 #import <NGExtensions/NSObject+Logs.h>
30
31 #import "iCalDateHolder.h"
32 #import "iCalObject.h"
33
34 @interface NSTimeZone(iCalTimeZone)
35
36 + (NSTimeZone *)timeZoneWithICalId:(NSString *)_tz;
37
38 @end
39
40 @implementation iCalDateHolder
41
42 static NSTimeZone *gmt = nil;
43
44 + (void)initialize {
45   if (gmt == nil)
46     gmt = [[NSTimeZone timeZoneWithName:@"GMT"] retain];
47 }
48
49 - (void)dealloc {
50   [self->tzid   release];
51   [self->string release];
52   [self->tag    release];
53   [super dealloc];
54 }
55
56 /* accessors */
57
58 - (void)setString:(NSString *)_value {
59   ASSIGNCOPY(self->string, _value);
60 }
61 - (NSString *)string {
62   return self->string;
63 }
64
65 - (void)setTag:(NSString *)_value {
66   ASSIGNCOPY(self->tag, _value);
67 }
68 - (NSString *)tag {
69   return self->tag;
70 }
71
72 - (void)setTzid:(NSString *)_value {
73   ASSIGNCOPY(self->tzid, _value);
74 }
75 - (NSString *)tzid {
76   return self->tzid;
77 }
78
79 /* mapping to Foundation */
80
81 - (NSTimeZone *)timeZone {
82   // TODO: lookup tzid in iCalCalendar !
83   NSString *s;
84
85   s = [self tzid];
86   
87   /* a hack */
88   if ([s hasPrefix:@"/softwarestudio.org"]) {
89     NSRange r;
90     
91     r = [s rangeOfString:@"Europe/"];
92     if (r.length > 0)
93       s = [s substringFromIndex:r.location];
94   }
95   return [NSTimeZone timeZoneWithICalId:s];
96 }
97
98 /* decoding */
99
100 - (id)awakeAfterUsingSaxDecoder:(id)_decoder {
101   NSCalendarDate *date = nil;
102   NSString   *s;
103   NSTimeZone *tz;
104   
105   s = self->string;
106   if ([s length] < 5) {
107     [self logWithFormat:@"tag %@: got an weird date string '%@' ?!", 
108             self->tag, s];
109     return s;
110   }
111   
112   /* calculate timezone */
113   
114   if ([self->string hasSuffix:@"Z"]) {
115     /* zulu time, eg 20021009T094500Z */
116     tz = gmt;
117     s = [s substringToIndex:([s length] - 1)];
118   }
119   else
120     tz = [self timeZone];
121   
122   /* 
123      012345678901234
124      20021009T094500 - 15 chars 
125      20021009T0945   - 13 chars 
126      991009T0945     - 11 chars
127      
128      20031111        - 8 chars
129   */
130   if ([s rangeOfString:@"T"].length == 0 && [s length] == 8) {
131     /* hm, maybe a date without a time? like an allday event! */
132     int year, month, day;
133     char *buf;
134
135     buf = strdup([s cStringUsingEncoding: NSASCIIStringEncoding]);
136     
137     day    = atoi(buf + 6);
138     buf[6] = '\0';
139     month  = atoi(buf + 4);
140     buf[4] = '\0';
141     year   = atoi(buf);
142     free (buf);
143
144     date = [NSCalendarDate dateWithYear:year month:month day:day
145                            hour:0 minute:0 second:0
146                            timeZone:tz];
147   }
148   else if ([s length] == 15) {
149     int year, month, day, hour, minute, second;
150     char buf[24];
151     [s getCString:&(buf[0])];
152       
153     second = atoi(&(buf[13])); buf[13] = '\0';
154     minute = atoi(&(buf[11])); buf[11] = '\0';
155     hour   = atoi(&(buf[9]));  buf[9] = '\0';
156     day    = atoi(&(buf[6]));  buf[6] = '\0';
157     month  = atoi(&(buf[4]));  buf[4] = '\0';
158     year   = atoi(&(buf[0]));
159       
160     date = [NSCalendarDate dateWithYear:year month:month day:day
161                            hour:hour minute:minute second:second
162                            timeZone:tz];
163   }
164   else
165     NSLog(@"%s: unknown date format (%@) ???", __PRETTY_FUNCTION__, s);
166     
167   if (date == nil)
168     NSLog(@"couldn't convert string '%@' to date (format '%@') ..", s);
169
170   return date;
171 }
172
173 /* description */
174
175 - (void)appendAttributesToDescription:(NSMutableString *)ms {
176   if (self->tag)    [ms appendFormat:@" %@",  self->tag];
177   if (self->string) [ms appendFormat:@" '%@'",  self->string];
178   if (self->tzid)   [ms appendFormat:@" tz=%@", self->tzid];
179 }
180
181 - (NSString *)description {
182   NSMutableString *ms;
183
184   ms = [NSMutableString stringWithCapacity:128];
185   [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])];
186   [self appendAttributesToDescription:ms];
187   [ms appendString:@">"];
188   return ms;
189 }
190
191 @end /* iCalDateHolder */
192
193 @implementation NSTimeZone(iCalTimeZone)
194
195 static NSMutableDictionary *idToTz = nil; // THREAD
196
197 + (NSTimeZone *)timeZoneWithICalId:(NSString *)_tzid {
198   static NSString *iCalDefaultTZ = nil;
199   NSTimeZone *tz;
200   
201   if (idToTz == nil)
202     idToTz = [[NSMutableDictionary alloc] initWithCapacity:16];
203   
204   if ([_tzid length] == 0) {
205     
206     tz = [iCalObject iCalDefaultTimeZone];
207     if (tz != nil) return tz;
208
209     if (iCalDefaultTZ == nil) {
210       NSString *defTz;
211       NSUserDefaults *ud;
212       // TODO: take a default timeZone
213       ud = [NSUserDefaults standardUserDefaults];
214       defTz = [ud stringForKey:@"iCalTimeZoneName"];
215       if ([defTz length] == 0)
216         defTz = [ud stringForKey:@"TimeZoneName"];
217       if ([defTz length] == 0)
218         defTz = [ud stringForKey:@"TimeZone"];
219       if ([defTz length] == 0)
220         defTz = @"GMT";
221       iCalDefaultTZ = [defTz retain];
222     }
223     
224     _tzid = iCalDefaultTZ;
225     
226   }
227   
228   if ([_tzid length] == 0)
229     _tzid = @"GMT";
230   
231   tz = [idToTz objectForKey:_tzid];
232   if (tz == nil) tz = [NSTimeZone timeZoneWithName:_tzid];
233   if (tz == nil) tz = [NSTimeZone timeZoneWithAbbreviation:_tzid];
234   
235   if (tz == nil) {
236     NSLog(@"couldn't map timezone id %@", _tzid);
237   }
238   
239   if (tz) [idToTz setObject:tz forKey:_tzid];
240   return tz;
241 }
242
243 @end /* NSTimeZone(iCalTimeZone) */