Skip to content

Instantly share code, notes, and snippets.

@fiznool
Created February 5, 2015 10:27

Revisions

  1. fiznool created this gist Feb 5, 2015.
    47 changes: 47 additions & 0 deletions date-duration.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    Date.prototype.duration = function(granularity) {
    if(!granularity) {
    granularity = 's';
    }

    var units = [{
    enabled: /^[wdhms]$/.test(granularity),
    singular: 'week',
    plural: 'weeks',
    inMillis: 7 * 24 * 60 * 60 * 1000
    }, {
    enabled: /^[dhms]$/.test(granularity),
    singular: 'day',
    plural: 'days',
    inMillis: 24 * 60 * 60 * 1000
    }, {
    enabled: /^[hms]$/.test(granularity),
    singular: 'hour',
    plural: 'hours',
    inMillis: 60 * 60 * 1000
    }, {
    enabled: /^[ms]$/.test(granularity),
    singular: 'minute',
    plural: 'minutes',
    inMillis: 60 * 1000
    }, {
    enabled: /^[s]$/.test(granularity),
    singular: 'second',
    plural: 'seconds',
    inMillis: 1000
    }];

    var duration = [];
    var millis = this.getTime() - Date.now();

    units.forEach(function(unit) {
    if(unit.enabled) {
    var val = Math.floor(millis / unit.inMillis);
    if(val > 0) {
    duration.push(val + ' ' + (val > 1 ? unit.plural : unit.singular));
    millis = millis - (val * unit.inMillis);
    }
    }
    });

    return duration.join(', ');
    };
    80 changes: 80 additions & 0 deletions date-duration.spec.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,80 @@
    describe('Date duration', function() {
    beforeEach(function() {
    // Ensure date under test equals the relative date
    spyOn(Date, 'now').and.returnValue(0);
    });

    it('should return a duration', function() {
    var oneSecond = new Date(1000);
    expect(oneSecond.duration()).toBe('1 second');

    var oneMinute = new Date(60 * 1000);
    expect(oneMinute.duration()).toBe('1 minute');

    var oneHour = new Date(60* 60 * 1000);
    expect(oneHour.duration()).toBe('1 hour');

    var oneDay = new Date(24 * 60 * 60 * 1000);
    expect(oneDay.duration()).toBe('1 day');

    var oneWeek = new Date(7 * 24 * 60 * 60 * 1000);
    expect(oneWeek.duration()).toBe('1 week');
    });

    it('should pluralise correctly', function() {
    var twoSecond = new Date(2 * 1000);
    expect(twoSecond.duration()).toBe('2 seconds');

    var twoMinute = new Date(2 * 60 * 1000);
    expect(twoMinute.duration()).toBe('2 minutes');

    var twoHour = new Date(2 * 60* 60 * 1000);
    expect(twoHour.duration()).toBe('2 hours');

    var twoDay = new Date(2 * 24 * 60 * 60 * 1000);
    expect(twoDay.duration()).toBe('2 days');

    var twoWeek = new Date(2 * 7 * 24 * 60 * 60 * 1000);
    expect(twoWeek.duration()).toBe('2 weeks');
    });

    it('should combine duration units', function() {
    var fiveMinutesThirtySeconds = new Date(
    (5 * 60 * 1000) + (30 * 1000));
    expect(fiveMinutesThirtySeconds.duration())
    .toBe('5 minutes, 30 seconds');

    var oneDayFourHoursFifteenMinutes = new Date(
    (24 * 60 * 60 * 1000) +
    (4 * 60 * 60 * 1000) +
    (15 * 60 * 1000));
    expect(oneDayFourHoursFifteenMinutes.duration())
    .toBe('1 day, 4 hours, 15 minutes');

    var threeWeeksFourDays = new Date(
    (3 * 7 * 24 * 60 * 60 * 1000) +
    (4 * 24 * 60 * 60 * 1000));
    expect(threeWeeksFourDays.duration())
    .toBe('3 weeks, 4 days');
    });

    it('should allow granularity to be specified', function() {
    var fiveMinutesThirtySeconds = new Date(
    (5 * 60 * 1000) + (30 * 1000));
    expect(fiveMinutesThirtySeconds.duration('m'))
    .toBe('5 minutes');

    var oneDayFourHoursFifteenMinutes = new Date(
    (24 * 60 * 60 * 1000) +
    (4 * 60 * 60 * 1000) +
    (15 * 60 * 1000));
    expect(oneDayFourHoursFifteenMinutes.duration('h'))
    .toBe('1 day, 4 hours');

    var threeWeeksFourDays = new Date(
    (3 * 7 * 24 * 60 * 60 * 1000) +
    (4 * 24 * 60 * 60 * 1000));
    expect(threeWeeksFourDays.duration('w'))
    .toBe('3 weeks');
    });
    });