docs: function parseDate(fmt, date) {
      var indexMap = {}; // contains reGroupPosition -> typeLetter or [typeLetter, value array]
      var reIndex = 1;
      var timezoneOffsetMatch;
      var timezoneIndex;
      var match;
  
      var format = replace(fmt, /^\?/);
      if (format!=fmt && !trim(date))
        return _null;
  
      if (match = /^\[([+-])(\d\d)(\d\d)\]\s*(.*)/.exec(format)) {
        timezoneOffsetMatch = match;
        format = match[4];
      }
  
      var parser = new RegExp(format.replace(/(.)(\1*)(?:\[([^\]]*)\])?/g, function(wholeMatch, placeholderChar, placeholderDigits, param) {
        if (/[dmhkyhs]/i.test(placeholderChar)) {
          indexMap[reIndex++] = placeholderChar;
          var plen = placeholderDigits.length+1;
          return "(\\d"+(plen<2?"+":("{1,"+plen+"}"))+")";
        }
        else if (placeholderChar == 'z') {
          timezoneIndex = reIndex;
          reIndex += 3;
          return "([+-])(\\d\\d)(\\d\\d)";
        }
        else if (/[Nna]/.test(placeholderChar)) {
          indexMap[reIndex++] = [placeholderChar, param && param.split(',')];
          return "([a-zA-Z\\u0080-\\u1fff]+)";
        }
        else if (/w/i.test(placeholderChar))
          return "[a-zA-Z\\u0080-\\u1fff]+";
        else if (/\s/.test(placeholderChar))
          return "\\s+";
        else
          return escapeRegExp(wholeMatch);
      }));
  
      if (!(match = parser.exec(date)))
        return undef;
  
      var ctorArgs = [0, 0, 0, 0, 0, 0,  0];
      for (var i = 1; i < reIndex; i++) {
        var matchVal = match[i];
        var indexEntry = indexMap[i];
        if (isList(indexEntry)) { // for a, n or N
          var placeholderChar = indexEntry[0];
          var mapEntry  = PARSE_DATE_MAP[placeholderChar];
          var ctorIndex = mapEntry[0];
          var valList = indexEntry[1] || mapEntry[1];
          var listValue = find(valList, function(v, index) { if (startsWith(matchVal.toLowerCase(), v.toLowerCase())) return index; });
          if (listValue == _null)
            return undef;
          if (placeholderChar == 'a')
            ctorArgs[ctorIndex] += listValue * 12;
          else
            ctorArgs[ctorIndex] = listValue;
        }
        else if (indexEntry) { // for numeric values (yHmMs)
          var value = parseFloat(matchVal);
          var mapEntry  = PARSE_DATE_MAP[indexEntry];
          if (isList(mapEntry))
            ctorArgs[mapEntry[0]] += value - mapEntry[1];
          else
            ctorArgs[mapEntry] += value;
        }
      }
      var d = new Date(ctorArgs[0], ctorArgs[1], ctorArgs[2], ctorArgs[3], ctorArgs[4], ctorArgs[5], ctorArgs[6]);
      return dateAdd(d, 'minutes', -getTimezone(timezoneOffsetMatch, 1, d) - getTimezone(match, timezoneIndex, d));
    }