1

I am getting date string like dd-MMM-yyyy or MMM-dd-yyyy format. All I want is to extract day, month and year using one regular expression (without using any 3rd party plugin). Is it possible?

Shiela
  • 500
  • 1
  • 7
  • 20
Prateek
  • 4,220
  • 1
  • 17
  • 22
  • @wared: I would assume it is `jan`, `feb`, `mar`, etc. maybe in uppercase – musefan Feb 13 '14 at 09:20
  • e.g. "12-Feb-2012" or "Feb-12-2012" – Prateek Feb 13 '14 at 09:21
  • 1
    try to split dd-MMM-yyyy then at index 0 u ve axact dd at index 1 u ve mmm and at index 2 u ve yyyy – Hisham Feb 13 '14 at 09:24
  • to me, this looks like a really bad idea. prefer simple, clean code. – Karoly Horvath Feb 13 '14 at 09:44
  • Not a duplicate : *a single regular expression* for *two different formats*. –  Feb 14 '14 at 14:19
  • Not a duplicate: the user wants to parse a string. This is exactly what was suggested in the correct answer of that question, but the OP never would have found it using his question. See http://meta.stackexchange.com/questions/139961/whats-the-policy-on-closing-unique-questions-with-overlapping-but-non-duplicat – Jan Doggen Feb 14 '14 at 14:45
  • @JanDoggen The supposedly duplicated question has nothing to do with the current question anyway, apart "parse" and "date". Well folks, you should close every question containing such words... –  Feb 14 '14 at 15:22
  • 2
    @MuhammadHisham Please don't use SMS slang here. Please note that your comment does not answer the question : http://stackoverflow.com/questions/21749728/how-to-parse-dd-mmm-yyyy-or-mmm-dd-yyyy-date-string-using-single-regular-exp#comment32954065_21749728. –  Feb 14 '14 at 15:51
  • Updated : http://stackoverflow.com/a/21750042/1636522. Enjoy :) –  Feb 15 '14 at 08:58
  • 1
    @People : who has marked this question as duplicate, must know that other duplicate one should solve my problem. The link which you guys have mentioned is not addressing my problem at all, because this question itself is different than just parsing date by specifying particular date format. – Prateek Feb 15 '14 at 19:24
  • @Prateek In case you're not already aware of this trick : you can upvote a comment in order to pull it up to the top of the comments stack. The goal is to increase its visibility. –  Feb 16 '14 at 07:17
  • @Prateek You should also edit your question, even if it's already resolved, in order to draw people attention and make them want to vote for reopening. –  Feb 16 '14 at 07:22
  • @Prateek I mean, you have to figure out that your question is not attractive in its current state. Two lines of explanations are far from being enough to deserve community attention. Indeed, since your requirements are not clearly exposed, you're rather likely to be downvoted, or closed, even for the wrong reason. What happened is not so surprising after all. –  Feb 16 '14 at 08:52

4 Answers4

7

I would invert month and day positions first do get the same format for all dates :

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+)/ matches only "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)

To go further

Now that you know how to split the input, I'd like to go further by turning the result into a Date object. Firstly, let's open the Chrome's console to quick check if the input is parseable as is :

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

Apparently, Chrome can get this job done properly. This is great, but other implementations do not necessarily behave the same way, you should better rely on the specifications. Luckily, someone has already checked them for you : undocumented supported Date.parse format?

To summarize roughly, the ability to parse your own formats is likely to vary across implementations. There is only one reliable format, namely YYYY-MM-DDTHH:mm:ss.sssZ, where every letter - except "T" and "Z" - stands for a digit.

To be precise, MM is expected to be a number. If you want to be sure that your input will be parsed properly, you have to find a way to turn the month part into a number. Let's try something :

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"]

Not so bad, and the job is almost done. Indeed, as mentionned in the specs, the parser accepts date only formats like YYYY-MM-DD, which is very easy to achieve :

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

Let's see what the console says :

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

Done!


To close the case

Alternatively, you could do this :

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]);

You could go even further by hiding the process into a function :

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);
};

Usage examples :

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

Feel free to ask for details.

Community
  • 1
  • 1
2

Yes, that's certainly possible, but you will have to check which capturing groups matched:

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

If groups 1 through 3 are defined after the match, then dd-MMM-yyyy was used, if groups 4 through 6 are defined, then the other was used.

This regex doesn't do any plausibility checking, so it would match 99-XXX-9999 as well, but that's a different problem.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
0

First you can convert dd-MMM-yyyy or MMM-dd-yyyy format to dd-MMM-yyyy .

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

Then you can use REGEX : /(\d+)-([a-zA-Z]{3})-(\d{4})/

Code :

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

Sujith PS
  • 4,776
  • 3
  • 34
  • 61
-1

This variant adds the symetric YYY-mmm-dd, allows for single digit day numbers and provides for the specification of the month names for language independence.

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"));

Displays

["13", "feb", "2014"]
["Feb", "13", "2014"]
["2014", "FEB", "13"]
["1", "feb", "2014"]
["Feb", "1", "2014"]
["2014", "FEB", "1"]
"01-fev-678"
HBP
  • 15,685
  • 6
  • 28
  • 34