2 NSCalendarDate+MySQL4Val.m
4 Copyright (C) 2003-2005 SKYRIX Software AG
6 Author: Helge Hess (helge.hess@skyrix.com)
8 This file is part of the MySQL4 Adaptor Library
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Library General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
20 You should have received a copy of the GNU Library General Public
21 License along with this library; see the file COPYING.LIB.
22 If not, write to the Free Software Foundation,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #import <Foundation/NSString.h>
28 #include "MySQL4Channel.h"
31 #if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY
32 @interface NSCalendarDate(UsedPrivates)
33 - (id)initWithTimeIntervalSince1970:(NSTimeInterval)_tv;
37 static NSString *SQLITE3_DATETIME_FORMAT = @"%b %d %Y %I:%M:%S:000%p";
39 @implementation NSCalendarDate(MySQL4Values)
42 Format: '2001-07-26 14:00:00+02'
43 '2001-07-26 14:00:00+09:30'
44 0123456789012345678901234
46 Matthew: "07/25/2003 06:00:00 CDT".
49 static Class NSCalDateClass = Nil;
50 static NSTimeZone *DefServerTimezone = nil;
51 static NSTimeZone *gmt = nil;
52 static NSTimeZone *gmt01 = nil;
53 static NSTimeZone *gmt02 = nil;
55 - (id)initWithMySQL4Data:(const void *)_value length:(int)_length {
56 static unsigned char buf[28]; // reused buffer, THREAD
57 const char *_cstr = _value;
61 int year, month, day, hour, min, sec, tzOffset;
66 if (_length != 22 && _length != 25) {
67 NSLog(@"ERROR(%s): unexpected date string '%s', returning now"
68 @" (expected format: '2001-07-26 14:00:00+02')",
69 __PRETTY_FUNCTION__, _cstr);
70 return [NSCalendarDate date];
72 strncpy(buf, _cstr, 25);
75 /* perform on reverse, so that we don't overwrite with null-terminators */
79 tzOffset = atoi(p) * 60;
81 else if (_length >= 25) {
85 buf[22] = '\0'; // the ':'
87 tzOffset = atoi(p) * 60;
88 tzOffset = tzOffset > 0 ? (tzOffset + mins) : (tzOffset - mins);
91 p = &(buf[17]); buf[19] = '\0'; sec = atoi(p);
92 p = &(buf[14]); buf[16] = '\0'; min = atoi(p);
93 p = &(buf[11]); buf[13] = '\0'; hour = atoi(p);
94 p = &(buf[8]); buf[10] = '\0'; day = atoi(p);
95 p = &(buf[5]); buf[7] = '\0'; month = atoi(p);
96 p = &(buf[0]); buf[4] = '\0'; year = atoi(p);
98 /* TODO: cache all timezones (just 26 ;-) */
102 gmt = [[NSTimeZone timeZoneForSecondsFromGMT:0] retain];
103 NSAssert(gmt, @"could not create GMT timezone?!");
109 gmt01 = [[NSTimeZone timeZoneForSecondsFromGMT:3600] retain];
110 NSAssert(gmt01, @"could not create GMT+01 timezone?!");
116 gmt02 = [[NSTimeZone timeZoneForSecondsFromGMT:7200] retain];
117 NSAssert(gmt02, @"could not create GMT+02 timezone?!");
123 /* cache the first, "alternative" timezone */
124 static int firstTZOffset = 0; // can use 0 since GMT is a separate case
125 static NSTimeZone *firstTZ = nil;
126 if (firstTZOffset == 0) {
127 firstTZOffset = tzOffset;
128 firstTZ = [[NSTimeZone timeZoneForSecondsFromGMT:(tzOffset*60)] retain];
131 attrTZ = (firstTZOffset == tzOffset)
133 : [NSTimeZone timeZoneForSecondsFromGMT:(tzOffset * 60)];
138 if (NSCalDateClass == Nil) NSCalDateClass = [NSCalendarDate class];
139 date = [NSCalDateClass dateWithYear:year month:month day:day
140 hour:hour minute:min second:sec
143 NSLog(@"ERROR(%s): could not construct date from string '%s': "
144 @"year=%i,month=%i,day=%i,hour=%i,minute=%i,second=%i, tz=%@",
145 __PRETTY_FUNCTION__, _cstr,
146 year, month, day, hour, min, sec, attrTZ);
151 - (id)initWithMySQL4Double:(double)_value {
152 return [self initWithTimeIntervalSince1970:_value];
154 - (id)initWithMySQL4Int:(int)_value {
155 return [self initWithMySQL4Double:_value];
158 - (id)initWithMySQL4Text:(const unsigned char *)_value {
159 return [self initWithMySQL4Data:_value length:strlen(_value)];
162 /* generating value */
164 - (NSString *)stringValueForMySQL4Type:(NSString *)_type
165 attribute:(EOAttribute *)_attribute
170 EOQuotedExpression *expr;
171 NSTimeZone *serverTimeZone;
177 if ((len = [_type length]) == 0)
180 c1 = [_type characterAtIndex:0];
182 if (c1 == 'i' || c1 == 'I') { // INTEGER
184 sprintf(buf, "%d", ((unsigned int)[self timeIntervalSince1970]));
185 return [NSString stringWithCString:buf];
187 if (c1 == 'r' || c1 == 'R') { // REAL
188 char buf[64]; // TODO: check format
189 sprintf(buf, "%f", [self timeIntervalSince1970]);
190 return [NSString stringWithCString:buf];
193 if ((serverTimeZone = [_attribute serverTimeZone]) == nil ) {
194 if (DefServerTimezone == nil) {
195 DefServerTimezone = [[NSTimeZone localTimeZone] retain];
196 NSLog(@"Note: MySQL4 adaptor using timezone '%@' as default",
199 serverTimeZone = DefServerTimezone;
203 format = [_attribute calendarFormat];
204 #else /* hm, why is that? */
205 format = @"%Y-%m-%d %H:%M:%S%z";
208 format = SQLITE3_DATETIME_FORMAT;
210 [self setTimeZone:serverTimeZone];
212 val = [self descriptionWithCalendarFormat:format];
213 expr = [[EOQuotedExpression alloc] initWithExpression:val
214 quote:@"\'" escape:@"\\'"];
215 val = [[expr expressionValueForContext:nil] retain];
218 return [val autorelease];
221 @end /* NSCalendarDate(MySQL4Values) */