I have a date and a format for that date, given by the user. (d.m.yyyy and 15.10.2021 used for this example)
const format = dateFormat || 'yyyy-mm-dd';
From that format, I need to get the position of the year, month and day, so that I can use that position on the date.
const year = /y{4}|y{2}/.exec(format);
const month = /m{1,2}/.exec(format);
const day = /d{1,2}/.exec(format);
Everything works so far, but when i try to get the position of year from my date:
const yearVal = date.substring(year.index, year.index year[0].length);
year.index
is 4 when it should be 6. So instead of 2021
, i get 0.20
It's like index
does not include the dots, but how would that make any sense!?
This is where I got the idea: Return positions of a regex match() in Javascript?
Am I using index
wrong, or what went wrong with this?
EDIT: Some people understood that the format "d.m.yyyy" was a typo, or means that there is only one number. I understand the confusion, so lets clear that out. Libraries like Luxon or node-dateformat define the difference between "d" and "dd" like this:
"d" Day of the month as digits; no leading zero for single-digit days.
"dd" Day of the month as digits; leading zero for single-digit days.
CodePudding user response:
You could generate a regex from the pattern like this:
format.replace(/([ymd])\1*/g, (match, ymd) => `(?<${ymd}>${'\\d'.repeat(match.length)})`);
yyyy-mm-dd
will become /(<?y>\d\d\d\d)-(<?m>\d\d)-(<?d>\d\d)/
, then you can extract the year/month/day using group names:
function getDates(format, date) {
const regex = new RegExp(format.replace(/([ymd])\1*/g, (match, ymd) => `(?<${ymd}>${'\\d'.repeat(match.length)})`));
const result = date.match(regex);
if(result) {
const { y: year, m: month, d: day } = result.groups;
return { year, month, day };
}
}
console.log(getDates('yyyy-mm-dd', '2021-10-15'));
console.log(getDates('dd/mm/yyyy', '15/10/2021'));
console.log(getDates('mm-dd-yy', '10-15-21'));
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
This is solution is not smart. You can't easily add hours and minutes to this. But at least it works.
function dateFromString(date, dateFormat) {
const format = dateFormat || 'yyyy-mm-dd';
let parts = date.match(/(\d )/g); // get all groups of numbers
// parse format
const year = /y{4}|y{2}/.exec(format).index;
const month = /m{1,2}/.exec(format).index;
const day = /d{1,2}/.exec(format).index;
// order the parts
if (year > month) {
if (month > day) {
parts = parts.reverse();
} else if (day > year) {
[parts[0], parts[1]] = [parts[1], parts[0]];
} else {
[parts[0], parts[1], parts[2]] = [parts[2], parts[0], parts[1]];
}
} else if (month > day) {
if (day > year) {
[parts[1], parts[2]] = [parts[2], parts[1]];
} else {
[parts[0], parts[1], parts[2]] = [parts[1], parts[2], parts[0]];
}
}
// make sure year is a full year
if (parts[0].length < 4) {
parts[0] = "20" parts[0];
}
return new Date(parts[0], parts[1], parts[2], 0, 0, 0, 0);
}
console.log(dateFromString("15.10.21", "d.m.yy").toString());
console.log(dateFromString("10/15/2021", "mm/dd/yyyy").toString());
console.log(dateFromString("2021-10-15", "yyyy-mm-dd").toString());
console.log(dateFromString("15@2021#10", "dd@yyyy#mm").toString());
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>