parseInvalidISO.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. var total = 0, accepted = 0, failed = 0;
  6. echo("////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////");
  7. echo("// Definitely invalid ISO strings");
  8. echo("");
  9. echo("// Field value outside valid range");
  10. echo("");
  11. runTest("0001-00-01T01:01:01.001Z");
  12. runTest("0001-13-01T01:01:01.001Z");
  13. runTest("0001-01-00T01:01:01.001Z");
  14. runTest("0001-01-32T01:01:01.001Z");
  15. runTest("0001-01-01T25:01:01.001Z");
  16. runTest("0001-01-01T01:01:01.001+25:00");
  17. runTest("0001-01-01T01:60:01.001Z");
  18. runTest("0001-01-01T01:01:01.001+00:60");
  19. runTest("0001-01-01T01:01:60.001Z");
  20. echo("// Time value outside valid range");
  21. echo("");
  22. runTest("-300000-01-01T01:01:01.001Z");
  23. runTest("+300000-01-01T01:01:01.001Z");
  24. // Many other invalid ISO strings are tested in "potential cross-browser compatibility issues" section
  25. writeStats();
  26. echo("////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////");
  27. echo("// Potential cross-browser compatibility issues");
  28. echo("");
  29. echo("// Leading and trailing whitespace, nulls, or non-whitespace non-nulls");
  30. echo("");
  31. var s = "0001-01-01T01:01:01.001Z";
  32. var spaceNulls = ["", "\0", "\t", "\n", "\v", "\f", "\r", " ", "\u00a0", "\u2028", "\u2029", "\ufeff"];
  33. for (var i = 0; i < spaceNulls.length; ++i) {
  34. if (s !== "") {
  35. runTest(spaceNulls[i] + s);
  36. runTest(s + spaceNulls[i]);
  37. }
  38. runTest(s + spaceNulls[i] + "x");
  39. }
  40. echo("// Less and more digits per field");
  41. echo("");
  42. runTest("001-01-01T01:01:01.001Z");
  43. runTest("00001-01-01T01:01:01.001Z");
  44. runTest("0001-1-01T01:01:01.001Z");
  45. runTest("0001-001-01T01:01:01.001Z");
  46. runTest("0001-01-1T01:01:01.001Z");
  47. runTest("0001-01-001T01:01:01.001Z");
  48. runTest("0001-01-01T1:01:01.001Z");
  49. runTest("0001-01-01T001:01:01.001Z");
  50. runTest("0001-01-01T01:1:01.001Z");
  51. runTest("0001-01-01T01:001:01.001Z");
  52. runTest("0001-01-01T01:01:1.001Z");
  53. runTest("0001-01-01T01:01:001.001Z");
  54. runTest("0001-01-01T01:01:01.01Z");
  55. runTest("0001-01-01T01:01:01.0001Z");
  56. echo("// Date-only forms with UTC offset");
  57. echo("");
  58. runTest("0001Z");
  59. runTest("0001-01Z");
  60. runTest("0001-01-01Z"); // note: this is rejected by the ISO parser as it should be, but it's accepted by the fallback parser
  61. echo("// Optionality of minutes");
  62. echo("");
  63. runTest("0001-01-01T01Z");
  64. runTest("0001-01-01T01:01:01.001+01");
  65. echo("// Time-only forms");
  66. echo("");
  67. runTest("T01:01Z");
  68. runTest("T01:01:01Z");
  69. runTest("T01:01:01.001Z");
  70. echo("// Field before missing optional field ending with separator");
  71. echo("");
  72. runTest("0001-");
  73. runTest("0001-01-");
  74. runTest("0001-T01:01:01.001Z");
  75. runTest("0001-01-T01:01:01.001Z");
  76. runTest("0001-01-01T01:01:Z");
  77. runTest("0001-01-01T01:01:01.Z");
  78. echo("// Optionality and type of sign on years");
  79. echo("");
  80. runTest("+0001-01-01T01:01:01.001Z");
  81. runTest("-0001-01-01T01:01:01.001Z");
  82. runTest("010000-01-01T01:01:01.001Z");
  83. runTest("-000000-01-01T01:01:01.001Z");
  84. echo("// Test support for zones without colons (DEVDIV2: 481975)");
  85. echo("");
  86. runTest("2012-02-22T03:08:26+0000");
  87. echo("// Test support for zones(Issue#1402:OS8026281)");
  88. echo("");
  89. runTest("Wed Jul 22 16:04:54 2016 +0000");
  90. runTest("Wed Jul 22 16:04:54 +0000 2016");
  91. runTest("Wed Jul 22 +0000 16:04:54 2016");
  92. runTest("Wed Jul +0000 22 16:04:54 2016");
  93. runTest("Wed +0000 Jul 22 16:04:54 2016");
  94. runTest("+0000 Wed Jul 22 16:04:54 2016");
  95. runTest("Wed Jul 22 16:04:54 2016");
  96. writeStats();
  97. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  98. // Test-specific helpers
  99. function runTest(s) {
  100. ++total;
  101. echo(s);
  102. safeCall(function () {
  103. var iso = new Date(s);
  104. var timeValue1 = iso.getTime();
  105. if (isNaN(timeValue1)) {
  106. echo(iso);
  107. } else {
  108. iso = iso.toISOString();
  109. echo(iso);
  110. var timeValue2 = new Date(iso).getTime();
  111. echo(timeValue1 + " " + (timeValue1 === timeValue2 ? "===" : "!==") + " " + timeValue2);
  112. if (iso.indexOf("Invalid", 0) === -1) {
  113. if (timeValue1 === timeValue2)
  114. ++accepted;
  115. else
  116. ++failed;
  117. }
  118. }
  119. });
  120. echo("");
  121. }
  122. function writeStats() {
  123. echo("Total: " + total);
  124. echo("Accepted: " + accepted);
  125. echo("Rejected: " + (total - accepted - failed));
  126. echo("Failed: " + failed);
  127. echo("");
  128. failed = accepted = total = 0;
  129. }
  130. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  131. // General helpers
  132. function toString(o, quoteStrings) {
  133. switch (o) {
  134. case null:
  135. case undefined:
  136. return "" + o;
  137. }
  138. switch (typeof o) {
  139. case "boolean":
  140. case "number":
  141. return "" + o;
  142. case "string":
  143. {
  144. var hex = "0123456789abcdef";
  145. var s = "";
  146. for (var i = 0; i < o.length; ++i) {
  147. var c = o.charCodeAt(i);
  148. if (c === 0)
  149. s += "\\0";
  150. else if (c >= 0x20 && c < 0x7f)
  151. s += quoteStrings && o.charAt(i) === "\"" ? "\\\"" : o.charAt(i);
  152. else if (c <= 0xff)
  153. s += "\\x" + hex.charAt((c >> 4) & 0xf) + hex.charAt(c & 0xf);
  154. else
  155. s += "\\u" + hex.charAt((c >> 12) & 0xf) + hex.charAt((c >> 8) & 0xf) + hex.charAt((c >> 4) & 0xf) + hex.charAt(c & 0xf);
  156. }
  157. if (quoteStrings)
  158. s = "\"" + s + "\"";
  159. return s;
  160. }
  161. case "object":
  162. case "function":
  163. break;
  164. default:
  165. return "<unknown type '" + typeof o + "'>";
  166. }
  167. if (o instanceof Array) {
  168. var s = "[";
  169. for (var i = 0; i < o.length; ++i) {
  170. if (i)
  171. s += ", ";
  172. s += this.toString(o[i], true);
  173. }
  174. return s + "]";
  175. }
  176. if (o instanceof Error)
  177. return o.name + ": " + o.message;
  178. if (o instanceof RegExp)
  179. return o.toString() + (o.lastIndex === 0 ? "" : " (lastIndex: " + o.lastIndex + ")");
  180. return "" + o;
  181. }
  182. function echo(o) {
  183. var s = this.toString(o);
  184. try {
  185. document.write(s + "<br/>");
  186. } catch (ex) {
  187. try {
  188. WScript.Echo(s);
  189. } catch (ex2) {
  190. print(s);
  191. }
  192. }
  193. }
  194. function safeCall(f) {
  195. var args = [];
  196. for (var a = 1; a < arguments.length; ++a)
  197. args.push(arguments[a]);
  198. try {
  199. return f.apply(this, args);
  200. } catch (ex) {
  201. echo(ex);
  202. }
  203. }