0

I have a string, which can come in different formats:

01.01.2020
01/01/2020
01-01-2020

or
2020-01-01
2020.01.01
2020/01/01


Now if I try doing

const date = new Date(myDateString); 

I will in some cases get an error "Invalid Date". How can I cover all scenarios and transform any scenario into a valid date?

It seems like the new Date(), only takes the format Y-m-y?, even though the other cases are also "valid" dates?

VLAZ
  • 26,331
  • 9
  • 49
  • 67
viewist
  • 77
  • 1
  • 7
  • If your incoming dates are not always in the same format, then I don't think you can do anything useful without also having the format be passed in with the date. Otherwise you have no way of knowing if months and days are swapped. – maru Feb 04 '22 at 15:46
  • [What are valid Date Time Strings in JavaScript?](https://stackoverflow.com/q/51715259) | [Check if a string is a date value](https://stackoverflow.com/q/7445328) - just because the Date construct accepts a string, doesn't really mean it's "valid". It just means that *this* implementation accepts *this* particular format at *this* particular time. Because handling non-standard date strings is implementation dependent. – VLAZ Feb 04 '22 at 15:47

4 Answers4

0

You can split the string on the known delimiters and then see whether the first part has four digits. If so, you know it's year-month-day. If not, you know it's month-day-year. You can then construct the date accordingly:

const dateStrings = [
  "10.31.2020",
  "10/31/2020",
  "10-31-2020",
  "2020-10-31",
  "2020.10.31",
  "2020/10/31",
]

function parseDateStr(str) {
  // split on dots, dashes, and slashes
  const parts = str.split(/[./-]/);

  // mm-dd-yyyy
  const [year, month, day] = parts[0].length > 2 ? parts : [parts[2], parts[0], parts[1]];

  // alternate for dd-mm-yyyy
  // const [year, month, day] = parts[0].length > 2 ? parts : parts.reverse();
  
  // construct and return the date. (month is 0 based)
  return new Date(year, month - 1, day);
}

const results = dateStrings.map(parseDateStr);

console.log(results);
ray
  • 26,557
  • 5
  • 28
  • 27
  • How do you know it isn't day-month-year? – maru Feb 04 '22 at 15:50
  • That's not something you can know just from the input, obviously, but I assume OP knows how to interpret strings in that ambiguous format, and it's always one way or the other. Easy to update this to do day-month-year instead if that's the assumption. – ray Feb 04 '22 at 15:52
  • Almost, but as maru says, this won't work with a date like: 01.31.2020, which will not give the correct date :( – viewist Feb 05 '22 at 08:32
  • The problem is that I don't know which format will come in, I just know it will be one of the mentioned... – viewist Feb 05 '22 at 08:32
  • @viewist I've updated the snippet to parse `mm-dd-yyyy` instead of `dd-mm-yyyy`. If you don't know whether the day or month comes first in a `xx-xx-xxxx` date there's no way for the code to know that either. – ray Feb 05 '22 at 16:36
0

You can moment to do that. But you need to know which format is used.

https://stackoverflow.com/a/44134515/3573340

Clem
  • 2,150
  • 15
  • 17
0

Date() constructor is accurate if it's parameters are YYYY, MM, DD. The dates of Jan 1, 2020 should go like this:

new Date(2020, 0, 1) // Month is 0 index, so MM -1
  • Given an array of strings .map() and split() each by .-/ delimitters, resulting in sub-arrays of 3 strings from each string:

    strArr.map(str => str.split(/[-./]/))
    
  • then .flatMap() to catch any array that starts with 2 digits and .reverse() it:

    .flatMap(sub => sub[0].length === 2 ? [sub.reverse()] : [sub])
    
  • Finally, .flatMap() each sub-array into the Date() constructor:

    .flatMap(sub => [new Date(+sub[0], +sub[1] - 1, +sub[2])])
    

const jan1_2020 = [
  `01.01.2020`,
  `01/01/2020`,
  `01-01-2020`,
  `2020-01-01`,
  `2020.01.01`,
  `2020/01/01`
];

const formatDate = strArr => strArr.map(str => str.split(/[-./]/)).flatMap(sub => sub[0].length === 2 ? [sub.reverse()] : [sub]).flatMap(sub => [new Date(+sub[0], +sub[1] - 1, +sub[2])]);


let x = formatDate(jan1_2020);
console.log(x);
zer00ne
  • 41,936
  • 6
  • 41
  • 68
-1

JavaScript will parse the dates in following formats:

ISO Date - YYYY-MM-DD

Short Date - YYYY/MM/DD

Long Date - Jan 01 2022

Some other versions of the dates also might also work but the best practice is to limiting your formats to ISO format. For more on js date formats refer this

JaivBhup
  • 792
  • 4
  • 7
  • Of these three, only the first one is a standard date string. The other two are non-standard. Thus parsing of those formats is implementation dependent - you might get the correct date, you might get some valid date which is not the one you meant, or you can get an invalid date. – VLAZ Feb 04 '22 at 15:55
  • Yes the first one is the standard date string but i think all these dates will parse a correct date every time. Right? Dates in js has always been wired but if someone is using js on browser and nodejs limiting formats to this type is the best possible way to approach dates. I think. – JaivBhup Feb 04 '22 at 16:02
  • 1
    "*i think all these dates will parse a correct date every time. Right?*" No - non-standard date strings have implementation dependent behaviour. There is no guarantee they'd work the same on different platforms. "*if someone is using js on browser and nodejs limiting formats to this type is the best possible way to approach dates.*" correct. And the only useful common format is [the simplified ISO 8601 one defined in the spec](https://tc39.es/ecma262/#sec-date-time-string-format). All non-spec compliant formats are not guaranteed to produce the same results. – VLAZ Feb 04 '22 at 16:06
  • Oh I see that helps a lot and will change my way of how i approach date problems. Thank you very much @VLAZ – JaivBhup Feb 04 '22 at 16:08