Revision: 4557
Author: [email protected]
Date: Sun May 2 23:43:25 2010
Log: Added support for ES5 date time string format to Date.parse.
Review URL: http://codereview.chromium.org/1704016
http://code.google.com/p/v8/source/detail?r=4557
Modified:
/branches/bleeding_edge/src/date.js
/branches/bleeding_edge/src/dateparser-inl.h
/branches/bleeding_edge/src/dateparser.cc
/branches/bleeding_edge/src/dateparser.h
/branches/bleeding_edge/test/mjsunit/date-parse.js
=======================================
--- /branches/bleeding_edge/src/date.js Tue Apr 6 03:22:52 2010
+++ /branches/bleeding_edge/src/date.js Sun May 2 23:43:25 2010
@@ -620,7 +620,7 @@
// -------------------------------------------------------------------
// Reused output buffer. Used when parsing date strings.
-var parse_buffer = $Array(7);
+var parse_buffer = $Array(8);
// ECMA 262 - 15.9.4.2
function DateParse(string) {
@@ -628,13 +628,13 @@
if (IS_NULL(arr)) return $NaN;
var day = MakeDay(arr[0], arr[1], arr[2]);
- var time = MakeTime(arr[3], arr[4], arr[5], 0);
+ var time = MakeTime(arr[3], arr[4], arr[5], arr[6]);
var date = MakeDate(day, time);
- if (IS_NULL(arr[6])) {
+ if (IS_NULL(arr[7])) {
return TimeClip(UTC(date));
} else {
- return TimeClip(date - arr[6] * 1000);
+ return TimeClip(date - arr[7] * 1000);
}
}
=======================================
--- /branches/bleeding_edge/src/dateparser-inl.h Thu Oct 15 08:01:36 2009
+++ /branches/bleeding_edge/src/dateparser-inl.h Sun May 2 23:43:25 2010
@@ -54,16 +54,25 @@
} else {
// n + ":"
if (!time.Add(n)) return false;
- }
+ in.Skip('.');
+ }
+ } else if (in.Skip('.') && time.IsExpecting(n)) {
+ time.Add(n);
+ if (!in.IsAsciiDigit()) return false;
+ int n = in.ReadUnsignedNumber();
+ time.AddFinal(n);
} else if (tz.IsExpecting(n)) {
tz.SetAbsoluteMinute(n);
} else if (time.IsExpecting(n)) {
time.AddFinal(n);
- // Require end or white space immediately after finalizing time.
- if (!in.IsEnd() && !in.SkipWhiteSpace()) return false;
+ // Require end, white space or Z immediately after finalizing time.
+ if (!in.IsEnd() && !in.SkipWhiteSpace() && !in.Is('Z')) return
false;
} else {
if (!day.Add(n)) return false;
in.Skip('-'); // Ignore suffix '-' for year, month, or day.
+ // Skip trailing 'T' for ECMAScript 5 date string format but make
+ // sure that it is followed by a digit (for the time).
+ if (in.Skip('T') && !in.IsAsciiDigit()) return false;
}
} else if (in.IsAsciiAlphaOrAbove()) {
// Parse a "word" (sequence of chars. >= 'A').
=======================================
--- /branches/bleeding_edge/src/dateparser.cc Fri Jan 29 03:46:55 2010
+++ /branches/bleeding_edge/src/dateparser.cc Sun May 2 23:43:25 2010
@@ -33,6 +33,16 @@
namespace internal {
bool DateParser::DayComposer::Write(FixedArray* output) {
+ // Set year to 0 by default.
+ if (index_ < 1) {
+ comp_[index_++] = 1;
+ }
+
+ // Day and month defaults to 1.
+ while (index_ < kSize) {
+ comp_[index_++] = 1;
+ }
+
int year = 0; // Default year is 0 (=> 2000) for KJS compatibility.
int month = kNone;
int day = kNone;
@@ -88,6 +98,7 @@
int& hour = comp_[0];
int& minute = comp_[1];
int& second = comp_[2];
+ int& millisecond = comp_[3];
if (hour_offset_ != kNone) {
if (!IsHour12(hour)) return false;
@@ -95,11 +106,13 @@
hour += hour_offset_;
}
- if (!IsHour(hour) || !IsMinute(minute) || !IsSecond(second)) return
false;
+ if (!IsHour(hour) || !IsMinute(minute) ||
+ !IsSecond(second) || !IsMillisecond(millisecond)) return false;
output->set(HOUR, Smi::FromInt(hour));
output->set(MINUTE, Smi::FromInt(minute));
output->set(SECOND, Smi::FromInt(second));
+ output->set(MILLISECOND, Smi::FromInt(millisecond));
return true;
}
@@ -134,6 +147,7 @@
{'p', 'm', '\0', DateParser::AM_PM, 12},
{'u', 't', '\0', DateParser::TIME_ZONE_NAME, 0},
{'u', 't', 'c', DateParser::TIME_ZONE_NAME, 0},
+ {'z', '\0', '\0', DateParser::TIME_ZONE_NAME, 0},
{'g', 'm', 't', DateParser::TIME_ZONE_NAME, 0},
{'c', 'd', 't', DateParser::TIME_ZONE_NAME, -5},
{'c', 's', 't', DateParser::TIME_ZONE_NAME, -6},
=======================================
--- /branches/bleeding_edge/src/dateparser.h Mon May 25 03:05:56 2009
+++ /branches/bleeding_edge/src/dateparser.h Sun May 2 23:43:25 2010
@@ -44,13 +44,14 @@
// [3]: hour
// [4]: minute
// [5]: second
- // [6]: UTC offset in seconds, or null value if no timezone specified
+ // [6]: millisecond
+ // [7]: UTC offset in seconds, or null value if no timezone specified
// If parsing fails, return false (content of output array is not
defined).
template <typename Char>
static bool Parse(Vector<Char> str, FixedArray* output);
enum {
- YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, UTC_OFFSET, OUTPUT_SIZE
+ YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, MILLISECOND, UTC_OFFSET,
OUTPUT_SIZE
};
private:
@@ -189,7 +190,9 @@
TimeComposer() : index_(0), hour_offset_(kNone) {}
bool IsEmpty() const { return index_ == 0; }
bool IsExpecting(int n) const {
- return (index_ == 1 && IsMinute(n)) || (index_ == 2 && IsSecond(n));
+ return (index_ == 1 && IsMinute(n)) ||
+ (index_ == 2 && IsSecond(n)) ||
+ (index_ == 3 && IsMillisecond(n));
}
bool Add(int n) {
return index_ < kSize ? (comp_[index_++] = n, true) : false;
@@ -207,8 +210,9 @@
static bool IsHour(int x) { return Between(x, 0, 23); }
static bool IsHour12(int x) { return Between(x, 0, 12); }
static bool IsSecond(int x) { return Between(x, 0, 59); }
-
- static const int kSize = 3;
+ static bool IsMillisecond(int x) { return Between(x, 0, 999); }
+
+ static const int kSize = 4;
int comp_[kSize];
int index_;
int hour_offset_;
=======================================
--- /branches/bleeding_edge/test/mjsunit/date-parse.js Mon Aug 24 02:08:12
2009
+++ /branches/bleeding_edge/test/mjsunit/date-parse.js Sun May 2 23:43:25
2010
@@ -205,7 +205,6 @@
'Saturday, 01-Jan-00 01:00:00 PDT',
'01 Jan 00 01:00 -0700'];
-
// Local time cases.
var testCasesLocalTime = [
// Allow timezone ommision.
@@ -233,6 +232,27 @@
['Saturday, 01-Jan-00 08:00 PM UT', 946756800000],
['01 Jan 00 08:00 PM +0000', 946756800000]];
+// Test different version of the ES5 date time string format.
+var testCasesES5Misc = [
+ ['2000-01-01T08:00:00.000Z', 946713600000],
+ ['2000-01-01T08:00:00Z', 946713600000],
+ ['2000-01-01T08:00Z', 946713600000],
+ ['2000-01T08:00:00.000Z', 946713600000],
+ ['2000T08:00:00.000Z', 946713600000],
+ ['2000T08:00Z', 946713600000],
+ ['2000-01T00:00:00.000-08:00', 946713600000],
+ ['2000-01T08:00:00.001Z', 946713600001],
+ ['2000-01T08:00:00.099Z', 946713600099],
+ ['2000-01T08:00:00.999Z', 946713600999],
+ ['2000-01T00:00:00.001-08:00', 946713600001]];
+
+var testCasesES5MiscNegative = [
+ '2000-01-01TZ',
+ '2000-01-01T60Z',
+ '2000-01-01T60:60Z',
+ '2000-01-0108:00Z',
+ '2000-01-01T08Z'];
+
// Run all the tests.
testCasesUT.forEach(testDateParse);
@@ -248,6 +268,12 @@
testCasesLocalTime.forEach(testDateParseLocalTime);
testCasesMisc.forEach(testDateParseMisc);
+// ES5 date time string format compliance.
+testCasesES5Misc.forEach(testDateParseMisc);
+testCasesES5MiscNegative.forEach(function (s) {
+ assertTrue(isNaN(Date.parse(s)), s + " is not NaN.");
+});
+
// Test that we can parse our own date format.
// (Dates from 1970 to ~2070 with 150h steps.)
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev