HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Determining how long ago a page was last edited

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
lastdetermininglongpagehowwaseditedago

Problem

I'm making a function that takes the date a page was last edited, accessed through MediaWiki's API, compares it to the current date, and returns how long ago the page was edited, e.g. 1 year/2 days/etc.

It's essentially a massive if/else statement, and I was wondering if there was a better way to implement it.

```
var timestamp,
utcArr,
today,
utcArr = [],
timestamp2,
timestamp3,
timestamp4,
i,
mwArr = [],
lastEdited;

today = new Date();
utcArr.push(today.getUTCFullYear());
utcArr.push(today.getUTCMonth() + 1); // returns value 0-11
utcArr.push(today.getUTCDate());
utcArr.push(today.getUTCHours());
utcArr.push(today.getUTCMinutes());

/**
* Time function
* For formatting the returned value for timestamp
* example timestamp var: '2013-04-27T14:29:53Z'
*/
function time() {
timestamp2 = timestamp.replace(/(\:|T|Z)/g, '-'); // use g to replace every occurrence, not just one
timestamp3 = timestamp2.split('-');
timestamp4 = timestamp3.filter(function (e) { // remove what's left from Z
return e;
});
for (i = 0; i < timestamp4.length; i++) {
mwArr.push(parseFloat(timestamp4[i]));
}

/**
* Compares dates in array and produces the difference between them
* @todo Find a better way to do this
*/
if ((utcArr[0] - mwArr[0]) === 0) { // years
if ((utcArr[1] - mwArr[1]) === 0) { // months
if ((utcArr[2] - mwArr[2]) === 0) { // days
if ((utcArr[3] - mwArr[3]) === 0 { // hours
if ((utcArr[4] - mwArr[4]) === 0) { // minutes
lastEdited = '1 minute';
} else {
lastEdited = utcArr[4] - mwArr[4] + ' minutes';
}

Solution

I looked at the source code of moment.js for inspiration:

http://momentjs.com/

And I'm trying to be as declarative as possible, using data to define the time-units I want to use:

unitMillisecondFactors = {
    'Millisecond': 1000,
    'Second': 60,
    'Minute': 60,
    'Hour': 24,
    'Day': 356,
    'Year': 10,
    'Decade': 1
};


The Javascript Date object can compute the difference between two timestamps in milliseconds. Looking at such a difference the algorithm goes like this: we currently have units Milliseconds. The factor for getting from milliseconds to seconds is 1000. is the number we'er looking at smaller then that factor?
Then we're done, we return a result by rounding down and appending the unit.
If we're not done, then we devide the number by the factor and try with the next unit.

function compute_time(timestamp) {
    var n = new Date() - new Date(timestamp);
    for (var unit in unitMillisecondFactors) {
        var factor = unitMillisecondFactors[unit];
        if (n < factor) {
            n = Math.floor(n);
            if (n == 1) {
                return s + "more than " + n + " " + unit + " ago\n";
            } 
            else {
                return s + "more than " + n + " " + unit + "s ago\n";
            }
        }
        n = n / factor;
    }
}


That's it. See http://jsfiddle.net/bjelline/S23V2/ for a working example with some extra output to see the steps of computation.

Code Snippets

unitMillisecondFactors = {
    'Millisecond': 1000,
    'Second': 60,
    'Minute': 60,
    'Hour': 24,
    'Day': 356,
    'Year': 10,
    'Decade': 1
};
function compute_time(timestamp) {
    var n = new Date() - new Date(timestamp);
    for (var unit in unitMillisecondFactors) {
        var factor = unitMillisecondFactors[unit];
        if (n < factor) {
            n = Math.floor(n);
            if (n == 1) {
                return s + "more than " + n + " " + unit + " ago\n";
            } 
            else {
                return s + "more than " + n + " " + unit + "s ago\n";
            }
        }
        n = n / factor;
    }
}

Context

StackExchange Code Review Q#25807, answer score: 3

Revisions (0)

No revisions yet.