Index: base/third_party/nspr/prtime.cc |
diff --git a/base/third_party/nspr/prtime.cc b/base/third_party/nspr/prtime.cc |
index 0c97bc16d8832c793da8269c01bc8d9350e1e404..2029660c6f7f36f9f2b00195c187991f5c6cfeb0 100644 |
--- a/base/third_party/nspr/prtime.cc |
+++ b/base/third_party/nspr/prtime.cc |
@@ -61,6 +61,8 @@ |
* 1. prtime.h |
* 2. prtypes.h |
* 3. prlong.h |
+ * |
+ * Unit tests are in base/time/pr_time_unittest.cc. |
*/ |
#include "base/logging.h" |
@@ -132,6 +134,8 @@ PR_ImplodeTime(const PRExplodedTime *exploded) |
// Adjust for time zone and dst. Convert from seconds to microseconds. |
result -= (exploded->tm_params.tp_gmt_offset + |
exploded->tm_params.tp_dst_offset) * kSecondsToMicroseconds; |
+ // Add microseconds that cannot be represented in |st|. |
+ result += exploded->tm_usec % 1000; |
return result; |
#elif defined(OS_MACOSX) |
// Create the system struct representing our exploded time. |
@@ -505,6 +509,7 @@ typedef enum |
* 06/21/95 04:24:34 PM |
* 20/06/95 21:07 |
* 95-06-08 19:32:48 EDT |
+ * 1995-06-17T23:11:25.342156Z |
* |
* If the input string doesn't contain a description of the timezone, |
* we consult the `default_to_gmt' to decide whether the string should |
@@ -531,6 +536,7 @@ PR_ParseTimeString( |
int hour = -1; |
int min = -1; |
int sec = -1; |
+ int usec = -1; |
const char *rest = string; |
@@ -774,6 +780,7 @@ PR_ParseTimeString( |
int tmp_hour = -1; |
int tmp_min = -1; |
int tmp_sec = -1; |
+ int tmp_usec = -1; |
const char *end = rest + 1; |
while (*end >= '0' && *end <= '9') |
end++; |
@@ -833,14 +840,38 @@ PR_ParseTimeString( |
else |
tmp_sec = (rest[0]-'0'); |
- /* If we made it here, we've parsed hour and min, |
- and possibly sec, so it worked as a unit. */ |
+ /* fractional second */ |
+ rest = end; |
+ if (*rest == '.') |
+ { |
+ rest++; |
+ end++; |
+ tmp_usec = 0; |
+ /* use up to 6 digits, skip over the rest */ |
+ while (*end >= '0' && *end <= '9') |
+ { |
+ if (end - rest < 6) |
+ tmp_usec = tmp_usec * 10 + *end - '0'; |
+ end++; |
+ } |
+ int ndigits = end - rest; |
+ while (ndigits++ < 6) |
+ tmp_usec *= 10; |
+ rest = end; |
+ } |
- /* skip over whitespace and see if there's an AM or PM |
- directly following the time. |
- */ |
- if (tmp_hour <= 12) |
+ if (*rest == 'Z') |
{ |
+ zone = TT_GMT; |
+ rest++; |
+ } |
+ else if (tmp_hour <= 12) |
+ { |
+ /* If we made it here, we've parsed hour and min, |
+ and possibly sec, so the current token is a time. |
+ Now skip over whitespace and see if there's an AM |
+ or PM directly following the time. |
+ */ |
const char *s = end; |
while (*s && (*s == ' ' || *s == '\t')) |
s++; |
@@ -858,6 +889,7 @@ PR_ParseTimeString( |
hour = tmp_hour; |
min = tmp_min; |
sec = tmp_sec; |
+ usec = tmp_usec; |
rest = end; |
break; |
} |
@@ -865,8 +897,7 @@ PR_ParseTimeString( |
end[1] >= '0' && end[1] <= '9') |
{ |
/* Perhaps this is 6/16/95, 16/6/95, 6-16-95, or 16-6-95 |
- or even 95-06-05... |
- #### But it doesn't handle 1995-06-22. |
+ or even 95-06-05 or 1995-06-22. |
*/ |
int n1, n2, n3; |
const char *s; |
@@ -877,9 +908,19 @@ PR_ParseTimeString( |
s = rest; |
- n1 = (*s++ - '0'); /* first 1 or 2 digits */ |
+ n1 = (*s++ - '0'); /* first 1, 2 or 4 digits */ |
if (*s >= '0' && *s <= '9') |
- n1 = n1*10 + (*s++ - '0'); |
+ { |
+ n1 = n1*10 + (*s++ - '0'); |
+ |
+ if (*s >= '0' && *s <= '9') /* optional digits 3 and 4 */ |
+ { |
+ n1 = n1*10 + (*s++ - '0'); |
+ if (*s < '0' || *s > '9') |
+ break; |
+ n1 = n1*10 + (*s++ - '0'); |
+ } |
+ } |
if (*s != '/' && *s != '-') /* slash */ |
break; |
@@ -911,17 +952,21 @@ PR_ParseTimeString( |
n3 = n3*10 + (*s++ - '0'); |
} |
- if ((*s >= '0' && *s <= '9') || /* followed by non-alphanum */ |
- (*s >= 'A' && *s <= 'Z') || |
- (*s >= 'a' && *s <= 'z')) |
+ if (*s == 'T' && s[1] >= '0' && s[1] <= '9') |
+ /* followed by ISO 8601 T delimiter and number is ok */ |
+ ; |
+ else if ((*s >= '0' && *s <= '9') || |
+ (*s >= 'A' && *s <= 'Z') || |
+ (*s >= 'a' && *s <= 'z')) |
+ /* but other alphanumerics are not ok */ |
break; |
- /* Ok, we parsed three 1-2 digit numbers, with / or - |
+ /* Ok, we parsed three multi-digit numbers, with / or - |
between them. Now decide what the hell they are |
- (DD/MM/YY or MM/DD/YY or YY/MM/DD.) |
+ (DD/MM/YY or MM/DD/YY or [YY]YY/MM/DD.) |
*/ |
- if (n1 > 31 || n1 == 0) /* must be YY/MM/DD */ |
+ if (n1 > 31 || n1 == 0) /* must be [YY]YY/MM/DD */ |
{ |
if (n2 > 12) break; |
if (n3 > 31) break; |
@@ -1014,26 +1059,27 @@ PR_ParseTimeString( |
/* else, three or more than five digits - what's that? */ |
break; |
- } |
- } |
+ } /* case '0' .. '9' */ |
+ } /* switch */ |
/* Skip to the end of this token, whether we parsed it or not. |
- Tokens are delimited by whitespace, or ,;-/ |
- But explicitly not :+-. |
+ Tokens are delimited by whitespace, or ,;-+/()[] but explicitly not .: |
+ 'T' is also treated as delimiter when followed by a digit (ISO 8601). |
*/ |
while (*rest && |
*rest != ' ' && *rest != '\t' && |
*rest != ',' && *rest != ';' && |
*rest != '-' && *rest != '+' && |
*rest != '/' && |
- *rest != '(' && *rest != ')' && *rest != '[' && *rest != ']') |
+ *rest != '(' && *rest != ')' && *rest != '[' && *rest != ']' && |
+ !(*rest == 'T' && rest[1] >= '0' && rest[1] <= '9') |
+ ) |
rest++; |
/* skip over uninteresting chars. */ |
SKIP_MORE: |
- while (*rest && |
- (*rest == ' ' || *rest == '\t' || |
- *rest == ',' || *rest == ';' || *rest == '/' || |
- *rest == '(' || *rest == ')' || *rest == '[' || *rest == ']')) |
+ while (*rest == ' ' || *rest == '\t' || |
+ *rest == ',' || *rest == ';' || *rest == '/' || |
+ *rest == '(' || *rest == ')' || *rest == '[' || *rest == ']') |
rest++; |
/* "-" is ignored at the beginning of a token if we have not yet |
@@ -1047,7 +1093,10 @@ PR_ParseTimeString( |
goto SKIP_MORE; |
} |
- } |
+ /* Skip T that may precede ISO 8601 time. */ |
+ if (*rest == 'T' && rest[1] >= '0' && rest[1] <= '9') |
+ rest++; |
+ } /* while */ |
if (zone != TT_UNKNOWN && zone_offset == -1) |
{ |
@@ -1082,6 +1131,8 @@ PR_ParseTimeString( |
return PR_FAILURE; |
memset(result, 0, sizeof(*result)); |
+ if (usec != -1) |
+ result->tm_usec = usec; |
if (sec != -1) |
result->tm_sec = sec; |
if (min != -1) |
@@ -1135,11 +1186,9 @@ PR_ParseTimeString( |
*/ |
/* month, day, hours, mins and secs are always non-negative |
- so we dont need to worry about them. */ |
- if(result->tm_year >= 1970) |
+ so we dont need to worry about them. */ |
+ if (result->tm_year >= 1970) |
{ |
- PRInt64 usec_per_sec; |
- |
localTime.tm_sec = result->tm_sec; |
localTime.tm_min = result->tm_min; |
localTime.tm_hour = result->tm_hour; |
@@ -1179,11 +1228,8 @@ PR_ParseTimeString( |
#endif |
if (secs != (time_t) -1) |
{ |
- PRTime usecs64; |
- LL_I2L(usecs64, secs); |
- LL_I2L(usec_per_sec, PR_USEC_PER_SEC); |
- LL_MUL(usecs64, usecs64, usec_per_sec); |
- *result_imploded = usecs64; |
+ *result_imploded = (PRInt64)secs * PR_USEC_PER_SEC; |
+ *result_imploded += result->tm_usec; |
return PR_SUCCESS; |
} |
} |