jeffusu
jeffusu

Reputation: 135

Parse Custom Date and Sort

I'm new to javascript/jQuery and am attempting something ambitious for my skill level. I found some snippets that have helped but am stuck.

I have a bunch of dates in the format like this: dd-month-yyyy (10-Oct-2013). As far as I understand this is somewhat of an unconventional format for a date. So what I'm trying to do is parse the date into a normal format, and then arrange the parent divs using the jQuery tinysort plugin (which I don't think I am using correctly).

I made a jsfiddle here: http://jsfiddle.net/8BYDZ/

Or here is my code:

<div id="date-sort">
  <div class="date-content"> 
    <p>Some Content</p>
    <p class="date-sort">10-Oct-2013</p>
    <hr />
  </div>
  <div class="date-content"> 
    <p>Some Content</p>
    <p class="date-sort">12-Oct-2013</p>
    <hr />
  </div>
  <div class="date-content"> 
    <p>Some Content</p>
    <p class="date-sort">2-Sep-2013</p>
    <hr />
  </div>
  <div class="date-content"> 
    <p>Some Content</p>
    <p class="date-sort">22-Jun-2013</p>
    <hr />
  </div>
  <div class="date-content"> 
    <p>Some Content</p>
    <p class="date-sort">1-May-2013</p>
    <hr />
  </div>
</div>
$(document).ready(function(){
    function customParse(str) {
      var months = ['Jan','Feb','Mar','Apr','May','Jun',
                    'Jul','Aug','Sep','Oct','Nov','Dec'],
          n = months.length, re = /(\d{2})-([a-z]{3})-(\d{4})/i, matches;

      while(n--) { months[months[n]]=n; } // map month names to their index :)

      matches = str.match(re); // extract date parts from string

      return new Date(matches[3], months[matches[2]], matches[1]);
    }

    var array = [];

    var elements = $('.date-sort');

    for(var i = 0; i < elements.length; i++) {
       var current = elements[i];
        if(current.children.length === 0 && current.textContent.replace(/ |\n/g,'') !== '') {
           // Check the element has no children && that it is not empty
           customParse(current.textContent);
           array.push(current.textContent);
        }
    } 

    $('div#date-sort>.date-content>.date-sort').tsort();

});

Thanks for any help, insight, or input.

Upvotes: 0

Views: 639

Answers (3)

StackSlave
StackSlave

Reputation: 10617

You simply need to eliminate the - marks with .replace(), then by using new Date().getTime() you assign the number of milliseconds between midnight of January 1, 1970 and your Dates to an Array that will .sort() just how you need it to.

$(document).ready(function(){
  var ds = $('.date-sort'), dt = [];
  ds.each(function(i){
    dt[i] = new Date($(this).html().replace(/-/g, ' ')).getTime();
  });
  dt.sort();
  ds.each(function(i){
    $(this).html(new Date(dt[i])/*add . whatever here*/);
  });    
});

I updated your JSFiddle.

Upvotes: 1

Ethan Brown
Ethan Brown

Reputation: 27292

In JavaScript, objects are generally considered the best way to create associative maps (as the commentors pointed out below, it's perfectly valid to set a property on an array).

I would use an object as your map between month names and numbers. Also, I would use lowercase names, so I could pay the cost of lowercasing once, and use that value in my mapping.

So I would replace the definition of your months array with an object initializer:

var months = { 'jan': 1, 'feb': 2, 'mar': 3, /*...*/ };

In that way, you don't need the loop.

Now you just need to call .toLowercase() on your input, and the month names will map correctly.

Upvotes: 0

kavun
kavun

Reputation: 3381

You need to give tinysort a sortable date.

new Date(matches[3], months[matches[2]], matches[1]).toJSON();

// ...

current.setAttribute('data-date', customParse(current.textContent));

// ...

$('div#date-sort>.date-content').tsort('.date-sort', {attr: 'data-date' });

Your regular expression was too restrictive as days are not always two numbers.

re = /(\d{1,2})-([a-z]{3})-(\d{4})/i

Here is a working jsiddle

Upvotes: 1

Related Questions