I have a array of objects like this:
arr = [
{ id: '5', Time: '01:00', status: 'grey' },
{ id: '7', Time: '12:00', status: 'grey' },
{ id: '8', Time: '12:45', status: 'green' },
]
Result I'm trying to get like this:
[
{ id: '7', Time: '12:00', status: 'grey' },
{ id: '8', Time: '12:45', status: 'green' },
{ id: '5', Time: '01:00', status: 'grey' },
]
I am doing sort like this but not working:
arr = arr.sort(function (a, b) {
var a1 = a.Time;
var b1 = b.Time;
if (a1 == b1) return 0;
return a1 > b1 ? 1 : -1;
});
While debug I noticed for example arr[0].Time > arr[1].Time gives me false, but "1:00" > "12:00" gives me true.
My debug console is below.
I am using Chrome and Firefox and both giving same results. Any idea?
You can convert them to a Date object.
const birthday = new Date('1995-12-17T03:24:00') // change 03:24
Then you can compare two dates. in one go
arr = [{
id: '5',
Time: '01:00',
status: 'grey'
},
{
id: '7',
Time: '12:00',
status: 'grey'
},
{
id: '8',
Time: '12:45',
status: 'green'
},
]
arr.sort(function(a,b) {
var date1 = (new Date("2000-01-01T" + a.Time + ":00")).getTime()
var date2 = (new Date("2000-01-01T" + b.Time + ":00")).getTime()
return (date1 < date2 ? -1 : (date1 > date2 ? 1 : 0))
})
console.log(arr)
Since you say all of these times are in PM, 12-hour notation is not zero-based (12, 1, 2, ... 11). It's probably easiest to convert these times to a zero-based notation, in which case 00:00 and 00:45 both come before 01:00.
To achieve this we can simply take the remainder of the hours if we divide it by 12.
const zeroBasedHour = hour % 12; // 0-11, instead of 12, 1-11
Let's create a function that does the conversion and adds the minutes in decimal form.
// 12-hour notation without am/pm.
// The initial 0 in 03:45 is optional.
function decimalTime(timeNotation) {
const [, hours, minutes] = timeNotation.match(/^(\d?\d):(\d\d)$/);
return parseInt(hours, 10) % 12
+ parseInt(minutes, 10) / 60;
}
This function would convert 12:00 to the decimal value 0. 12:45 is converted to the decimal value 0.75. And 01:00 is converted into 1. This makes sorting the array based on time alone very easy.
const arr = [
{ id: '5', Time: '01:00', status: 'grey' },
{ id: '7', Time: '12:00', status: 'grey' },
{ id: '8', Time: '12:45', status: 'green' },
];
arr.sort((a, b) => decimalTime(a.Time) - decimalTime(b.Time));
console.log(arr);
function decimalTime(timeNotation) {
const [, hours, minutes] = timeNotation.match(/^(\d?\d):(\d\d)$/);
return parseInt(hours, 10) % 12
+ parseInt(minutes, 10) / 60;
}
Note that the above assumes times are all either AM or PM, but not a mix of the two. You can very easily add AM/PM support by adding an additional 12 to final value if the provided time is PM. Do note that the function below no longer accepts a time without AM/PM.
// 12-hour notation with am/pm.
// The initial 0 in 03:45 is optional.
// The space between the time and am/pm is also optional.
// am/pm is case insensitive.
function decimalTime(timeNotation) {
const modifiers = { am: 0, pm: 12 };
const [, hours, minutes, modifier] =
timeNotation.match(/^(\d?\d):(\d\d) ?(am|pm)?$/i);
return parseInt(hours, 10) % 12
+ modifiers[modifier.toLowerCase()]
+ parseInt(minutes, 10) / 60;
}