Sorting dates which are not in right format - javascript

I am getting input from the excel sheet and the dates are not in proper ISO format which can be operated on i.e the column looks something like below, I am trying to sort it using converting it to proper date using javascript date and moment however I am not getting proper output I can use a second opinion on this matter.
Input ["28/02/23","31/12/21","31/05/21","30/09/23","31/10/22","30/09/21","30/06/23","31/05/22","30/04/21","31/07/21","30/06/21","28/02/22","31/12/22","30/06/22","31/08/21","30/04/22","31/10/20","31/08/22","31/07/22","31/05/23","31/01/23","30/04/23","30/09/22","28/02/21","30/11/20","30/11/21","31/01/21","31/03/23","31/01/22","31/07/23","31/12/20","31/03/21","31/08/23","30/11/22","31/10/21","31/03/22","30/09/20"]
method I wrote
dateCompare = (d1, d2) => {
let d1Component = d1.toString().split('/')
, d2Component = d2.toString().split('/')
, rD1 = new Date(parseInt(20 + d1Component[2]), d1Component[1] - 1, d1Component[0])
, rD2 = new Date(parseInt(20 + d2Component[2]), d2Component[1] - 1, d2Component[0])
return moment(rD1).isAfter(moment(rD2))
}
The output I am getting from above method is ["30/09/35", "28/02/23", "31/05/21", "31/12/21", "31/10/22", "30/09/21", "30/09/20", "31/05/22", "30/04/21", "31/07/21", "30/06/21", "28/02/22", "31/12/22", "30/06/22", "31/08/21", "30/04/22", "31/10/20", "31/08/22", "31/07/22", "31/03/22", "31/01/23", "31/10/21", "30/09/22", "28/02/21", "30/11/20", "30/11/21", "31/01/21", "30/11/22", "31/01/22", "31/03/21", "31/12/20", "31/01/37", "31/07/23", "31/03/23", "30/04/23", "31/05/23", "30/06/23", "30/04/37", "31/10/23", "31/08/23", "30/09/23", "30/06/37", "29/02/24", "30/11/23", "31/12/23", "31/01/24", "31/08/37", "31/07/24", "31/03/24", "30/04/24", "31/05/24", "30/06/24", "30/11/37", "31/01/25", "31/08/24", "30/09/24", "31/10/24", "30/11/24", "31/12/24", "31/03/38", "31/08/25", "28/02/25", "31/03/25", "30/04/25"] which I believe is not at all sorted in any ways.

A comparison function should return a negative number for less than, a positive number for greater than, and 0 for equal to, not true/false. Also, since you're already using moment, use it to parse the dates as well:
function dateCompare(d1, d2) {
const d1Parsed = moment(d1, "DD/MM/YY");
const d2Parsed = moment(d2, "DD/MM/YY");
if (d1Parsed.isBefore(d2Parsed)) {
return -1;
} else if (d1Parsed.isSame(d2Parsed)) {
return 0;
} else {
return 1;
}
}
Alternatively, take the difference of their timestamps (if d1Parsed is before d2Parsed then its timestamp will be less, so the resulting subtraction will be negative, if they're equal it'll be 0, and if it's greater it'll be positive, doing the same thing as the previous code):
function dateCompare(d1, d2) {
const d1Parsed = moment(d1, "DD/MM/YY");
const d2Parsed = moment(d2, "DD/MM/YY");
return d1Parsed.valueOf() - d2Parsed.valueOf();
}

You can use map and convert the dates, than sort them.
const dates = ["28/02/23", "31/12/21", "31/05/21", "30/09/23", "31/10/22", "30/09/21", "30/06/23", "31/05/22", "30/04/21", "31/07/21", "30/06/21", "28/02/22", "31/12/22", "30/06/22", "31/08/21", "30/04/22", "31/10/20", "31/08/22", "31/07/22", "31/05/23", "31/01/23", "30/04/23", "30/09/22", "28/02/21", "30/11/20", "30/11/21", "31/01/21", "31/03/23", "31/01/22", "31/07/23", "31/12/20", "31/03/21", "31/08/23", "30/11/22", "31/10/21", "31/03/22", "30/09/20"];
const convertedDates = dates.map(d => {
var day = d.split("/")[0];
var month = d.split("/")[1];
var year = d.split("/")[2];
return "20" + year + '-' + ("0" + month).slice(-2) + '-' + ("0" + day).slice(-2);
})
.sort();
;
console.log(convertedDates);

Without using a third party library, you could convert the custorm date to an ISO 8601 compliant date string and sort with
String#localeCompare.
const
getISO = string => string.replace(/(\d\d)\/(\d\d)\/(\d\d)/, '20$3-$2-$1'),
data = ["28/02/23", "31/12/21", "31/05/21", "30/09/23", "31/10/22", "30/09/21", "30/06/23", "31/05/22", "30/04/21", "31/07/21", "30/06/21", "28/02/22", "31/12/22", "30/06/22", "31/08/21", "30/04/22", "31/10/20", "31/08/22", "31/07/22", "31/05/23", "31/01/23", "30/04/23", "30/09/22", "28/02/21", "30/11/20", "30/11/21", "31/01/21", "31/03/23", "31/01/22", "31/07/23", "31/12/20", "31/03/21", "31/08/23", "30/11/22", "31/10/21", "31/03/22", "30/09/20"];
data.sort((a, b) => getISO(a).localeCompare(getISO(b)));
console.log(data);

Related

Parsing string into Time format JavaScript

I have the following time format 2h 34m 22s and I'm parsing it as 02:34:22 using this code:
const splitterArray = '2h 34m 22s'.split(' ');
let h = '00', m = '00', s = '00';
splitterArray.forEach(val => {
if (val.includes('h')) {
h = val.replace('h', '');
} else if (val.includes('m')) {
m = val.replace('m', '');
}
else if (val.includes('s')) {
s = val.replace('s', '');
}
});
console.log(`${h}:${m}:${s}`);
This also handles the case when there's only minutes and seconds, or only hours and seconds or only hours and minutes.
Just checking if there's a better way to do it like a library or so (maybe to accept days too).
You could match in wanted order and get the result with colons.
function convert(string) {
return Array
.from('hms', p => (string.match(new RegExp(`\\d+(?=${p})`))?.[0] || '') .padStart(2, '0'))
.join(':');
}
console.log(convert('2h 34m 22s'));
I suggest using the moment library. it has plenty of examples and documentation for all of your time formatting and parsing needs:
https://momentjs.com/

Get the difference between two variables

I have an object and Hours is saved as a string . I need to convert the string to hours and then get the difference between the 2 variables.
const groupSchedule=[
{"days":"sat","Hourfrom":"15:00","Hourto":"19:00"},
{"days":"sun","Hourfrom":"15:00","Hourto":"19:00"},
{"days":"mon","Hourfrom":"15:00","Hourto":"19:00"},
]
function numberOfHoursInWeek(groupSchedule) {
let hours = 0;
for (const gSchedule of groupSchedule) {
let hour = gSchedule.Hourto.to - gSchedule.Hourfrom;
console.log(hour);
hours += hour;
}
return hours;
}
Problem in converting string to hour (NAN)
I tried to write in a very verbose way. You could do something like this:
const hoursTo = "19:33";
const hoursFrom = "14:55";
const hoursToArray = hoursTo.split(":");
const hoursFromArray = hoursFrom.split(":");
const hoursToDate = new Date(0, 0, 0, hoursToArray[0], hoursToArray[1], 0, 0);
const hoursFromDate = new Date(0, 0, 0, hoursFromArray[0], hoursFromArray[1], 0, 0);
const difference = Math.abs(hoursToDate - hoursFromDate) / 36e5;
console.log(hours) //4.633333333333334;
The basic issue is that you are taking gSchedule.hourTo and gSchedule.hourFrom and trying to perform arithmetic with them when they are string values. You need to split the string and extract a numeric type to perform this type of mathematical calculation.
In this case the relevant numeric portion is the hours portion of the HH:MMstring, so using the split function with : as a delimiter will return a list of two string, one string of hours and one of minutes. We can then parse the hours string to get an int, float, or other numeric type.
//split time strings on the ':'
let hrToSplit = gSchedule.hourTo.split(':')
let hrFromSplit = gSchedule.hourFrom.split(':')
//parse time strings to extract hour as int
let hrToNum = parseInt(hrToSplit[0], 10)
let hrFromNum = parseInt(hrFromSplit[0], 10)
//perform whatever math is needing using the numbers themselves, not the strings
console.log(hrToNum + hrFromNum)
If you want to do some further reading on different approaches beyond the answers you got here, this is a similar question that may be useful to reference.

Add 0 before single digit number of time format [duplicate]

This question already has answers here:
Adding "0" if clock have one digit
(9 answers)
Closed 3 years ago.
How can we add 0 before single digit number of time format.
Like if I have a time "0:3:25" (hh:mm:ss) format to convert into "00:03:25"
You shouldn't overcomplicate this:
const time = "0:3:25";
const paddedTime = time.split(':').map(e => `0${e}`.slice(-2)).join(':')
console.log(paddedTime)
split the string by semicolons (:), that yields an array (hours, minutes, seconds). map this array with a function that adds a 0 before every item in the array, and slice the last two digits (you get an array again). Then join the resulting array by semicolons (and you get a string).
Or you could use a regex instead of the split:
const time = "0:3:25";
const paddedTime = time.match(/\d+/g).map(e => `0${e}`.slice(-2)).join(':')
console.log(paddedTime)
The last part is the same with regex (map, slice, join).
And you also could use the padStart() (JavaScript built-in function):
const time = "0:3:25";
const paddedTime = time.split(':').map(e => e.padStart(2, 0)).join(':')
console.log(paddedTime)
padStart() on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
You can do something like below (Explanations included):
const time = '0:3:25';
const correctedTime = parseTime(time);
console.log(correctedTime);
function parseTime(time){
return time
.split(':') // Split them into array as chunk of [hour, minute, second]
.map(pad) // Map them with `pad` function below
.join(':'); // Join them back into 'hh:mm:ss'
}
function pad(n){
return parseInt(n) < 10 // If number less than 10
? '0' + n // Add '0' in front
: n; // Else, return the original string.
}
you can add split the existing time string on the ":", then for each portion, add the "0" then take the last two characters. Then simply join the portions back into a striung.
let time = "0:3:25";
function updateTime(){
let newTimePortions = [];
let timePortions = time.split(":");
timePortions.forEach(function(portion,index) {
newTimePortions[index] = ("0" + portion).slice(-2)
})
return newTimePortions.join(':')
}
console.log(updateTime()); // gives 00:03:25
Please try below code
var dateinfo="0:3:25";
var newdate=dateinfo.split(":");
var hdate=newdate[0];
var mdate=newdate[1];
var sdate=newdate[2];
if(hdate.length == 1 ){
hdate="0"+hdate;
}
if(mdate.length == 1 ){
mdate="0"+mdate;
}
if(sdate.length == 1 ){
sdate="0"+sdate;
}
dateinfo=hdate+":"+mdate+":"+sdate;
This is work for me

Converting a string (150000) to time ( hh:mm:ss) in javascript

I am new to JS. Can anybody tell me whether is it possible to convert a string ( eg: "140000") to time (eg: 14:00:00) in Javascript.
You can do this:
Split your text into an array using the split method.
Map over your array and replace every item that has the index can be divided by to with the item + : using the map method.
Join your array to be string again using the join method.
Remove the last : from your result.
let convertToTime = str => str
.split("")
.map((item, index) => (index % 2 != 0) ? item + ':' : item)
.join("")
.slice(0, -1);
console.log(convertToTime("140000")); // 14:00:00
console.log(convertToTime("173003")); // 17:30:03
console.log(convertToTime("225510")); // 22:55:10
console.log(convertToTime("010201")); // 01:02:01
That's a bit tricky, because well... there is no Time object in Javascript.
There is only a Date object, although the name is kind of misleading, because the Date object contains both "Date" and "Time". There is a reason behind this seemingly confusing convention. I'm not going to go into too long of a detail, but to put it shortly, referencing "Time" is unreliable (to human brain).
For that, I'll just recommend reading this answer which explains it quite brilliantly.
Either way, this simple function will do the trick.
toDate(what){}
Upon sucessful string of time conversion, return a newly created Date object. Otherwise return -1. (or you could throw an Exception instead, up to you really)
var str = '143025';
function toDate(what){ // turns string into Date() object
var result;
if (what.length === 6) { // must be in HH:MM:SS length
var timearr = what.match(/.{1,2}/g); // splits time to HH:MM:SS array
if (timearr[0] <= 24 && timearr[1] <= 60 && timearr[2] <= 60){
return new Date('01 January 0001 ' + timearr[0] + ':'+
timearr[1] + ':' + timearr[2] + ' GMT'); // valid time format
}
}
return -1;
}
var mytime = toDate(str);
console.log(mytime.toUTCString());
Note, Date by itself is only expression of serialized numbers, if you want to return the time as result, you need to use the .toString or .toUTCString method from the Date.prototype object.

Get most current data from Array JavaScript

I have a SP2010 list which contains a column with dates. (Date created).
I pull these using Spservices which comes in the following format:YYYY.MM.DD 00:00.
In the main function which reads the list I split the date so all that remains is YYYY.MM.DD.
dateAdded = ($(this).attr("ows_DatumActualiteit")).split(" ")[0];
The dates are then pushed in to an array for later filtering.
function selectMostRecentAct(datesIn){
var dateArray = [];
dateArray.push(datesIn);
for (var i = 0; i < dateArray.length; i++) {
console.log(dateArray[i]); //spits out all the dates in the array.
};
I want to select the most recent date in this array. How can I achieve this?
This question seems similar to yours:
What is the elegant way to get the latest date from array of objects in client side?
An alternative would be to loop through the whole array and compare the dates. As far as I know, you can use the <, >, == operators with dates.
dateArray.forEach((e) => {
if (e > latestDate)
latestDate = e;
});
console.log('Latest date is: ' + latestDate);
You need to sort the values then take the first element.
I'm assuming the format of your dates, but new Date is very lenient and should accept most reasonable inputs.
const dates = [
"2018-03-01T10:30:12.000Z",
"2018-03-01T12:11:49.000Z",
"2018-03-12T15:54:49.000Z",
"2018-03-09T19:12:49.000Z",
"2018-03-03T01:41:49.000Z",
];
const selectMostRecent = dates =>
dates.sort((a, b) => new Date(b) - new Date(a))[0];
console.log(selectMostRecent(dates));
Sort wants a comparison function that returns a value, either positive, negative or zero. When you perform arithmetic on a date value it is converted to epoch time (e.g. 1522096404277, milliseconds since 01/01/1970), and then subtracting these gives us the signed value we desire.
For example,
2018-03-09T19:12:49.000Z returns 1520622769000
2018-03-03T01:41:49.000Z returns 1520041309000
And when we do 2018-03-09T19:12:49.000Z - 2018-03-03T01:41:49.000Z (but those are coerced to numbers as described above) we get 581460000, meaning that the first date is sorted above the latter one.
Maybe something like this:
dateArray
.map(d => new Date(d.replace(/\./g, "-"))) // ISO format
.sort((a, b) => b - a) // Newest to oldest, probably
[0] // First!
This uses a reusable function for max; it should work for any values that you can compare with >. Note that it requires you to set a minimum value. For strings, "" (the empty string) seems appropriate. For numbers, you could use -Infinity, although that case is already covered by Math.max. For actual dates (not these dates formatted as strings), you can choose any date that would be well before any conceivable values, perhaps something like new Date(-1e15).
const max = (min) => vals => vals.reduce((curr, val) => val > curr ? val : curr, min)
const maxDate = max('')
console.log(
maxDate(['2014.07.23', '2014.08.29', '2007.03.25', '2017.09.30', '2008.02.29'])
)

Categories

Resources