149 lines
3.5 KiB
JavaScript
149 lines
3.5 KiB
JavaScript
|
// ### filter.js >>
|
||
|
|
||
|
angular
|
||
|
.module('angular-duration-format.filter', [ ])
|
||
|
.filter('duration', function() {
|
||
|
var DURATION_FORMATS_SPLIT = /((?:[^ydhms']+)|(?:'(?:[^']|'')*')|(?:y+|d+|h+|m+|s+))(.*)/;
|
||
|
var DURATION_FORMATS = {
|
||
|
y: { // years
|
||
|
// "longer" years are not supported
|
||
|
value: 365 * 24 * 60 * 60 * 1000,
|
||
|
},
|
||
|
yy: {
|
||
|
value: 'y',
|
||
|
pad: 2,
|
||
|
},
|
||
|
d: { // days
|
||
|
value: 24 * 60 * 60 * 1000,
|
||
|
},
|
||
|
dd: {
|
||
|
value: 'd',
|
||
|
pad: 2,
|
||
|
},
|
||
|
h: { // hours
|
||
|
value: 60 * 60 * 1000,
|
||
|
},
|
||
|
hh: { // padded hours
|
||
|
value: 'h',
|
||
|
pad: 2,
|
||
|
},
|
||
|
m: { // minutes
|
||
|
value: 60 * 1000,
|
||
|
},
|
||
|
mm: { // padded minutes
|
||
|
value: 'm',
|
||
|
pad: 2,
|
||
|
},
|
||
|
s: { // seconds
|
||
|
value: 1000,
|
||
|
},
|
||
|
ss: { // padded seconds
|
||
|
value: 's',
|
||
|
pad: 2,
|
||
|
},
|
||
|
sss: { // milliseconds
|
||
|
value: 1,
|
||
|
},
|
||
|
ssss: { // padded milliseconds
|
||
|
value: 'sss',
|
||
|
pad: 4,
|
||
|
},
|
||
|
};
|
||
|
|
||
|
function _parseFormat(string) {
|
||
|
// @inspiration AngularJS date filter
|
||
|
var parts = [];
|
||
|
var format = string ? string.toString() : '';
|
||
|
|
||
|
while (format) {
|
||
|
var match = DURATION_FORMATS_SPLIT.exec(format);
|
||
|
|
||
|
if (match) {
|
||
|
parts = parts.concat(match.slice(1));
|
||
|
|
||
|
format = parts.pop();
|
||
|
} else {
|
||
|
parts.push(format);
|
||
|
|
||
|
format = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return parts;
|
||
|
}
|
||
|
|
||
|
function _formatDuration(timestamp, format) {
|
||
|
var text = '';
|
||
|
var values = { };
|
||
|
|
||
|
format.filter(function(format) { // filter only value parts of format
|
||
|
return DURATION_FORMATS.hasOwnProperty(format);
|
||
|
}).map(function(format) { // get formats with values only
|
||
|
var config = DURATION_FORMATS[format];
|
||
|
|
||
|
if (config.hasOwnProperty('pad')) {
|
||
|
return config.value;
|
||
|
} else {
|
||
|
return format;
|
||
|
}
|
||
|
}).filter(function(format, index, arr) { // remove duplicates
|
||
|
return (arr.indexOf(format) === index);
|
||
|
}).map(function(format) { // get format configurations with values
|
||
|
return angular.extend({
|
||
|
name: format,
|
||
|
}, DURATION_FORMATS[format]);
|
||
|
}).sort(function(a, b) { // sort formats descending by value
|
||
|
return b.value - a.value;
|
||
|
}).forEach(function(format) { // create values for format parts
|
||
|
var value = values[format.name] = Math.floor(timestamp / format.value);
|
||
|
|
||
|
timestamp = timestamp - (value * format.value);
|
||
|
});
|
||
|
|
||
|
format.forEach(function(part) {
|
||
|
var format = DURATION_FORMATS[part];
|
||
|
|
||
|
if (format) {
|
||
|
var value = values[format.value];
|
||
|
|
||
|
text += (format.hasOwnProperty('pad') ? _padNumber(value, Math.max(format.pad, value.toString().length)) : values[part]);
|
||
|
} else {
|
||
|
text += part.replace(/(^'|'$)/g, '').replace(/''/g, '\'');
|
||
|
}
|
||
|
});
|
||
|
|
||
|
return text;
|
||
|
}
|
||
|
|
||
|
function _padNumber(number, len) {
|
||
|
return ((new Array(len + 1)).join('0') + number).slice(-len);
|
||
|
}
|
||
|
|
||
|
return function(value, format) {
|
||
|
var parsedValue = parseFloat(value, 10);
|
||
|
var parsedFormat = _parseFormat(format);
|
||
|
|
||
|
if (isNaN(parsedValue) || (parsedFormat.length === 0)) {
|
||
|
return value;
|
||
|
} else {
|
||
|
return _formatDuration(parsedValue, parsedFormat);
|
||
|
}
|
||
|
};
|
||
|
});
|
||
|
|
||
|
|
||
|
// ### << filter.js
|
||
|
|
||
|
|
||
|
|
||
|
// ### main.js >>
|
||
|
|
||
|
angular
|
||
|
.module('angular-duration-format', [
|
||
|
'angular-duration-format.filter',
|
||
|
]);
|
||
|
|
||
|
|
||
|
// ### << main.js
|
||
|
|