]> err.no Git - scalable-opengroupware.org/blob - SOPE/NGCards/iCalDateHolder.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1178 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[16];
134     [s getCString:&(buf[0])];
135     
136     buf[9] = '\0';
137     day    = atoi(&(buf[6]));  buf[6] = '\0';
138     month  = atoi(&(buf[4]));  buf[4] = '\0';
139     year   = atoi(&(buf[0]));
140     
141     date = [NSCalendarDate dateWithYear:year month:month day:day
142                            hour:0 minute:0 second:0
143                            timeZone:tz];
144   }
145   else if ([s length] == 15) {
146     int year, month, day, hour, minute, second;
147     char buf[24];
148     [s getCString:&(buf[0])];
149       
150     second = atoi(&(buf[13])); buf[13] = '\0';
151     minute = atoi(&(buf[11])); buf[11] = '\0';
152     hour   = atoi(&(buf[9]));  buf[9] = '\0';
153     day    = atoi(&(buf[6]));  buf[6] = '\0';
154     month  = atoi(&(buf[4]));  buf[4] = '\0';
155     year   = atoi(&(buf[0]));
156       
157     date = [NSCalendarDate dateWithYear:year month:month day:day
158                            hour:hour minute:minute second:second
159                            timeZone:tz];
160   }
161   else
162     NSLog(@"%s: unknown date format (%@) ???", __PRETTY_FUNCTION__, s);
163     
164   if (date == nil)
165     NSLog(@"couldn't convert string '%@' to date (format '%@') ..", s);
166
167   return date;
168 }
169
170 /* description */
171
172 - (void)appendAttributesToDescription:(NSMutableString *)ms {
173   if (self->tag)    [ms appendFormat:@" %@",  self->tag];
174   if (self->string) [ms appendFormat:@" '%@'",  self->string];
175   if (self->tzid)   [ms appendFormat:@" tz=%@", self->tzid];
176 }
177
178 - (NSString *)description {
179   NSMutableString *ms;
180
181   ms = [NSMutableString stringWithCapacity:128];
182   [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])];
183   [self appendAttributesToDescription:ms];
184   [ms appendString:@">"];
185   return ms;
186 }
187
188 @end /* iCalDateHolder */
189
190 @implementation NSTimeZone(iCalTimeZone)
191
192 static NSMutableDictionary *idToTz = nil; // THREAD
193
194 + (NSTimeZone *)timeZoneWithICalId:(NSString *)_tzid {
195   static NSString *iCalDefaultTZ = nil;
196   NSTimeZone *tz;
197   
198   if (idToTz == nil)
199     idToTz = [[NSMutableDictionary alloc] initWithCapacity:16];
200   
201   if ([_tzid length] == 0) {
202     
203     tz = [iCalObject iCalDefaultTimeZone];
204     if (tz != nil) return tz;
205
206     if (iCalDefaultTZ == nil) {
207       NSString *defTz;
208       NSUserDefaults *ud;
209       // TODO: take a default timeZone
210       ud = [NSUserDefaults standardUserDefaults];
211       defTz = [ud stringForKey:@"iCalTimeZoneName"];
212       if ([defTz length] == 0)
213         defTz = [ud stringForKey:@"TimeZoneName"];
214       if ([defTz length] == 0)
215         defTz = [ud stringForKey:@"TimeZone"];
216       if ([defTz length] == 0)
217         defTz = @"GMT";
218       iCalDefaultTZ = [defTz retain];
219     }
220     
221     _tzid = iCalDefaultTZ;
222     
223   }
224   
225   if ([_tzid length] == 0)
226     _tzid = @"GMT";
227   
228   tz = [idToTz objectForKey:_tzid];
229   if (tz == nil) tz = [NSTimeZone timeZoneWithName:_tzid];
230   if (tz == nil) tz = [NSTimeZone timeZoneWithAbbreviation:_tzid];
231   
232   if (tz == nil) {
233     NSLog(@"couldn't map timezone id %@", _tzid);
234   }
235   
236   if (tz) [idToTz setObject:tz forKey:_tzid];
237   return tz;
238 }
239
240 @end /* NSTimeZone(iCalTimeZone) */