2
NSCalendarDate+SQLiteVal.m
4
Copyright (C) 2003-2005 SKYRIX Software AG
6
Author: Helge Hess (helge.hess@skyrix.com)
8
This file is part of the SQLite 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 "SQLiteChannel.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(SQLiteValues)
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)initWithSQLiteData:(const void *)_value length:(int)_length {
56
static 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)initWithSQLiteDouble:(double)_value {
152
return [self initWithTimeIntervalSince1970:_value];
154
- (id)initWithSQLiteInt:(int)_value {
155
return [self initWithSQLiteDouble:_value];
158
- (id)initWithSQLiteText:(const unsigned char *)_value {
159
return [self initWithSQLiteData:_value length:strlen((char *)_value)];
162
/* generating value */
164
- (NSString *)stringValueForSQLite3Type:(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: SQLite 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(SQLiteValues) */