Skip to content

Commit

Permalink
v1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Kevin Stumpf committed Oct 16, 2015
1 parent 593d6a0 commit a88d633
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 2 deletions.
63 changes: 61 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,61 @@
# frequency-formatter
Formats time interval to human readable string
# Moment Duration Format Frequency

**Format plugin for the Moment Duration object.**

This is a plugin to the Moment.js JavaScript date library to add frequency formatting to Moment Durations.


---

## Installation

**Node.js**

`npm install moment-duration-format-frequency`


## Usage

### Module

To use this plugin as a module, use the `require` function:
```
require("moment-duration-format-frequency");
```

The plugin does not export anything, so there is no need to assign the require output to a variable.

The plugin depends on moment.js.


### Basics

The duration format method can format moment durations as human readable frequencies:

```
moment.duration(1.5, 'weeks').formatAsFrequency('weeks');
// "every 1-2 weeks"
moment.duration(0.23, 'weeks').formatAsFrequency('weeks');
// "4-5 times per week"
moment.duration(3, 'weeks').formatAsFrequency('weeks');
// "every 3 weeks"
moment.duration(0.25, 'weeks').formatAsFrequency('weeks');
// "4 times per week"
moment.duration(3, 'years').formatAsFrequency('years');
// "every 3 years"
```

### Customization

Individual strings can be customized:

```
moment.duration.fn.formatAsFrequency.defaults.everyString = 'alle';
moment.duration(3, 'years').formatAsFrequency('years');
// "alle 3 years"
```
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./lib/frequencyFormatter');
63 changes: 63 additions & 0 deletions lib/momentDurationFormatFrequency.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* jshint node: true */

'use strict';

var moment = require('moment');
var util = require('util');
var _ = require('lodash');
var isNaturalNumber = require('is-natural-number');

(function(moment) {
var roundNumber = function(number) {
return parseFloat(number.toFixed(2));
};

var isApproximatelyNaturalNumber = function(number) {
return isNaturalNumber(roundNumber(number));
};

moment.duration.fn.formatAsFrequency = function(unit, options) {
options = options || {};
_.defaults(options, this.formatAsFrequency.defaults);

var unitDuration = moment.duration(1, unit);
var isValidUnit = unitDuration.asMilliseconds() > 0;
if (!isValidUnit) {
throw new Error(util.format('%s is not a valid moment unit', unit));
}

var intervalInMs = this.asMilliseconds();
var unitDurationInMs = unitDuration.asMilliseconds();

var unitSingular = moment.normalizeUnits(unit);
var unitPlural = unitSingular + 's';

if (intervalInMs === unitDurationInMs) {
return util.format('%s %s', options.everyString, unitSingular);
}

if (intervalInMs < unitDurationInMs) {
var numberOfIntervalsPerUnit = unitDurationInMs / intervalInMs;
if (isApproximatelyNaturalNumber(numberOfIntervalsPerUnit)) {
return util.format('%d %s %s %s', roundNumber(numberOfIntervalsPerUnit), options.timesString, options.perString, unitSingular);
}

return util.format('%d%s%d %s %s %s', Math.floor(numberOfIntervalsPerUnit), options.separatorString, Math.ceil(numberOfIntervalsPerUnit), options.timesString, options.perString, unitSingular);
}

var numberOfUnitsPerInterval = intervalInMs / unitDuration;
if (isApproximatelyNaturalNumber(numberOfUnitsPerInterval)) {
return util.format('%s %d %s', options.everyString, roundNumber(numberOfUnitsPerInterval), unitPlural);
}

return util.format('%s %d%s%d %s', options.everyString, Math.floor(numberOfUnitsPerInterval), options.separatorString, Math.ceil(numberOfUnitsPerInterval), unitPlural);

};

moment.duration.fn.formatAsFrequency.defaults = {
everyString: 'every',
perString: 'per',
timesString: 'times',
separatorString: '-'
};
})(moment);
33 changes: 33 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "moment-duration-format-frequency",
"version": "1.0.0",
"description": "Formats time interval to human readable string",
"main": "index.js",
"scripts": {
"test": "mocha test"
},
"repository": {
"type": "git",
"url": "git+https://github.com/DispatcherInc/moment-duration-format-frequency.git"
},
"keywords": [
"frequency",
"format",
"interval",
"string"
],
"author": "Kevin Stumpf",
"license": "ISC",
"bugs": {
"url": "https://github.com/DispatcherInc/moment-duration-format-frequency/issues"
},
"homepage": "https://github.com/DispatcherInc/moment-duration-format-frequency#readme",
"devDependencies": {
"chai": "^3.3.0"
},
"dependencies": {
"is-natural-number": "^2.0.0",
"lodash": "^3.10.1",
"moment": ">=1.4.0"
}
}
50 changes: 50 additions & 0 deletions test/momentDurationFormatFrequencySpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* jshint node: true */

'use strict';

var chai = require('chai');
var expect = chai.expect;
var moment = require('moment');

require('./../lib/momentDurationFormatFrequency');

describe('moment-duration-format-frequency', function() {
it('should work with frequencies greater than 1 per unit', function() {
var everyOneAndAHalfWeeks = moment.duration(1.5, 'weeks');

expect(everyOneAndAHalfWeeks.formatAsFrequency('weeks')).to.eql('every 1-2 weeks');
});

it('should work with frequencies less than 1 per unit', function() {
var fourToFiveTimesPerWeek = moment.duration(0.23, 'weeks');

expect(fourToFiveTimesPerWeek.formatAsFrequency('weeks')).to.eql('4-5 times per week');
});

it('should work with frequencies of 1 per unit', function() {
var everyThreeWeeks = moment.duration(3, 'weeks');

expect(everyThreeWeeks.formatAsFrequency('weeks')).to.eql('every 3 weeks');
});

it('should work with frequencies whose inverse is a natural number', function() {
var fourTimesPerWeek = moment.duration(0.25, 'weeks');

expect(fourTimesPerWeek.formatAsFrequency('weeks')).to.eql('4 times per week');
});

it('should work with years unit as well', function() {
var everyThreeYears = moment.duration(3, 'years');

expect(everyThreeYears.formatAsFrequency('years')).to.eql('every 3 years');
});

describe('defaults', function() {
it('everyString should be overwritable', function() {
moment.duration.fn.formatAsFrequency.defaults.everyString = 'alle';

var everyThreeYears = moment.duration(3, 'years');
expect(everyThreeYears.formatAsFrequency('years')).to.eql('alle 3 years');
});
});
});

0 comments on commit a88d633

Please sign in to comment.