Date parsing from different formats? - javascript

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?

You can moment to do that. But you need to know which format is used.
https://stackoverflow.com/a/44134515/3573340

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

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

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

Related

How to get date string from day number and month number using moment?

dayNumber: 28,
monthNumber: 2,
expected output using moment "2022-02-28"
What I've tried const date = moment() .month(monthNumber) .days(dayNumber) .format("YYYY-MM-DD");
but that gives me something like "2022-03-17"
what am I doing wrong?
You have two errors in your code:
The first one is that you need to replace the days function call with date
The second one is that the argument of the month function starts from 0. So 0 is January, 1 is February etc.
So, what you need to do in order to get 2022-02-28 is the following:
const date = moment() .month(1) .date(28) .format("YYYY-MM-DD");
.month expects values from 0-11. See: https://momentjs.com/docs/#/get-set/month/
.days is day of week, .date is day of month. See: https://momentjs.com/docs/#/get-set/day/ and https://momentjs.com/docs/#/get-set/date/
const date = moment().month(monthNumber-1).date(dayNumber).format("YYYY-MM-DD");
You can also create a moment instance with an array of numbers that mirror the parameters passed to new Date(), e.g. [year, month, day].
See moment/parsing/array
NB: Month is zero-indexed.
const year = 2022;
const monthNumber = 2;
const dayNumber = 28;
console.log(moment([year, monthNumber - 1, dayNumber]).format('YYYY-MM-DD'))
<script src="https://momentjs.com/downloads/moment.js"></script>

Sort Data and Time String in Javascript [duplicate]

This question already has answers here:
Why does Date.parse give incorrect results?
(11 answers)
Closed 1 year ago.
I Know there are lot of answers out there to sort date and time. But in every answer, they sort only date or they sort only time. I can't find the answer which sorts both date and time string.
Here's the Code I tried:
var x = [ '29/09/2020 11:55:56', '04/08/2021 11:57:06', '30/09/2019 15:19:49', '04/08/2021 13:57:06' ]
x.sort((a, b) => new Date(b).getTime() - new Date(a).getTime()).reverse();
console.log(x)
Output I got:
["04/08/2021 13:57:06", "30/09/2019 15:19:49", "04/08/2021 11:57:06", "29/09/2020 11:55:56"]
Required Output:
["04/08/2021 13:57:06","04/08/2021 11:57:06", "29/09/2020 11:55:56", "30/09/2019 15:19:49", ]
I searched whole day. Please Help me with some solutions to fix this.
The problem is that Date uses a yyyy/mm/dd format instead of a dd/mm/yyyy format. So all your Date objects are Invalid Date.
P.S. If you sort but have to reverse the order afterwards, just reverse the subtractions.
if momentjs an option:
var x = [ '29/09/2020 11:55:56', '04/08/2021 11:57:06', '30/09/2019 15:19:49', '04/08/2021 13:57:06' ];
x.sort((a, b) => moment(b,"DD-MM-YYYY hh:mm:ss") - (moment(a,"DD-MM-YYYY hh:mm:ss")));
console.log(x)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
I think this is a very hard task when you try to compare date and time in strings. And would take to much time when executing. Instead i would convert date and times to timestamp format then compare. To convert a date string to a timestamp format i referred to the answer on this stackoverflow question
const dates = [ '29/09/2020 11:55:56', '04/08/2021 11:57:06', '30/09/2019 15:19:49', '04/08/2021 13:57:06' ];
dates.sort((date1,date2) => {
var dateTimeParts = date1.split(' '),
timeParts = dateTimeParts[1].split(':'),
dateParts = dateTimeParts[0].split('/'),
date1;
date1 = new Date(dateParts[2], parseInt(dateParts[1], 10) - 1, dateParts[0], timeParts[0], timeParts[1], timeParts[2]);
var dateTimeParts2 = date2.split(' '),
timeParts2 = dateTimeParts2[1].split(':'),
dateParts2 = dateTimeParts2[0].split('/'),
date2;
date2 = new Date(dateParts2[2], parseInt(dateParts2[1], 10) - 1, dateParts2[0], timeParts2[0], timeParts2[1], timeParts[2]);
return date1.getTime() / 1000 - date2.getTime() / 1000
});
console.log(dates);
Date and time are not separate in the context of a javascript Date object, internally they are just stored as millisecond offsets. But, you can't rely on Date parsing strings for you. Write a custom parser for you specific date-time strings and then then simply subtract dates.
There's no need for reverse() either, simply switch the subtraction to change direction.
const x = [ '29/09/2020 11:55:56', '04/08/2021 11:57:06', '30/09/2019 15:19:49', '04/08/2021 13:57:06' ];
const parse_date_string = (str) => {
const [date, time]= str.split(' ');
const [day, month, year] = date.split('/');
const [hr, min, sec] = time.split(':');
return [year, (month - 1), day, hr, min, sec].map(Number);
}
x.sort((a, b) => new Date(...parse_date_string(b)) - new Date(...parse_date_string(a)));
console.log(x)

Convert a string in date (so formatted: month day, year hh:mm:ss)

I know there are tons of questions about date formatting, but I'm stuck with a conversion.
I have a string so formatted: mag 11, 2021 2:31:00 pm ("mag" is the abbreviation of May in italian).
I want to convert it in date so I can change it to the format DD/MM/YYYY HH:MM:ss (in this case "11/05/2021 14:31").
I tried to use the new Date or Date.parse functions, but in console it returns me the error 'Invalid date'.
Here's what I tried:
let a = "mag 11, 2021 2:31:00 pm";
let b = new Date(a);
console.log(b);
console output -----> Invalid Date
let a = "mag 11, 2021 2:31:00 pm";
let b = Date.parse(a);
console.log(b);
console output -----> NaN
Any idea? Thx
This question has been answered many times before, the following is for this specific case.
A Date object isn't required, the timestamp can be split into its parts, the month name converted to a number then the parts reformatted, e.g.
/*
mag 11, 2021 2:31:00 pm => DD/MM/YYYY HH:MM:ss
e.g. 11/05/2021 14:31
*/
function reformatDate(date) {
let z = n => ('0'+n).slice(-2);
let months = [,'gen','feb','mar','apr','mag','giu',
'lug','ago','set','ott','nov','dic'];
let [M,D,Y,h,m,s,ap] = date.toLowerCase().split(/\W+/);
h = h%12 + (ap == 'am'? 0 : 12);
M = months.indexOf(M);
return `${z(D)}/${z(M)}/${Y} ${z(h)}:${m}`;
}
console.log(reformatDate('mag 11, 2021 2:31:00 pm'));
In the OP, the format tokens include seconds but the example doesn't. Adding seconds to the above output if required should be easy.
The above can be modified to build the month names array based on a specific language, but then language to use would need to be passed to the function too.
If a library is used to parse the string, the language and format must be specified for the parser (e.g. date-fns allows setting the parse and format language), then the language and format of the output. So unless other date manipulation is required, a library may be more trouble than it's worth.
let now = new Date();
var dateString = moment(now).format('YYYY-MM-DD');
console.log(dateString) // Output: 2020-07-21
var dateStringWithTime = moment(now).format('YYYY-MM-DD HH:MM:SS');
console.log(dateStringWithTime) // Output: 2020-07-21 07:24:06
You can check here for all details of dateTime for Javascript

Converting to UTC is giving NaN error in Javascript

I have below code which is giving NaN error when i am trying to convert it into Date.UTC format.
let sDate = "2019, 10, 19";
let min = Date.UTC(sDate);
whereas below code is giving me correct result
let min = Date.UTC(2019, 10, 19);
but as per my need, sDate is supposed to be passed as parameter because it may vary. How to correct this?
If you refer docs, Date.UTC does not take date string as an argument. It takes individual parts.
Date.UTC(year[, month[, day[, hour[, minute[, second[, millisecond]]]]]])
So when you pass Date.UTC('2019, 10, 19'), you are just passing year's value and not other values. Year's value is also not number. Hence NaN.
If you wish to create UTC date using date string, you will have to split values.
The date arguments are not a string:
let sDate = "2019, 10, 19";
let min = Date.UTC(...sDate.split(', '));
console.log(new Date(min));
You can use String.split (with destructuring) to convert a known date string format into year, month, day. You have do subtract 1 from the month value when passing to the Date.UTC function since this accepts a month value from 0 to 11 (January to December).
If you want to do more sophisticated Date parsing I strongly recommend you use a library such as Moment.js. This is well tested and has a very flexible API.
const sDate = "2019, 10, 19";
const [year, month, day] = sDate.split(",");
console.log("Date components:", {year, month, day});
// Date constructor takes a month from 0: January to 11: December
const utcDate = Date.UTC(year, month - 1, day);
console.log("Date (ISO):", new Date(utcDate).toISOString());
console.log("Date (toLocaleString):", new Date(utcDate).toLocaleString("en", { timeZone: "UTC"}));
The Date.UTC() method accepts parameters similar to the Date constructor but treats them as UTC
Date.UTC(year[, month[, day[, hour[, minute[, second[, millisecond]]]]]])
you can't use string directly
getData=(d)=>{
return [d.getFullYear(),d.getMonth(),d.getDate(), d.getHours(),d.getMinutes()];
};
let splited = getData(new Date('2019, 10, 19'))
console.log(new Date(Date.UTC(...splited)));

Javascript to compare two dates, from strings, begin <= end

I get two strings formated like (Brazilian Format): "DD/MM/YYYY", I need to compare both. Since the first field is the begin and the last is the end,
My validation is begin <= end
Date.new(begin) is generating 'invalid date' even on ISO !
Don't use Date.new. Use new Date(). Because of the format of your date string, I would recommend grabbing each field individually and passing them into the constructor:
var startYear = parseInt(document.getElementById('startYear'), 10);
var startMonth = parseInt(document.getElementById('startMonth'), 10) - 1; // as per Residuum's comment
var startDay = parseInt(document.getElementById('startDay'), 10);
var start = new Date(startYear, startMonth, startDay);
etc. If you're handed a date string, then you can use fuzzy lollipop's method to get each field from the string. I'm not sure if the Date constructor will accept unparsed strings for the individual fields, however.
The, once you have the two dates you'd like to compare, just compare their values in milliseconds since the epoch:
function isValid(start, end) {
return start.getTime() < end.getTime();
}
There's a nice date handling library called datejs which has a parseExact(dateStr, format) method.
you can do this, if you know your date will always be formatted the same way dd/mm/yyyy
today = "23/02/1001";
dateComponents = today.split("/");
date = new Date(dateComponents[2], dateComponents[1] - 1, dateComponents[0]);
but a better solutions is to look at this page there is Datejs which is a good alternative to date processing.
Quick 'n dirty :
function is_valid (start , end) {
return start.split('/').reverse().join('') <= end.split('/').reverse().join('') ;
}
That is, split the date into components, reverse the order join them again and do a string comparison.
Edit: As noted in the comment, of course this won't work if your month/days smaller than 10 are not zero padded.
The new 'hotness' in JS time world: http://momentjs.com/
Fits this use-case as well
Here are all available constructors for date objects in Javascript:
dateobject = new Date(); // returns date of current time stamp
// on the browser
dateobject = new Date("Month Day, Year Hours:Minutes:Seconds");
dateobject = new Date(Year, Month, Day);
dateobject = new Date(Year, Month, Day, Hours, Minutes, Seconds);
dateobject = new Date(Milliseconds);
Pick the one you try to use, but I would go for new Date(Year, Month, Day); in your case.
EDIT:
Note: Monthis zero-based in Javascript, so January 1 2010, will be new Date(2010, 0, 1) and December 31 2011 is new Date(2010, 11, 31).

Categories