Skip to content
This repository has been archived by the owner on Jun 24, 2022. It is now read-only.

Commit

Permalink
Fix strptime for %Y%m%d and similar formats (Fixes #9)
Browse files Browse the repository at this point in the history
Previously, strptime grabbed an arbitrary number of digits for the
%Y and %G formats.  Now it operates like the standard library,
checking to see if %Y or %G is followed by a numeric literal or
format, and restricting the number of digits to 4 if so.
  • Loading branch information
jeremyevans committed Aug 31, 2010
1 parent 9ac21b1 commit 44ef76e
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 2 deletions.
20 changes: 18 additions & 2 deletions ext/date_ext/date_ext.c
@@ -1,3 +1,4 @@
#include <ctype.h>
#include "date_ext.h"

const unsigned char rhrd_days_in_month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
Expand All @@ -11,6 +12,7 @@ const char * rhrd__abbr_day_names[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri"
const char rhrd__zone_re_str[] = "\\A(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?|[[:alpha:].\\s]+(?:standard|daylight)\\s+time\\b|[[:alpha:]]+(?:\\s+dst)?\\b";
const char rhrd__zone_dst_re_str[] = "\\s+(?:(?:(standard)|daylight)\\s+time|dst)\\z";
const char rhrd__zone_sign_re_str[] = "\\A(?:gmt|utc?)?(?:(-)|\\+)";
const char rhrd__strptime_num_patterns[] = "CDdeFGgHIjkLlMmNQRrSsTUuVvWwXxYy0123456789";

VALUE rhrd_class;
VALUE rhrd_s_class;
Expand Down Expand Up @@ -934,6 +936,7 @@ VALUE rhrd__strptime(VALUE rstr, const char *fmt_str, long fmt_len) {
long wnum1 = 0;
long i;
long fmt_pos;
int year_only4 = 0;
int scan_len;
VALUE zone = Qnil;
VALUE hash;
Expand Down Expand Up @@ -1043,7 +1046,16 @@ VALUE rhrd__strptime(VALUE rstr, const char *fmt_str, long fmt_len) {
state |= RHRR_CWYEAR_SET | RHRR_CENTURY_SET;
break;
case 'G':
if (sscanf(str + pos, "%ld%n", &cwyear, &scan_len) != 1) {
#define RHR_PARSE_year_only4 year_only4 = 0;\
if (fmt_pos + 1 < fmt_len) {\
if(isdigit(fmt_str[fmt_pos + 1])) {\
year_only4 = 1;\
} else if ((fmt_pos + 2 < fmt_len) && (fmt_str[fmt_pos + 1] == '%') && strchr(rhrd__strptime_num_patterns, fmt_str[fmt_pos + 2])) {\
year_only4 = 1;\
}\
}
RHR_PARSE_year_only4
if (sscanf(str + pos, year_only4 ? "%4ld%n" : "%ld%n", &cwyear, &scan_len) != 1) {
return Qnil;
}
state |= RHRR_CWYEAR_SET + RHRR_CENTURY_SET;
Expand Down Expand Up @@ -1228,10 +1240,11 @@ VALUE rhrd__strptime(VALUE rstr, const char *fmt_str, long fmt_len) {
RHR_PARSE_y
break;
case 'Y':
#define RHR_PARSE_Y if (sscanf(str + pos, "%ld%n", &year, &scan_len) != 1) {\
#define RHR_PARSE_Y if (sscanf(str + pos, year_only4 ? "%4ld%n" : "%ld%n", &year, &scan_len) != 1) {\
return Qnil;\
}\
state |= RHRR_YEAR_SET + RHRR_CENTURY_SET;
RHR_PARSE_year_only4
RHR_PARSE_Y
break;
case 'z':
Expand Down Expand Up @@ -1265,6 +1278,7 @@ VALUE rhrd__strptime(VALUE rstr, const char *fmt_str, long fmt_len) {
RHR_PARSE_sep(':')
RHR_PARSE_S
RHR_PARSE_sep(' ')
RHR_PARSE_year_only4
RHR_PARSE_Y
break;
case 'x':
Expand Down Expand Up @@ -1309,6 +1323,7 @@ VALUE rhrd__strptime(VALUE rstr, const char *fmt_str, long fmt_len) {
RHR_PARSE_sep('-')
RHR_PARSE_b
RHR_PARSE_sep('-')
RHR_PARSE_year_only4
RHR_PARSE_Y
break;
case '+':
Expand All @@ -1326,6 +1341,7 @@ VALUE rhrd__strptime(VALUE rstr, const char *fmt_str, long fmt_len) {
RHR_PARSE_sep(' ')
RHR_PARSE_Z
RHR_PARSE_sep(' ')
RHR_PARSE_year_only4
RHR_PARSE_Y
break;
default:
Expand Down
1 change: 1 addition & 0 deletions ext/date_ext/date_ext.h
Expand Up @@ -5,6 +5,7 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <ruby.h>

Expand Down

0 comments on commit 44ef76e

Please sign in to comment.