なんというか、太い信念というか、志が低いぞ!>俺 Date_parseISO8601String その2

睡魔には勝てず、これにて撃沈!
細かいところは、チェックしてません。境界でのエラーはあると思います。

gtlt さんの指摘を受け、前回までのものを手直ししていましたが、簡単(?)なほうから。
#それにもまして、あさっての方向をうろついているのだろう〜。
#4時間粘って、これだけか〜(泣)
#それにしても、正規表現も奥が深い

<!DOCTYPE html>
<title>Date_parseISO8601String</title>

<style type="text/css">
table , td {
  border :1px #ccc inset;
}
th {
  border :1px #ccc outset;
  background : #eee;
}
</style>

<body>
<h1>Date_parseISO8601String() </h1>
<p>ISO 8601 のサブセットを採用します</p>
<dl>
<dt>ES5 の場合</dt>
<dd>
  <ul>
    <li>YYYY
    <li>YYYY-MM
    <li>YYYY-MM-DD
    <li>YYYY-DDD
    <li>YYYY-Www
    <li>YYYY-Www-D
    <li>THH
    <li>THH:mm:ss
    <li>THH:mm:ss.sss
    <li>[+-]HH:mm
    <li>[Z]
  </ul>

</dd>
</dl>
<table>
<tr>
<th rowspan="2">DateTime<th>YYYY<th>MM<th>DD<th>DDD<th>WW<th>Wd<th>HH<th>MN<th>SS<th>MS<th>TzHH<th>Tzmm<th>UTC
<tr>
<th>YYYY<th>MM<th>DD<th>HH<th>MN<th>SS<th>MS<th colspan="6"> none

<script>
(function () {
  var y  = '([+-][0-9]{6}|[0-9]{4})';
  var md = '-([0-3][0-9])(?:-([0-3][0-9]))?';
  var d3 = '-([0-3][0-9]{2})';
  var w  = '-W([0-5][0-9])(?:\\-([1-7]))?';
  var date = '(?:' + y + ')?(?:(?:' + md + ')|(?:' + d3 + ')?|(?:' + w + ')?)?';
  var time = 'T([0-2][0-9])(?::([0-5][0-9]))?(?::([0-5][0-9]))?(?:\\.([0-9]{3})[0-9]*)?';
  var tz = '([+-][0-2][0-9]):([0-5][0-9])';
  var utc = 'Z';
  var ES5 = '^(?:' + date + ')?(?:' + time + ')?(?:' + tz + ')?(' + utc + ')?$';
  var date_time_tz = new RegExp (ES5);

  var num = function (str) {
    return str ? Number (str): 0;
  };
  
  var parse = function (str, test) {
    var dt = date_time_tz.exec (str);
    var date;
    var day;
    var offset = 0;

    if (! dt) return;
    
    date = new Date (num (dt[1]), 0); // 年
    day = date.getDay (); //元日の曜日
    
    if (dt[2])
      date.setMonth (num (dt[2]) -1); // 月
    
    if (dt[3])
      date.setDate (num (dt[3])); // 日
    
    if (dt[4])
      date.setDate (num (dt[4])); // 日数形式
    
    if (dt[5]) {
      d = num (dt[5]) * 7 + (num (dt[6]) || 1) + (day <= 4 ? -day: 7 - day) - 7;
      date.setDate (d); // 週形式
    }
    
    if (dt[7])
      date.setHours (num (dt[7])); // 時
    
    if (dt[8])
      date.setMinutes (num (dt[8])); // 分
    
    if (dt[9])
      date.setSeconds (num (dt[9])); // 秒
    
    if (dt[10])
      date.setMilliseconds (num (dt[10])); // ミリ秒
    
    if (dt[11]) {
      offset = num (dt[11]) * 60;
      offset += num (dt[12]) * (offset < 0 ? -1: 1);
    }
    
    if (dt[13])
      offset += date.getTimezoneOffset ();
    
    if (offset)
     date.setMilliseconds (date.getMilliseconds () + offset * 60000);

    return test ? dt: date;
  };

  this.Date_parseISO8601String = parse;
})();

[
  '2010-11-14T00:00:00.000',
  '2010-11-14T00:00:00.000Z',
  '2010-11-14T00:00:00.000+01:23',
  '2010-11-14T00:00:00.000+01:23Z',
  '+102010-11-14T12:34:56.789+01:23Z',
  '2010-11T12:34:56.789+01:23Z',
  '+102010-11T12:34:56.789+01:23Z',
  '2010T12:34:56.789+01:23Z',
  '+102010T12:34:56.789+01:23Z',
  '2010-W01',
  '2010-W01-1',
  '+102010-W10-1T12:34:56.789+01:23Z',
  '2010-110',
  '+102010-110T12:34:56.789+01:23Z',
].map (function (t) {
  var debug = 0;// Dateオブジェクトと、切り分けた配列の表示切替
  var d = Date_parseISO8601String (t, debug);

  var a = debug
    ? d
    : d
      ? [
         t,
         d.getFullYear (),
         d.getMonth ()+1,
         d.getDate (),
         d.getHours (),
         d.getMinutes (),
         d.getSeconds (),
         d.getMilliseconds ()
        ]
      : [t]
  document.write ('<tr><td>' + a.join ('<td>'));
});
</script>
</table>