about summary refs log tree commit diff
path: root/src/time
diff options
context:
space:
mode:
Diffstat (limited to 'src/time')
-rw-r--r--src/time/strptime.c66
1 files changed, 65 insertions, 1 deletions
diff --git a/src/time/strptime.c b/src/time/strptime.c
index c54a0d8c..b1147242 100644
--- a/src/time/strptime.c
+++ b/src/time/strptime.c
@@ -59,6 +59,22 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri
 			s = strptime(s, "%m/%d/%y", tm);
 			if (!s) return 0;
 			break;
+		case 'F':
+			/* Use temp buffer to implement the odd requirement
+			 * that entire field be width-limited but the year
+			 * subfield not itself be limited. */
+			i = 0;
+			char tmp[20];
+			if (*s == '-' || *s == '+') tmp[i++] = *s++;
+			while (*s=='0' && isdigit(s[1])) s++;
+			for (; *s && i<(size_t)w && i+1<sizeof tmp; i++) {
+				tmp[i] = *s++;
+			}
+			tmp[i] = 0;
+			char *p = strptime(tmp, "%12Y-%m-%d", tm);
+			if (!p) return 0;
+			s -= tmp+i-p;
+			break;
 		case 'H':
 			dest = &tm->tm_hour;
 			min = 0;
@@ -114,6 +130,13 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri
 			s = strptime(s, "%H:%M", tm);
 			if (!s) return 0;
 			break;
+		case 's':
+			/* Parse only. Effect on tm is unspecified
+			 * and presently no effect is implemented.. */
+			if (*s == '-') s++;
+			if (!isdigit(*s)) return 0;
+			while (isdigit(*s)) s++;
+			break;
 		case 'S':
 			dest = &tm->tm_sec;
 			min = 0;
@@ -125,11 +148,30 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri
 			break;
 		case 'U':
 		case 'W':
-			/* Throw away result, for now. (FIXME?) */
+			/* Throw away result of %U, %V, %W, %g, and %G. Effect
+			 * is unspecified and there is no clear right choice. */
 			dest = &dummy;
 			min = 0;
 			range = 54;
 			goto numeric_range;
+		case 'V':
+			dest = &dummy;
+			min = 1;
+			range = 53;
+			goto numeric_range;
+		case 'g':
+			dest = &dummy;
+			w = 2;
+			goto numeric_digits;
+		case 'G':
+			dest = &dummy;
+			if (w<0) w=4;
+			goto numeric_digits;
+		case 'u':
+			dest = &tm->tm_wday;
+			min = 1;
+			range = 7;
+			goto numeric_range;
 		case 'w':
 			dest = &tm->tm_wday;
 			min = 0;
@@ -154,6 +196,28 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri
 			adj = 1900;
 			want_century = 0;
 			goto numeric_digits;
+		case 'z':
+			if (*s == '+') neg = 0;
+			else if (*s == '-') neg = 1;
+			else return 0;
+			for (i=0; i<4; i++) if (!isdigit(s[1+i])) return 0;
+			tm->__tm_gmtoff = (s[1]-'0')*36000+(s[2]-'0')*3600
+				+ (s[3]-'0')*600 + (s[4]-'0')*60;
+			if (neg) tm->__tm_gmtoff = -tm->__tm_gmtoff;
+			s += 5;
+			break;
+		case 'Z':
+			if (!strncmp(s, tzname[0], len = strlen(tzname[0]))) {
+				tm->tm_isdst = 0;
+				s += len;
+			} else if (!strncmp(s, tzname[1], len=strlen(tzname[1]))) {
+				tm->tm_isdst = 1;
+				s += len;
+			} else {
+				/* FIXME: is this supposed to be an error? */
+				while ((*s|32)-'a' <= 'z'-'a') s++;
+			}
+			break;
 		case '%':
 			if (*s++ != '%') return 0;
 			break;