3

I have an array of objects with an hour(fc_start_time) property and I want to sort it by this property. I've tried this but it does not work for me. This is the object structure:

Object { 
         id="540-events", 
         local_id=540, 
         title="Mas Flow", 
         fc_start_time="12:30 pm"
},
Object { 
         id="531-events", 
         local_id=531, 
         title="Slowly", 
         fc_start_time="04:30 pm"
},
Object { 
         id="531-events", 
         local_id=531, 
         title="Slowly", 
         fc_start_time="08:30 am"
}

Thanks in advance.

Community
  • 1
  • 1
saRca
  • 142
  • 1
  • 10
  • 1
    possible duplicate of [Sorting objects in an array by a field value in JavaScript](http://stackoverflow.com/q/1129216/710446) – apsillers Sep 19 '14 at 12:17
  • apsillers, is the same concept, I didn't found it when research. However that solution doesn't work for my case. For example '11:00 am' and '11:00 pm' are very similar and both will be before than "12:00 pm" – saRca Sep 19 '14 at 13:56

4 Answers4

3

Dates and time, eh? I hate them. Let's try to figure this out.

How you sort an array? With help of array's sort method. By default this method sorts strings, but we need custom compare function here.

How can we compare time in strings? We can use Date object, parse time, get milliseconds from 1970, and compare them. But we have am-pm format here. So, to use Date.parse method, we need to convert time to 24 hour format first (or use Date.js library).

function convertTo24Hour(time) {

  var hours = parseInt(time.substr(0, 2));

  if(time.indexOf('am') != -1 && hours == 12) {
    time = time.replace('12', '0');
  }
  if(time.indexOf('pm')  != -1 && hours < 12) {
    time = time.replace(hours, (hours + 12));
  }

  return time.replace(/(am|pm)/, '');
}

After we get 24h time, we can parse it like so (don't look at date before time, it doesn't matter, all we care about is time):

Date.parse( '9/19/2014 ' + convertTo24Hour(time) );

Now we can use this in array.sort compare function. We just compare two numbers, 1411129800000 ? 1411132800000, decide which one is bigger and sort array.

function compare(a,b) {

  var atime = Date.parse('9/19/2014 ' + convertTo24Hour(a.time));
  var btime = Date.parse('9/19/2014 ' + convertTo24Hour(b.time));

  if (atime < btime) {
     return -1;
  }

  if (atime > btime) {
    return 1;
  }

  return 0;
}

What we got after all:

  1. Use array.sort compare function to sort elements
  2. Convert time to number so we can correctly compare them
  3. To do so, convert 12h time format to 24 and use Date.parse

Here is jsfiddle to play with - http://jsfiddle.net/rqgmkdbs/

Community
  • 1
  • 1
2

Try this compare function according to the same time input as your example. It compares on the Floating notation of you time value.

<script>
    var objs = [
        {id:"540-events",local_id:540,title:"Mas Flow",fc_start_time:"12:30 pm"},
        {id:"540-events",local_id:540,title:"Mas Flow",fc_start_time:"10:30 pm"},
        {id:"540-events",local_id:540,title:"Mas Flow",fc_start_time:"12:30 pm"},
        {id:"540-events",local_id:540,title:"Mas Flow",fc_start_time:"14:30 pm"},
        {id:"540-events",local_id:540,title:"Mas Flow",fc_start_time:"09:30 pm"}
    ]       
    function compare(a,b) {
        var time1 = parseFloat(a.fc_start_time.replace(':','.').replace(/[^\d.-]/g, ''));
        var time2 = parseFloat(b.fc_start_time.replace(':','.').replace(/[^\d.-]/g, ''));
        if(a.fc_start_time.match(/.*pm/)) time1 += 12; if(b.fc_start_time.match(/.*pm/)) time2 += 12;
        if (time1 < time2) return -1;
        if (time1 > time2) return 1;
        return 0;
    }   
    objs.sort(compare);
    console.log(objs);      
</script>
saRca
  • 142
  • 1
  • 10
daan.desmedt
  • 3,752
  • 1
  • 19
  • 33
  • Thank you very much,this work very well. Just one thing, what about if the array have an object with fc_start_time:"09:30 am" ? – saRca Sep 19 '14 at 13:50
  • 1
    You can add these checks: if(a.fc_start_time.match(/.*pm/)) time1 += 12; if(b.fc_start_time.match(/.*pm/)) time2 += 12; just before the returns. – daan.desmedt Sep 19 '14 at 13:56
1
var input = [{hour:1, minutes:10},{hour:4, minutes: 1}, ...];
input.sort(function (a, b)
{
    // compare hours first
    if (a.hour < b.hour) return -1;
    if (a.hour > b.hour) return 1;

    // else a.hour === b.hour, so compare minutes to break the tie
    if (a.minute < b.minute) return -1;
    if (a.minute > b.minute) return 1;

    // couldn't break the tie
    return 0;
});
Ferrakkem Bhuiyan
  • 2,741
  • 2
  • 22
  • 38
0

Try this. You have to consider am and pm in your time.

<!doctype html>
</html>
    <head>
        <meta charset="utf-8">      
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        <script type="text/javascript">
            $(document).ready(function() {
                // The data
                var data = [
                   { id:"540-events", local_id:540, title:"Mas Flow", fc_start_time:"12:30 pm"}, 
                   { id:"531-events", local_id:531, title:"Slowly", fc_start_time:"04:30 pm"}, 
                   { id:"545-events", local_id:545, title:"Mas Flow 2", fc_start_time:"03:30 am"}
                ]
                // Sort values
                data.sort(function(a,b){
                    var aValue = new Number(a.fc_start_time.replace(/\d*/g,""));
                    var bValue = new Number(b.fc_start_time.replace(/\d*/g,""));
                    if( aTime.match(/.*pm/) ){
                        aValue + 12;
                    }
                    return aValue - bValue;    
                });
                // Show values
                for( var i = 0; i < data.length; i++){
                    $("ul").append("<li>"+data[i].fc_start_time+"</li>");
                }
        });
        </script>
    </head>
    <body>
        <ul>        
        </ul>
    </body>
</html>
drkunibar
  • 1,327
  • 1
  • 7
  • 7