ext/result.cc in swift-0.8.0 vs ext/result.cc in swift-0.8.1
- old
+ new
@@ -136,36 +136,55 @@
return offset;
}
VALUE typecast_timestamp(const char *data, uint64_t len, const char *zone) {
struct tm tm;
- int64_t epoch, adjust, offset;
uint64_t usec = 0;
+ int64_t epoch, adjust, offset;
char tzsign = 0, subsec[32];
- int tzhour = 0, tzmin = 0;
+ int tzhour = 0, tzmin = 0, lastmatch = -1;
memset(&tm, 0, sizeof(struct tm));
- // Based on github.com/jeremyevans/sequel_pg. atoll & pow seem to be tad faster than sscanf %Lf
- // NOTE: Reading subsec as string means malformed subsec > 32 digits could break this.
- if (strchr(data, '.')) {
- sscanf(data, "%04d-%02d-%02d %02d:%02d:%02d.%s%c%02d:%02d",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, subsec,
- &tzsign, &tzhour, &tzmin);
- usec = atoll(subsec)*(uint64_t)pow(10, 6 - strlen(subsec));
+ sscanf(data, "%04d-%02d-%02d %02d:%02d:%02d%n",
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &lastmatch);
+
+ // parse millisecs if any
+ if (lastmatch > 0 && lastmatch < len && *(data+lastmatch) == '.') {
+ lastmatch++;
+ int idx = 0;
+ const char *ptr = data + lastmatch;
+ while (*ptr && *ptr >= '0' && *ptr <= '9' && idx < 31) {
+ subsec[idx++] = *ptr;
+ ptr++;
+ lastmatch++;
+ }
+ subsec[idx] = 0;
+ usec = atoll(subsec);
}
- else {
- sscanf(data, "%04d-%02d-%02d %02d:%02d:%02d%c%02d:%02d",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec,
- &tzsign, &tzhour, &tzmin);
- }
tm.tm_year -= 1900;
tm.tm_mon -= 1;
tm.tm_isdst = -1;
if (tm.tm_mday > 0) {
epoch = mktime(&tm);
adjust = client_tzoffset(epoch, tm.tm_isdst);
offset = adjust;
+
+ // parse timezone offsets if any - matches +HH:MM +HH MM +HHMM
+ if (lastmatch > 0 && lastmatch < len) {
+ const char *ptr = data + lastmatch;
+ while(*ptr && *ptr != '+' && *ptr != '-') ptr++;
+ tzsign = *ptr++;
+ if (*ptr && *ptr >= '0' && *ptr <= '9') {
+ tzhour = *ptr++ - '0';
+ if (*ptr && *ptr >= '0' && *ptr <= '9') tzhour = tzhour*10 + *ptr++ - '0';
+ while(*ptr && (*ptr < '0' || *ptr > '9')) ptr++;
+ if (*ptr && *ptr >= '0' && *ptr <= '9') {
+ tzmin = *ptr++ - '0';
+ if (*ptr && *ptr >= '0' && *ptr <= '9') tzmin = tzmin*10 + *ptr++ - '0';
+ }
+ }
+ }
if (tzsign) {
offset = tzsign == '+'
? (time_t)tzhour * 3600 + (time_t)tzmin * 60
: (time_t)tzhour * -3600 + (time_t)tzmin * -60;