Merge branch 'dev-1.1'

This commit is contained in:
Michael Barrett 2014-07-18 21:31:12 +01:00
commit 0ff75942b9
14 changed files with 325 additions and 115 deletions

9
.editorconfig Normal file
View File

@ -0,0 +1,9 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

2
.gitignore vendored
View File

@ -1 +1 @@
test node_modules

2
.jshintrc Normal file
View File

@ -0,0 +1,2 @@
{
}

View File

@ -1 +1,5 @@
test test
.editorconfig
.jshintrc
Gruntfile.js
.DS_Store

7
.travis.yml Normal file
View File

@ -0,0 +1,7 @@
language: node_js
node_js:
- "0.10"
- "0.11"
before_script:
- npm install -g grunt-cli
script: grunt test

17
CHANGELOG.md Normal file
View File

@ -0,0 +1,17 @@
#Changelog
##1.1.0
- Added MIT license
- Added Changelog
- Added Grunt config
- Added editorconfig
- Added Tests
- Fixed JSHint errors
- Formatted code as per editorconfig
- Fixed bug with conversion from year(s) to another unit
- Make sure `Error` (type) is thrown when invalid unit is encountered
- Added minified distributable version
- Updated package.json
- Added bower config
- Added travis config

43
Gruntfile.js Normal file
View File

@ -0,0 +1,43 @@
module.exports = function(grunt) {
// measure the time each task takes
require('time-grunt')(grunt);
// autoload Grunt tasks
require('load-grunt-tasks')(grunt);
// main project config
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
dist: {
files: {
'dist/<%= pkg.name %>.min.js': '<%= pkg.name %>.js'
}
}
},
jshint: {
options: {
jshintrc: true
},
files: [
'Gruntfile.js',
'<%= pkg.name %>.js',
'test/**/*.js'
]
},
mochaTest: {
test: {
options: {
reporter: 'spec'
},
src: ['test/**/*.js']
}
}
});
// user defined tasks
grunt.registerTask('test', ['mochaTest']);
grunt.registerTask('lint', ['jshint']);
grunt.registerTask('build', ['uglify']);
grunt.registerTask('default', ['jshint', 'mochaTest', 'uglify']);
};

19
LICENSE Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) Michael David Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,5 +1,9 @@
#Timestring #Timestring
[![Build Status](https://travis-ci.org/mike182uk/timestring.svg?branch=master)](https://travis-ci.org/mike182uk/timestring)
[![NPM](https://nodei.co/npm/timestring.png?downloads=true&stars=true)](https://nodei.co/npm/timestring/)
Attempts to parse a human readable time string into a time based value. Attempts to parse a human readable time string into a time based value.
##Overview ##Overview
@ -158,14 +162,21 @@ console.log(daysThisWeek); // will log 5
###Browser ###Browser
All you need to do to get timestring working in the browser is download / clone this repo and make sure you include the `timestring.js` script on your page: All you need to do to get timestring working in the browser is download / clone this repo and make sure you include the `dist/timestring.min.js` script on your page:
```html ```html
<script src="<path-to-src>/timestring.js"></script> <script src="<path-to-src>/timestring.min.js"></script>
``` ```
### Node
To install for a node project, navigate to the projects root folder and in your terminal type the following: Alternatively you can you use bower to manage this dependency for you:
```
bower install timestring --save
```
###Node
To install for a node application, navigate to the projects root folder and in your terminal type the following:
``` ```
npm install timestring npm install timestring

16
bower.json Normal file
View File

@ -0,0 +1,16 @@
{
"name": "timestring",
"main": "timestring.js",
"version": "1.1.0",
"description": "Parse a human readable time string into a time based value",
"homepage": "https://github.com/mike182uk/timestring",
"authors": [
"Michael David Barrett <mike182uk@gmail.com>"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"test"
]
}

1
dist/timestring.min.js vendored Normal file
View File

@ -0,0 +1 @@
(function(){"use strict";var a=function(a){var b={hoursPerDay:24,daysPerWeek:7,weeksPerMonth:4,monthsPerYear:12};a=a||{},this.settings=b;for(var c in a)this.settings[c]=a[c];this.units={s:["s","sec","secs","second","seconds"],m:["m","min","mins","minute","minutes"],h:["h","hr","hrs","hour","hours"],d:["d","day","days"],w:["w","week","weeks"],mth:["mth","mths","month","months"],y:["y","yr","yrs","year","years"]},this.unitValues={s:1,m:60,h:3600},this.unitValues.d=this.settings.hoursPerDay*this.unitValues.h,this.unitValues.w=this.settings.daysPerWeek*this.unitValues.d,this.unitValues.mth=this.settings.weeksPerMonth*this.unitValues.w,this.unitValues.y=this.settings.monthsPerYear*this.unitValues.mth};a.prototype.parse=function(a,b){function c(a){for(var b in f.units)for(var c in f.units[b])if(a===f.units[b][c])return b;throw new Error("The unit ["+a+"] is not supported by timestring")}function d(a,b){var d=f.unitValues[c(b)];return a/d}function e(a,b){var d=f.unitValues[c(b)];return a*d}var f=this,g=0,h=a.toLowerCase().replace(/[^\.\w+-]+/g,"").match(/[-+]?[0-9]+[a-z]+/g);if(null!==h)for(var i=0;i<h.length;i++){var j=h[i],k=j.match(/[0-9]+/g)[0],l=j.match(/[a-z]+/g)[0];g+=e(k,l)}return b?d(g,b):g},String.prototype.parseTime=function(b,c){return new a(c).parse(this,b)},"undefined"!=typeof module&&module.exports?module.exports=a:this.Timestring=a}).call(this);

View File

@ -1,17 +1,22 @@
{ {
"name" : "timestring", "name": "timestring",
"description" : "Parse a human readable time string into a time based value", "description": "Parse a human readable time string into a time based value",
"homepage" : "https://github.com/mike182uk/timestring", "homepage": "https://github.com/mike182uk/timestring",
"keywords" : [ "author": "Michael David Barrett <mike182uk@gmail.com>",
"util", "repository": {
"functional", "type": "git",
"time" "url": "git://github.com/mike182uk/timestring.git"
], },
"author" : "Michael David Barrett <mike182uk@gmail.com>", "main": "timestring.js",
"repository" : { "version": "1.1.0",
"type": "git", "devDependencies": {
"url": "git://github.com/mike182uk/timestring.git" "chai": "^1.9.1",
}, "grunt": "^0.4.5",
"main" : "timestring.js", "grunt-contrib-jshint": "^0.10.0",
"version" : "1.0.2" "grunt-contrib-uglify": "^0.5.0",
"grunt-mocha-test": "^0.11.0",
"load-grunt-tasks": "^0.6.0",
"mocha": "^1.20.1",
"time-grunt": "^0.4.0"
}
} }

75
test/timestring.js Normal file
View File

@ -0,0 +1,75 @@
var chai = require('chai');
var expect = chai.expect;
var timestring = require('../timestring');
describe('timestring', function() {
it('can parse a timestring', function(done) {
var ts = new timestring();
expect(ts.parse('1s')).to.equal(1);
expect(ts.parse('1m')).to.equal(60);
expect(ts.parse('1h')).to.equal(3600);
expect(ts.parse('1d')).to.equal(86400);
expect(ts.parse('1w')).to.equal(604800);
expect(ts.parse('1mth')).to.equal(2419200);
expect(ts.parse('1y')).to.equal(29030400);
done();
});
it('can return a value in a specified unit', function(done) {
expect((new timestring()).parse('5m', 's')).to.equal(300);
expect((new timestring()).parse('5m', 'm')).to.equal(5);
done();
});
it('uses the passed settings instead of the defaults', function(done) {
var settings = {
hoursPerDay: 1,
daysPerWeek: 2,
weeksPerMonth: 3,
monthsPerYear: 4
};
var ts = new timestring(settings);
expect(ts.parse('1d', 'h')).to.equal(1);
expect(ts.parse('1w', 'd')).to.equal(2);
expect(ts.parse('1mth', 'w')).to.equal(3);
expect(ts.parse('1y', 'mth')).to.equal(4);
done();
});
it('throws an error when an invalid unit is used in the timestring', function(done) {
var ts = new timestring();
expect(ts.parse.bind(ts, '1g')).to.throw(Error);
done();
});
it('can parse a messy time string', function(done) {
expect((new timestring()).parse('5 D a YS 4 h 2 0 mI nS')).to.equal(447600);
done();
});
it('should expose a method on String.prototype that will parse the string as a timestring', function(done){
var str = '1min';
// no arguments passed
expect(str.parseTime()).to.equal(60);
// units argument passed
expect(str.parseTime('m')).to.equal(1);
// units + settings argument passed
str = '5h';
expect(str.parseTime('d', { hoursPerDay: 5 })).to.equal(1);
done();
});
});

View File

@ -1,111 +1,112 @@
(function(){ (function(){
"use strict"; "use strict";
var Timestring = function(settings) { var Timestring = function(settings) {
// default settings // default settings
var defaults = { var defaults = {
hoursPerDay: 24, hoursPerDay: 24,
daysPerWeek: 7, daysPerWeek: 7,
weeksPerMonth: 4, weeksPerMonth: 4,
monthsPerYear: 12 monthsPerYear: 12
};
// merge default settings with user settings
var settings = settings || {};
this.settings = {};
for (var property in defaults) { this.settings[property] = defaults[property]; }
for (var property in settings) { this.settings[property] = settings[property]; }
// time units
this.units = {
s: ['s', 'sec', 'secs', 'second', 'seconds'],
m: ['m', 'min', 'mins', 'minute', 'minutes'],
h: ['h', 'hr', 'hrs', 'hour', 'hours'],
d: ['d', 'day', 'days'],
w: ['w', 'week', 'weeks'],
mth: ['mth', 'mths','month', 'months'],
y: ['y', 'yr', 'yrs', 'year', 'years']
};
// time unit seconds mappings
this.unitValues = {
s: 1,
m: 60,
h: 3600
};
// dynamic time unit seconds mappings
// these are dynamic based on the settings
this.unitValues.d = this.settings.hoursPerDay * this.unitValues.h;
this.unitValues.w = this.settings.daysPerWeek * this.unitValues.d;
this.unitValues.mth = this.settings.weeksPerMonth * this.unitValues.w;
this.unitValues.y = this.settings.monthsPerYear * this.unitValues.w;
}; };
Timestring.prototype.parse = function(string, returnUnit) { // merge default settings with user settings
// reference to this settings = settings || {};
var self = this; this.settings = defaults;
for (var s in settings) { this.settings[s] = settings[s]; }
// get unit key helper // time units
function getUnitKey(unit) { this.units = {
for (var key in self.units) { s: ['s', 'sec', 'secs', 'second', 'seconds'],
for (var u in self.units[key]) { m: ['m', 'min', 'mins', 'minute', 'minutes'],
if (unit === self.units[key][u]) { h: ['h', 'hr', 'hrs', 'hour', 'hours'],
return key; d: ['d', 'day', 'days'],
} w: ['w', 'week', 'weeks'],
} mth: ['mth', 'mths','month', 'months'],
} y: ['y', 'yr', 'yrs', 'year', 'years']
};
// throw exception if invalid unit is passed // time unit seconds mappings
throw 'The unit [' + unit + '] is not supported by timestring'; this.unitValues = {
s: 1,
m: 60,
h: 3600
};
// dynamic time unit seconds mappings
// these are dynamic based on the settings
this.unitValues.d = this.settings.hoursPerDay * this.unitValues.h;
this.unitValues.w = this.settings.daysPerWeek * this.unitValues.d;
this.unitValues.mth = this.settings.weeksPerMonth * this.unitValues.w;
this.unitValues.y = this.settings.monthsPerYear * this.unitValues.mth;
};
Timestring.prototype.parse = function(string, returnUnit) {
// reference to this
var that = this;
// get unit key helper
function getUnitKey(unit) {
for (var k in that.units) {
for (var u in that.units[k]) {
if (unit === that.units[k][u]) {
return k;
}
} }
}
// convert a value to a specific unit // throw error if invalid unit was passed
function convert(value, unit) { throw new Error('The unit [' + unit + '] is not supported by timestring');
var baseValue = self.unitValues[getUnitKey(unit)];
return value / baseValue;
}
// get a value in seconds based on a specific unit
function getSeconds(value, unit) {
var baseValue = self.unitValues[getUnitKey(unit)];
return value * baseValue;
}
// seconds counter
var totalSeconds = 0;
// split string into groups and get total seconds for each group
var groups = string
.toLowerCase() // convert words to lower case
.replace(/[^\.\w+-]+/g, '') // remove white space
.match(/[-+]?[0-9]+[a-z]+/g); // match time groups (digit followed by time unit - i.e 5d 15m = 2 time groups)
if (groups !== null) {
for(var i = 0; i < groups.length; i++) {
var g = groups[i];
var value = g.match(/[0-9]+/g)[0];
var unit = g.match(/[a-z]+/g)[0];
totalSeconds += getSeconds(value, unit);
}
}
// return total, convert if needed
return (returnUnit) ? convert(totalSeconds, returnUnit) : totalSeconds;
} }
// add convenience method to string prototype // convert a value to a specific unit
String.prototype.parseTime = function (unit, settings) { function convert(value, unit) {
return (new Timestring(settings)).parse(this, unit); var baseValue = that.unitValues[getUnitKey(unit)];
return value / baseValue;
} }
// export Timestring object for either the browser or node // get a value in seconds based on a specific unit
if (typeof module !== 'undefined' && module.exports) { function getSeconds(value, unit) {
module.exports = Timestring; var baseValue = that.unitValues[getUnitKey(unit)];
return value * baseValue;
} }
else {
this.Timestring = Timestring; // seconds counter
var totalSeconds = 0;
// split string into groups and get total seconds for each group
var groups = string
.toLowerCase() // convert words to lower case
.replace(/[^\.\w+-]+/g, '') // remove white space
.match(/[-+]?[0-9]+[a-z]+/g); // match time groups (digit followed by time unit - i.e 5d 15m = 2 time groups)
if (groups !== null) {
for(var i = 0; i < groups.length; i++) {
var g = groups[i];
var value = g.match(/[0-9]+/g)[0];
var unit = g.match(/[a-z]+/g)[0];
totalSeconds += getSeconds(value, unit);
}
} }
// return total, convert if needed
return (returnUnit) ? convert(totalSeconds, returnUnit) : totalSeconds;
};
// add convenience method to string prototype
String.prototype.parseTime = function (unit, settings) {
return (new Timestring(settings)).parse(this, unit);
};
// export Timestring object
if (typeof module !== 'undefined' && module.exports) {
module.exports = Timestring;
}
else {
this.Timestring = Timestring;
}
}).call(this); }).call(this);