1 // Copyright 2008 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 // Test that we can parse dates in all the different formats that we 29 // have to support. 30 // 31 // These formats are all supported by KJS but a lot of them are not 32 // supported by Spidermonkey. 33 34 function testDateParse(string) { 35 var d = Date.parse(string); 36 assertEquals(946713600000, d, "parse: " + string); 37 }; 38 39 40 // For local time we just test that parsing returns non-NaN positive 41 // number of milliseconds to make it timezone independent. 42 function testDateParseLocalTime(string) { 43 var d = Date.parse("parse-local-time:" + string); 44 assertTrue(!isNaN(d), "parse-local-time: " + string + " is NaN."); 45 assertTrue(d > 0, "parse-local-time: " + string + " <= 0."); 46 }; 47 48 49 function testDateParseMisc(array) { 50 assertEquals(2, array.length, "array [" + array + "] length != 2."); 51 var string = array[0]; 52 var expected = array[1]; 53 var d = Date.parse(string); 54 assertEquals(expected, d, "parse-misc: " + string); 55 } 56 57 58 // 59 // Test all the formats in UT timezone. 60 // 61 var testCasesUT = [ 62 'Sat, 01-Jan-2000 08:00:00 UT', 63 'Sat, 01 Jan 2000 08:00:00 UT', 64 'Jan 01 2000 08:00:00 UT', 65 'Jan 01 08:00:00 UT 2000', 66 'Saturday, 01-Jan-00 08:00:00 UT', 67 '01 Jan 00 08:00 +0000', 68 // Ignore weekdays. 69 'Mon, 01 Jan 2000 08:00:00 UT', 70 'Tue, 01 Jan 2000 08:00:00 UT', 71 // Ignore prefix that is not part of a date. 72 '[Saturday] Jan 01 08:00:00 UT 2000', 73 'Ignore all of this stuff because it is annoying 01 Jan 2000 08:00:00 UT', 74 '[Saturday] Jan 01 2000 08:00:00 UT', 75 'All of this stuff is really annnoying, so it will be ignored Jan 01 2000 08:00:00 UT', 76 // If the three first letters of the month is a 77 // month name we are happy - ignore the rest. 78 'Sat, 01-Janisamonth-2000 08:00:00 UT', 79 'Sat, 01 Janisamonth 2000 08:00:00 UT', 80 'Janisamonth 01 2000 08:00:00 UT', 81 'Janisamonth 01 08:00:00 UT 2000', 82 'Saturday, 01-Janisamonth-00 08:00:00 UT', 83 '01 Janisamonth 00 08:00 +0000', 84 // Allow missing space between month and day. 85 'Janisamonthandtherestisignored01 2000 08:00:00 UT', 86 'Jan01 2000 08:00:00 UT', 87 // Allow year/month/day format. 88 'Sat, 2000/01/01 08:00:00 UT', 89 // Allow month/day/year format. 90 'Sat, 01/01/2000 08:00:00 UT', 91 // Allow month/day year format. 92 'Sat, 01/01 2000 08:00:00 UT', 93 // Allow comma instead of space after day, month and year. 94 'Sat, 01,Jan,2000,08:00:00 UT', 95 // Seconds are optional. 96 'Sat, 01-Jan-2000 08:00 UT', 97 'Sat, 01 Jan 2000 08:00 UT', 98 'Jan 01 2000 08:00 UT', 99 'Jan 01 08:00 UT 2000', 100 'Saturday, 01-Jan-00 08:00 UT', 101 '01 Jan 00 08:00 +0000', 102 // Allow AM/PM after the time. 103 'Sat, 01-Jan-2000 08:00 AM UT', 104 'Sat, 01 Jan 2000 08:00 AM UT', 105 'Jan 01 2000 08:00 AM UT', 106 'Jan 01 08:00 AM UT 2000', 107 'Saturday, 01-Jan-00 08:00 AM UT', 108 '01 Jan 00 08:00 AM +0000', 109 // White space and stuff in parenthesis is 110 // apparently allowed in most places where white 111 // space is allowed. 112 ' Sat, 01-Jan-2000 08:00:00 UT ', 113 ' Sat, 01 Jan 2000 08:00:00 UT ', 114 ' Saturday, 01-Jan-00 08:00:00 UT ', 115 ' 01 Jan 00 08:00 +0000 ', 116 ' ()(Sat, 01-Jan-2000) Sat, 01-Jan-2000 08:00:00 UT ', 117 ' Sat()(Sat, 01-Jan-2000)01 Jan 2000 08:00:00 UT ', 118 ' Sat,(02)01 Jan 2000 08:00:00 UT ', 119 ' Sat, 01(02)Jan 2000 08:00:00 UT ', 120 ' Sat, 01 Jan 2000 (2001)08:00:00 UT ', 121 ' Sat, 01 Jan 2000 (01)08:00:00 UT ', 122 ' Sat, 01 Jan 2000 (01:00:00)08:00:00 UT ', 123 ' Sat, 01 Jan 2000 08:00:00 (CDT)UT ', 124 ' Sat, 01 Jan 2000 08:00:00 UT((((CDT))))', 125 ' Saturday, 01-Jan-00 ()(((asfd)))(Sat, 01-Jan-2000)08:00:00 UT ', 126 ' 01 Jan 00 08:00 ()(((asdf)))(Sat, 01-Jan-2000)+0000 ', 127 ' 01 Jan 00 08:00 +0000()((asfd)(Sat, 01-Jan-2000)) ']; 128 129 // 130 // Test that we do the right correction for different time zones. 131 // I'll assume that we can handle the same formats as for UT and only 132 // test a few formats for each of the timezones. 133 // 134 135 // GMT = UT 136 var testCasesGMT = [ 137 'Sat, 01-Jan-2000 08:00:00 GMT', 138 'Sat, 01-Jan-2000 08:00:00 GMT+0', 139 'Sat, 01-Jan-2000 08:00:00 GMT+00', 140 'Sat, 01-Jan-2000 08:00:00 GMT+000', 141 'Sat, 01-Jan-2000 08:00:00 GMT+0000', 142 'Sat, 01-Jan-2000 08:00:00 GMT+00:00', // Interestingly, KJS cannot handle this. 143 'Sat, 01 Jan 2000 08:00:00 GMT', 144 'Saturday, 01-Jan-00 08:00:00 GMT', 145 '01 Jan 00 08:00 -0000', 146 '01 Jan 00 08:00 +0000']; 147 148 // EST = UT minus 5 hours. 149 var testCasesEST = [ 150 'Sat, 01-Jan-2000 03:00:00 UTC-0500', 151 'Sat, 01-Jan-2000 03:00:00 UTC-05:00', // Interestingly, KJS cannot handle this. 152 'Sat, 01-Jan-2000 03:00:00 EST', 153 'Sat, 01 Jan 2000 03:00:00 EST', 154 'Saturday, 01-Jan-00 03:00:00 EST', 155 '01 Jan 00 03:00 -0500']; 156 157 // EDT = UT minus 4 hours. 158 var testCasesEDT = [ 159 'Sat, 01-Jan-2000 04:00:00 EDT', 160 'Sat, 01 Jan 2000 04:00:00 EDT', 161 'Saturday, 01-Jan-00 04:00:00 EDT', 162 '01 Jan 00 04:00 -0400']; 163 164 // CST = UT minus 6 hours. 165 var testCasesCST = [ 166 'Sat, 01-Jan-2000 02:00:00 CST', 167 'Sat, 01 Jan 2000 02:00:00 CST', 168 'Saturday, 01-Jan-00 02:00:00 CST', 169 '01 Jan 00 02:00 -0600']; 170 171 // CDT = UT minus 5 hours. 172 var testCasesCDT = [ 173 'Sat, 01-Jan-2000 03:00:00 CDT', 174 'Sat, 01 Jan 2000 03:00:00 CDT', 175 'Saturday, 01-Jan-00 03:00:00 CDT', 176 '01 Jan 00 03:00 -0500']; 177 178 // MST = UT minus 7 hours. 179 var testCasesMST = [ 180 'Sat, 01-Jan-2000 01:00:00 MST', 181 'Sat, 01 Jan 2000 01:00:00 MST', 182 'Saturday, 01-Jan-00 01:00:00 MST', 183 '01 Jan 00 01:00 -0700']; 184 185 // MDT = UT minus 6 hours. 186 var testCasesMDT = [ 187 'Sat, 01-Jan-2000 02:00:00 MDT', 188 'Sat, 01 Jan 2000 02:00:00 MDT', 189 'Saturday, 01-Jan-00 02:00:00 MDT', 190 '01 Jan 00 02:00 -0600']; 191 192 // PST = UT minus 8 hours. 193 var testCasesPST = [ 194 'Sat, 01-Jan-2000 00:00:00 PST', 195 'Sat, 01 Jan 2000 00:00:00 PST', 196 'Saturday, 01-Jan-00 00:00:00 PST', 197 '01 Jan 00 00:00 -0800', 198 // Allow missing time. 199 'Sat, 01-Jan-2000 PST']; 200 201 // PDT = UT minus 7 hours. 202 var testCasesPDT = [ 203 'Sat, 01-Jan-2000 01:00:00 PDT', 204 'Sat, 01 Jan 2000 01:00:00 PDT', 205 'Saturday, 01-Jan-00 01:00:00 PDT', 206 '01 Jan 00 01:00 -0700']; 207 208 // Local time cases. 209 var testCasesLocalTime = [ 210 // Allow timezone ommision. 211 'Sat, 01-Jan-2000 08:00:00', 212 'Sat, 01 Jan 2000 08:00:00', 213 'Jan 01 2000 08:00:00', 214 'Jan 01 08:00:00 2000', 215 'Saturday, 01-Jan-00 08:00:00', 216 '01 Jan 00 08:00']; 217 218 219 // Misc. test cases that result in a different time value. 220 var testCasesMisc = [ 221 // Special handling for years in the [0, 100) range. 222 ['Sat, 01 Jan 0 08:00:00 UT', 946713600000], // year 2000 223 ['Sat, 01 Jan 49 08:00:00 UT', 2493100800000], // year 2049 224 ['Sat, 01 Jan 50 08:00:00 UT', -631123200000], // year 1950 225 ['Sat, 01 Jan 99 08:00:00 UT', 915177600000], // year 1999 226 ['Sat, 01 Jan 100 08:00:00 UT', -59011430400000], // year 100 227 // Test PM after time. 228 ['Sat, 01-Jan-2000 08:00 PM UT', 946756800000], 229 ['Sat, 01 Jan 2000 08:00 PM UT', 946756800000], 230 ['Jan 01 2000 08:00 PM UT', 946756800000], 231 ['Jan 01 08:00 PM UT 2000', 946756800000], 232 ['Saturday, 01-Jan-00 08:00 PM UT', 946756800000], 233 ['01 Jan 00 08:00 PM +0000', 946756800000]]; 234 235 // Test different version of the ES5 date time string format. 236 var testCasesES5Misc = [ 237 ['2000-01-01T08:00:00.000Z', 946713600000], 238 ['2000-01-01T08:00:00Z', 946713600000], 239 ['2000-01-01T08:00Z', 946713600000], 240 ['2000-01T08:00:00.000Z', 946713600000], 241 ['2000T08:00:00.000Z', 946713600000], 242 ['2000T08:00Z', 946713600000], 243 ['2000-01T00:00:00.000-08:00', 946713600000], 244 ['2000-01T08:00:00.001Z', 946713600001], 245 ['2000-01T08:00:00.099Z', 946713600099], 246 ['2000-01T08:00:00.999Z', 946713600999], 247 ['2000-01T00:00:00.001-08:00', 946713600001], 248 ['2000-01-01T24:00', 946771200000], 249 ['2000-01-01T24:00:00', 946771200000], 250 ['2000-01-01T24:00:00.000', 946771200000], 251 ['2000-01-01T24:00:00.000Z', 946771200000]]; 252 253 var testCasesES5MiscNegative = [ 254 '2000-01-01TZ', 255 '2000-01-01T60Z', 256 '2000-01-01T60:60Z', 257 '2000-01-0108:00Z', 258 '2000-01-01T08Z', 259 '2000-01-01T24:01', 260 '2000-01-01T24:00:01', 261 '2000-01-01T24:00:00.001', 262 '2000-01-01T24:00:00.999Z']; 263 264 265 // Run all the tests. 266 testCasesUT.forEach(testDateParse); 267 testCasesGMT.forEach(testDateParse); 268 testCasesEST.forEach(testDateParse); 269 testCasesEDT.forEach(testDateParse); 270 testCasesCST.forEach(testDateParse); 271 testCasesCDT.forEach(testDateParse); 272 testCasesMST.forEach(testDateParse); 273 testCasesMDT.forEach(testDateParse); 274 testCasesPST.forEach(testDateParse); 275 testCasesPDT.forEach(testDateParse); 276 testCasesLocalTime.forEach(testDateParseLocalTime); 277 testCasesMisc.forEach(testDateParseMisc); 278 279 // ES5 date time string format compliance. 280 testCasesES5Misc.forEach(testDateParseMisc); 281 testCasesES5MiscNegative.forEach(function (s) { 282 assertTrue(isNaN(Date.parse(s)), s + " is not NaN."); 283 }); 284 285 286 // Test that we can parse our own date format. 287 // (Dates from 1970 to ~2070 with 150h steps.) 288 for (var i = 0; i < 24 * 365 * 100; i += 150) { 289 var ms = i * (3600 * 1000); 290 var s = (new Date(ms)).toString(); 291 assertEquals(ms, Date.parse(s), "parse own: " + s); 292 } 293 294 // Negative tests. 295 var testCasesNegative = [ 296 'May 25 2008 1:30 (PM)) UTC', // Bad unmatched ')' after number. 297 'May 25 2008 1:30( )AM (PM)', // 298 'a1', // Issue 126448, 53209. 299 'nasfdjklsfjoaifg1', 300 'x_2', 301 'May 25 2008 AAA (GMT)']; // Unknown word after number. 302 303 testCasesNegative.forEach(function (s) { 304 assertTrue(isNaN(Date.parse(s)), s + " is not NaN."); 305 }); 306