its_me
its_me

Reputation: 11338

How to use Moment.js?

I'm unable to follow the Moment.js documentation, and need some help with setting it up. I've referenced the moment.min.js file properly on my webpage like so:

<script src="/js/moment.min.js"></script>

Coming to the HTML part of my webpage, I have two different datetime's on the same page:

Published Date

<time class="pubdate" datetime="2012-06-09T12:32:10-04:00" pubdate>
    June 09, 2012
</time>

Last Modified Date

<time class="updated" itemprop="dateModified" datetime="2012-06-09T12:32:10-04:00">
    June 9, 2012 ~ 12:32
</time>

Important! The relative date parsing shouldn't go beyond "yesterday". As for everything beyond, the <time> tags should display the exact datetime's they would without the JavaScript -- i.e. Moment.js shouldn't touch or parse dates that are past "yesterday".

Now, to make the library do its job as aforementioned, I need to call a function after the library reference. So, the question is, what should the function be? (Using jQuery is fine, as I already reference the library on my webpage.)

Upvotes: 24

Views: 112838

Answers (4)

Scott Davey
Scott Davey

Reputation: 907

Extending @its_me's implementation above, here's a version that

  • updates all elements with a given class
  • keeps them updated every minute (so '1 minute ago' becomes '2 minutes ago')
  • switches to a different format when +-1 day from now (e.g. Last Tuesday at 11:45 PM)

Here's a JSFiddle for you to play with.

Your HTML:

<time class="cw-relative-date" datetime="2014-06-09T12:32:10-00:00"></time>

The JS to include:

(function () {

// Define a function that updates all relative dates defined by <time class='cw-relative-date'>
var updateAllRelativeDates = function() {
        $('time').each(function (i, e) {
            if ($(e).attr("class") == 'cw-relative-date') {

                // Initialise momentjs
                var now = moment();
                moment.lang('en', {
                    calendar : {
                        lastDay : '[Yesterday at] LT',
                        sameDay : '[Today at] LT',
                        nextDay : '[Tomorrow at] LT',
                        lastWeek : '[Last] dddd [at] LT',
                        nextWeek : 'dddd [at] LT',
                        sameElse : 'D MMM YYYY [at] LT'
                    }
                });

                // Grab the datetime for the element and compare to now                    
                var time = moment($(e).attr('datetime'));
                var diff = now.diff(time, 'days');

                // If less than one day ago/away use relative, else use calendar display
                if (diff <= 1 && diff >= -1) {
                    $(e).html('<span>' + time.from(now) + '</span>');
                } else {
                    $(e).html('<span>' + time.calendar() + '</span>');
                }
            }
        });
    };

// Update all dates initially
updateAllRelativeDates();

// Register the timer to call it again every minute
setInterval(updateAllRelativeDates, 60000);

})();

Upvotes: 1

kodkod
kodkod

Reputation: 1576

You can also use the moment().calendar() function, which will format for you dates close to today (up to a week from today):

$('time').each(function(i, e) {
  var time = moment($(e).attr('datetime'));

  $(e).html('<span>' + time.calendar() + '</span>');
});​

You can customize the format strings with this code:

moment.calendar = {
  lastDay : '[Yesterday at] LT',
  sameDay : '[Today at] LT',
  nextDay : '[Tomorrow at] LT',
  lastWeek : '[last] dddd [at] LT',
  nextWeek : 'dddd [at] LT',
  sameElse : 'L'
};

If you are not interested in formatting dates prior to yesterday, just change the formats of lastWeek and nextWeek to full date-time format (e.g. 'L').


UPDATE 2013-09-06 Apparently it has a new syntax that also enables you to localize it:

moment.lang('en', {
  calendar: {
    lastDay : '[Yesterday at] LT',
    sameDay : '[Today at] LT',
    nextDay : '[Tomorrow at] LT',
    lastWeek : '[last] dddd [at] LT',
    nextWeek : 'dddd [at] LT',
    sameElse : 'L'
  }
});

Upvotes: 5

its_me
its_me

Reputation: 11338

Thanks to @JohannesKlauß for the code. This is basically how I executed his answer and how I am referencing the code on my website.

<script src="/js/moment.min.js"></script>
<script src="/js/moment.executor.js"></script>

Where, moment.min.js is the Moment.js library, and moment.executor.js has this code (courtesy of Johannes):

jQuery(document).ready(function($){

    var now = moment();

    $('time').each(function(i, e) {
        var time = moment($(e).attr('datetime'));

        if(now.diff(time, 'days') <= 1) {
            $(e).html('<span>' + time.from(now) + '</span>');
        }
    });

});

PS: You can actually edit moment.min.js and add the aforementioned code right in it, at the end. This way, you will be saving one additional HTTP request. :P

Upvotes: 2

Johannes Klau&#223;
Johannes Klau&#223;

Reputation: 11020

Please specify your question. I'm assuming you want a relative date parsing and the maximum should be "yesterday".

I never used moment.js but as far as the docs say, it's pretty simple.

Use var now = moment(); as your current date. Then parse every time-Tag in your DOM with var time = moment($(e).attr('datetime'));

To check the difference use the diff() method:

if(now.diff(time, 'days') <= 1) {
    // getting the relative output
}

Use var ago = now.from(time) to get the relative output and replace the time in your DOM with your ago variable.

Update based on comment:

Okay, well untested, but that's the basic idea:

Updated the code.

var now = moment();

$('time').each(function(i, e) {
    var time = moment($(e).attr('datetime'));

    if(now.diff(time, 'days') <= 1) {
        $(e).html('<span>' + time.from(now) + '</span>');
    }
});

Upvotes: 24

Related Questions