如何使用单个正则表达式解析“dd-MMM-yyyy”或“MMM-dd-yyyy”日期字符串?

时间:2014-02-13 09:17:07

标签: javascript regex date

我收到日期字符串,如dd-MMM-yyyyMMM-dd-yyyy格式。我想要的是使用一个正则表达式(不使用任何第三方插件)提取daymonthyear。有可能吗?

4 个答案:

答案 0 :(得分:7)

我会先反转月份和日期的位置,确保所有日期都采用相同的格式:

function splitDate(input) {
    return input.replace(
        /^(\w+)-(\d+)/, '$2-$1'
    ).split('-');
}

var parts = splitDate('Feb-12-2012'); // ["12", "Feb", "2012"]
var parts = splitDate('12-Feb-2012'); // ["12", "Feb", "2012"]

var day = parts[0];
var month = parts[1];
var year = parts[2];

/^(\w+)-(\d+)/仅匹配“Mmm-dd-yyyy”:

^       beginning of the input
(\w+)   a word character, one or more times ($1)
-       a dash
(\d+)   a digit, one or more times ($2)

进一步

既然你知道如何分割输入,我想进一步将结果转换为Date对象。首先,让我们打开Chrome控制台,快速检查输入是否可解析:

new Date('12-Feb-2012') // Sun Feb 12 2012...
new Date('Feb-12-2012') // Sun Feb 12 2012...

显然,Chrome可以正常完成这项工作。这很好,但其他实现不一定表现相同,您应该更好地依赖于规范。幸运的是,有人已经为你检查了它们:undocumented supported Date.parse format?

总而言之,解析自己的格式的能力可能因实现而异。只有一种可靠的格式,即YYYY-MM-DDTHH:mm:ss.sssZ,其中每个字母 - 除了“T”和“Z” - 代表一个数字。

准确地说,MM应该是一个数字。如果要确保正确解析输入,则必须找到将月份部分转换为数字的方法。我们试试吧:

var months = {
    Jan: '01', Feb: '02', Mar: '03', Apr: '04', May: '05', Jun: '06',
    Jul: '07', Aug: '08', Sep: '09', Oct: '10', Nov: '11', Dec: '12'
};
var parts = splitDate('Feb-12-2012'); // ["12", "Feb", "2012"]
parts[1] = months[parts[1]]; // parts -> ["12", "02", "2012"]

没那么糟糕,工作差不多完成了。实际上,如规范中所提到的,解析器只接受YYYY-MM-DD这样的日期格式,这很容易实现:

parts = parts.reverse(); // ["2012", "02", "12"]
parts = parts.join('-'); // "2012-02-12"

让我们看一下控制台的内容:

new Date(parts) // Sun Feb 12 2012...

完成!


关闭案例

或者,你可以这样做:

var parts = splitDate('Feb-12-2012'); // ["12", "Feb", "2012"]
parts[1] = months[parts[1]]; // parts -> ["12", "02", "2012"]
var date = new Date(parts[2], parts[1] - 1, parts[0]);

您可以通过将进程隐藏到函数中来进一步:

function parseDate(input) {
    var map = {
        Jan: 0, Feb: 1, Mar: 2, Apr: 3, May: 4, Jun: 5,
        Jul: 6, Aug: 7, Sep: 8, Oct: 9, Nov: 10, Dec: 11
    };
    return (parseDate = function (input) {
        input = input.replace(/^(\w+)-(\d+)/, '$2-$1').split('-');
        return new Date(input[2], map[input[1]], input[0]);
    })(input);
};

用法示例:

var date = parseDate('12-Feb-2012'); // Sun Feb 12 2012...
var date = parseDate('Feb-12-2012'); // Sun Feb 12 2012...

随时询问详情。

答案 1 :(得分:2)

是的,这当然是可能的,但您必须检查匹配的捕获组:

/^(?:(\d\d)-([a-z]{3})-(\d{4})|([a-z]{3})-(\d\d)-(\d{4}))$/i

如果在匹配后定义了群组13,则会使用dd-MMM-yyyy,如果定义了群组46,那么另一个用了。

此正则表达式不会进行任何合理性检查,因此它也会匹配99-XXX-9999,但这是一个不同的问题。

答案 2 :(得分:0)

首先,您可以将dd-MMM-yyyyMMM-dd-yyyy格式转换为dd-MMM-yyyy

使用:.replace(/([a-zA-Z]{3})-(\d{2})-(\d{4})/,"$2-$1-$3");

然后你可以使用REGEX:/(\d+)-([a-zA-Z]{3})-(\d{4})/

代码:

var d="DEC-16-1990";
d=d.replace(/([a-zA-Z]{3})-(\d{2})-(\d{4})/,"$2-$1-$3");
var ar=d.match(/(\d+)-([a-zA-Z]{3})-(\d{4})/);
var day=ar[1];    //16
var month=ar[2];  //DEC
var year=ar[3];   //1990

DEMO

答案 3 :(得分:-1)

此变体添加对称YYYY-mm-dd,允许单个数字日期数字,并提供月份名称的语言独立性规范。

function parseDate (date, months) {
  var dateRE = /^(?:(\d\d?)-(%m)-(\d{4})|(%m)-(\d\d?)-(\d{4})|(\d{4})-(%m)-(\d\d?))$/;
  if (!months)
    months = 'jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec';

  dateRE = RegExp (('' + dateRE).replace (/%m/g, months).slice (1, -1), 'i');

  date = date.match (dateRE) || [date];

  return date.length == 1 ? 
    date[0] :  // Return string if parse error
    [date[1] || date[4] || date[7], date[2] || date[5] || date[8], date[3] || date[6]|| date[9]];
}


console.log (parseDate ("13-feb-2014"));
console.log (parseDate ("Feb-13-2014"));
console.log (parseDate ("2014-FEB-13"));
console.log (parseDate ("1-feb-2014"));
console.log (parseDate ("Feb-1-2014"));
console.log (parseDate ("2014-FEB-1"));
console.log (parseDate ("01-fev-678"));

显示

["13", "feb", "2014"]
["Feb", "13", "2014"]
["2014", "FEB", "13"]
["1", "feb", "2014"]
["Feb", "1", "2014"]
["2014", "FEB", "1"]
"01-fev-678"