Fix timestamps without timezone to use local time zone

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@36655 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2013-05-24 14:20:29 +00:00
parent 5b64b5c3bf
commit 0469ba48fb
3 changed files with 431 additions and 296 deletions

121
ECPG.pgm
View file

@ -946,9 +946,13 @@ static unsigned int trim(char *str)
- (NSDate*) dbToDateFromBuffer: (char*)b length: (int)l - (NSDate*) dbToDateFromBuffer: (char*)b length: (int)l
{ {
char buf[l+32]; /* Allow space to expend buffer. */ char buf[l+32]; /* Allow space to expand buffer. */
NSCalendarDate *d;
BOOL milliseconds = NO;
BOOL timezone = NO;
NSString *s; NSString *s;
int i; int i;
int e;
memcpy(buf, b, l); memcpy(buf, b, l);
b = buf; b = buf;
@ -971,14 +975,23 @@ static unsigned int trim(char *str)
if (l == 10) if (l == 10)
{ {
s = [self dbToStringFromBuffer: b length: l]; s = [NSString stringWithUTF8String: b];
return [NSCalendarDate dateWithString: s return [NSCalendarDate dateWithString: s
calendarFormat: @"%Y-%m-%d" calendarFormat: @"%Y-%m-%d"
locale: nil]; locale: nil];
} }
else
{
i = l; i = l;
/* Convert +/-HH:SS timezone to +/-HHSS
*/
if (i > 5 && b[i-3] == ':' && (b[i-6] == '+' || b[i-6] == '-'))
{
b[i-3] = b[i-2];
b[i-2] = b[i-1];
b[--i] = '\0';
}
while (i-- > 0) while (i-- > 0)
{ {
if (b[i] == '+' || b[i] == '-') if (b[i] == '+' || b[i] == '-')
@ -991,10 +1004,15 @@ static unsigned int trim(char *str)
break; /* No time zone found */ break; /* No time zone found */
} }
} }
if (i > 0)
{
int e = i;
if (i == 0)
{
e = l;
}
else
{
timezone = YES;
e = i;
if (isdigit(b[i-1])) if (isdigit(b[i-1]))
{ {
/* /*
@ -1005,64 +1023,105 @@ static unsigned int trim(char *str)
b[++l] = '\0'; b[++l] = '\0';
} }
/*
* Ensure we have a four digit timezone value.
*/
if (isdigit(b[i+1]) && isdigit(b[i+2])) if (isdigit(b[i+1]) && isdigit(b[i+2]))
{ {
if (b[i+3] == '\0') if (b[i+3] == '\0')
{ {
// Two digit time zone // Two digit time zone ... append zero minutes
b[l++] = '0'; b[l++] = '0';
b[l++] = '0'; b[l++] = '0';
b[l] = '\0'; b[l] = '\0';
} }
else if (b[i+3] == ':') else if (b[i+3] == ':')
{ {
// Zone with colon before minutes // Zone with colon before minutes ... remove it
b[i+3] = b[i+4]; b[i+3] = b[i+4];
b[i+5] = b[i+5]; b[i+4] = b[i+5];
b[--l] = '\0'; b[--l] = '\0';
} }
} }
}
/* FIXME ... horrible kludge for postgres returning timestamps with /* kludge for timestamps with fractional second information.
fractional second information. */ * Force it to 3 digit millisecond */
while (i-- > 0) while (i-- > 0)
{ {
if (b[i] == '.') if (b[i] == '.')
{ {
milliseconds = YES;
i++;
if (!isdigit(b[i]))
{
memmove(&b[i+3], &b[i], e-i);
l += 3;
memcpy(&b[i], "000", 3);
}
i++;
if (!isdigit(b[i]))
{
memmove(&b[i+2], &b[i], e-i);
l += 2;
memcpy(&b[i], "00", 2);
}
i++;
if (!isdigit(b[i]))
{
memmove(&b[i+1], &b[i], e-i);
l += 1;
memcpy(&b[i], "0", 1);
}
i++;
break; break;
} }
} }
if (i > 0) if (i > 0 && i < e)
{ {
memmove(&b[i], &b[e], l - e); memmove(&b[i], &b[e], l - e);
l -= (e - i); l -= (e - i);
}
b[l] = '\0'; b[l] = '\0';
}
}
else if (l == 19)
{
/* A date and time without a timezone ... assume gmt */
strcat(b, " +0000");
l += 6;
}
/* If it's a simple date (YYYY-MM-DD) append time for start of day. */
if (l == 10)
{
strcat(b, " 00:00:00 +0000");
l += 15;
}
if (l == 0) if (l == 0)
{ {
return nil; return nil;
} }
s = [self dbToStringFromBuffer: b length: l]; s = [NSString stringWithUTF8String: b];
return [NSCalendarDate dateWithString: s
if (YES == timezone)
{
if (milliseconds == YES)
{
d = [NSCalendarDate dateWithString: s
calendarFormat: @"%Y-%m-%d %H:%M:%S.%F %z"
locale: nil];
}
else
{
d = [NSCalendarDate dateWithString: s
calendarFormat: @"%Y-%m-%d %H:%M:%S %z" calendarFormat: @"%Y-%m-%d %H:%M:%S %z"
locale: nil]; locale: nil];
} }
}
else
{
if (milliseconds == YES)
{
d = [NSCalendarDate dateWithString: s
calendarFormat: @"%Y-%m-%d %H:%M:%S.%F"
locale: nil];
}
else
{
d = [NSCalendarDate dateWithString: s
calendarFormat: @"%Y-%m-%d %H:%M:%S"
locale: nil];
}
}
[d setCalendarFormat: @"%Y-%m-%d %H:%M:%S %z"];
return d;
} }
- (NSString*) dbToStringFromBuffer: (char*)b length: (int)l - (NSString*) dbToStringFromBuffer: (char*)b length: (int)l

124
Oracle.pm
View file

@ -899,14 +899,15 @@ static unsigned int trim(char *str)
return ok; return ok;
} }
/**
* Convert from a database character buffer to an NSDate.
*/
- (NSDate*) dbToDateFromBuffer: (char*)b length: (int)l - (NSDate*) dbToDateFromBuffer: (char*)b length: (int)l
{ {
char buf[l+32]; /* Allow space to expend buffer. */ char buf[l+32]; /* Allow space to expand buffer. */
NSCalendarDate *d;
BOOL milliseconds = NO;
BOOL timezone = NO;
NSString *s; NSString *s;
int i; int i;
int e;
memcpy(buf, b, l); memcpy(buf, b, l);
b = buf; b = buf;
@ -929,14 +930,23 @@ static unsigned int trim(char *str)
if (l == 10) if (l == 10)
{ {
s = [self dbToStringFromBuffer: b length: l]; s = [NSString stringWithUTF8String: b];
return [NSCalendarDate dateWithString: s return [NSCalendarDate dateWithString: s
calendarFormat: @"%Y-%m-%d" calendarFormat: @"%Y-%m-%d"
locale: nil]; locale: nil];
} }
else
{
i = l; i = l;
/* Convert +/-HH:SS timezone to +/-HHSS
*/
if (i > 5 && b[i-3] == ':' && (b[i-6] == '+' || b[i-6] == '-'))
{
b[i-3] = b[i-2];
b[i-2] = b[i-1];
b[--i] = '\0';
}
while (i-- > 0) while (i-- > 0)
{ {
if (b[i] == '+' || b[i] == '-') if (b[i] == '+' || b[i] == '-')
@ -949,10 +959,15 @@ static unsigned int trim(char *str)
break; /* No time zone found */ break; /* No time zone found */
} }
} }
if (i > 0)
{
int e = i;
if (i == 0)
{
e = l;
}
else
{
timezone = YES;
e = i;
if (isdigit(b[i-1])) if (isdigit(b[i-1]))
{ {
/* /*
@ -963,64 +978,105 @@ static unsigned int trim(char *str)
b[++l] = '\0'; b[++l] = '\0';
} }
/*
* Ensure we have a four digit timezone value.
*/
if (isdigit(b[i+1]) && isdigit(b[i+2])) if (isdigit(b[i+1]) && isdigit(b[i+2]))
{ {
if (b[i+3] == '\0') if (b[i+3] == '\0')
{ {
// Two digit time zone // Two digit time zone ... append zero minutes
b[l++] = '0'; b[l++] = '0';
b[l++] = '0'; b[l++] = '0';
b[l] = '\0'; b[l] = '\0';
} }
else if (b[i+3] == ':') else if (b[i+3] == ':')
{ {
// Zone with colon before minutes // Zone with colon before minutes ... remove it
b[i+3] = b[i+4]; b[i+3] = b[i+4];
b[i+5] = b[i+5]; b[i+4] = b[i+5];
b[--l] = '\0'; b[--l] = '\0';
} }
} }
}
/* FIXME ... horrible kludge for postgres returning timestamps with /* kludge for timestamps with fractional second information.
fractional second information. */ * Force it to 3 digit millisecond */
while (i-- > 0) while (i-- > 0)
{ {
if (b[i] == '.') if (b[i] == '.')
{ {
milliseconds = YES;
i++;
if (!isdigit(b[i]))
{
memmove(&b[i+3], &b[i], e-i);
l += 3;
memcpy(&b[i], "000", 3);
}
i++;
if (!isdigit(b[i]))
{
memmove(&b[i+2], &b[i], e-i);
l += 2;
memcpy(&b[i], "00", 2);
}
i++;
if (!isdigit(b[i]))
{
memmove(&b[i+1], &b[i], e-i);
l += 1;
memcpy(&b[i], "0", 1);
}
i++;
break; break;
} }
} }
if (i > 0) if (i > 0 && i < e)
{ {
memmove(&b[i], &b[e], l - e); memmove(&b[i], &b[e], l - e);
l -= (e - i); l -= (e - i);
}
b[l] = '\0'; b[l] = '\0';
}
}
else if (l == 19)
{
/* A date and time without a timezone ... assume gmt */
strcat(b, " +0000");
l += 6;
}
/* If it's a simple date (YYYY-MM-DD) append time for start of day. */
if (l == 10)
{
strcat(b, " 00:00:00 +0000");
l += 15;
}
if (l == 0) if (l == 0)
{ {
return nil; return nil;
} }
s = [self dbToStringFromBuffer: b length: l]; s = [NSString stringWithUTF8String: b];
return [NSCalendarDate dateWithString: s
if (YES == timezone)
{
if (milliseconds == YES)
{
d = [NSCalendarDate dateWithString: s
calendarFormat: @"%Y-%m-%d %H:%M:%S.%F %z"
locale: nil];
}
else
{
d = [NSCalendarDate dateWithString: s
calendarFormat: @"%Y-%m-%d %H:%M:%S %z" calendarFormat: @"%Y-%m-%d %H:%M:%S %z"
locale: nil]; locale: nil];
} }
}
else
{
if (milliseconds == YES)
{
d = [NSCalendarDate dateWithString: s
calendarFormat: @"%Y-%m-%d %H:%M:%S.%F"
locale: nil];
}
else
{
d = [NSCalendarDate dateWithString: s
calendarFormat: @"%Y-%m-%d %H:%M:%S"
locale: nil];
}
}
[d setCalendarFormat: @"%Y-%m-%d %H:%M:%S %z"];
return d;
} }
/** /**

View file

@ -836,10 +836,12 @@ static unsigned int trim(char *str)
- (NSDate*) dbToDateFromBuffer: (char*)b length: (int)l - (NSDate*) dbToDateFromBuffer: (char*)b length: (int)l
{ {
char buf[l+32]; /* Allow space to expand buffer. */ char buf[l+32]; /* Allow space to expand buffer. */
NSDate *d; NSCalendarDate *d;
BOOL milliseconds = NO; BOOL milliseconds = NO;
BOOL timezone = NO;
NSString *s; NSString *s;
int i; int i;
int e;
memcpy(buf, b, l); memcpy(buf, b, l);
b = buf; b = buf;
@ -867,11 +869,9 @@ static unsigned int trim(char *str)
calendarFormat: @"%Y-%m-%d" calendarFormat: @"%Y-%m-%d"
locale: nil]; locale: nil];
} }
else
{
int e;
i = l; i = l;
/* Convert +/-HH:SS timezone to +/-HHSS /* Convert +/-HH:SS timezone to +/-HHSS
*/ */
if (i > 5 && b[i-3] == ':' && (b[i-6] == '+' || b[i-6] == '-')) if (i > 5 && b[i-3] == ':' && (b[i-6] == '+' || b[i-6] == '-'))
@ -893,14 +893,14 @@ static unsigned int trim(char *str)
break; /* No time zone found */ break; /* No time zone found */
} }
} }
if (i == 0) if (i == 0)
{ {
/* A date and time without a timezone ... assume gmt */ e = l;
strcpy(b + l, " +0000");
i = l + 1;
l += 6;
} }
else
{
timezone = YES;
e = i; e = i;
if (isdigit(b[i-1])) if (isdigit(b[i-1]))
{ {
@ -932,9 +932,10 @@ static unsigned int trim(char *str)
b[--l] = '\0'; b[--l] = '\0';
} }
} }
}
/* FIXME ... horrible kludge for postgres returning timestamps with /* kludge for timestamps with fractional second information.
fractional second information. Force it to 3 digit millisecond */ * Force it to 3 digit millisecond */
while (i-- > 0) while (i-- > 0)
{ {
if (b[i] == '.') if (b[i] == '.')
@ -977,6 +978,9 @@ static unsigned int trim(char *str)
} }
s = [NSString stringWithUTF8String: b]; s = [NSString stringWithUTF8String: b];
if (YES == timezone)
{
if (milliseconds == YES) if (milliseconds == YES)
{ {
d = [NSCalendarDate dateWithString: s d = [NSCalendarDate dateWithString: s
@ -989,8 +993,24 @@ static unsigned int trim(char *str)
calendarFormat: @"%Y-%m-%d %H:%M:%S %z" calendarFormat: @"%Y-%m-%d %H:%M:%S %z"
locale: nil]; locale: nil];
} }
return d;
} }
else
{
if (milliseconds == YES)
{
d = [NSCalendarDate dateWithString: s
calendarFormat: @"%Y-%m-%d %H:%M:%S.%F"
locale: nil];
}
else
{
d = [NSCalendarDate dateWithString: s
calendarFormat: @"%Y-%m-%d %H:%M:%S"
locale: nil];
}
}
[d setCalendarFormat: @"%Y-%m-%d %H:%M:%S %z"];
return d;
} }
- (void) dealloc - (void) dealloc