I am trying to get the total seconds from 2 timestamps. I am currently getting the total days, hours and minutes, but I am trying to get all the way to the second. I am unable to find the formula...
Can someone point me in the right direction of getting the seconds too, along with the days, hours and minutes that I have already accomplished.
Here is my code thus far:
//gets timestamps
var clockedIn = "2017-03-02 09:45:25";
var clockedOut = "2017-03-04 09:49:06";
//sets timestamps to vars
var now = clockedIn;
var then = clockedOut;
var diff = moment.duration(moment(then).diff(moment(now)));
//parses out times
var days = parseInt(diff.asDays());
var hours = parseInt(diff.asHours());
hours = (hours - days * 24);
var minutes = parseInt(diff.asMinutes());
minutes = minutes - (days * 24 * 60 + hours * 60);
//I am looking to get seconds here...
Any help would be appreciated, even if it is just a link.
Thanks
One simple solution is to create two Date objects and get the difference between them.
var clockedIn = new Date("2017-03-02 09:45:25");
var clockedOut = new Date("2017-03-04 09:49:06");
var seconds = (clockedOut-clockedIn)/1000
// divide by 1000 because the difference we get will be in milliseconds.
Do you mean this function? seconds()
There's a nice plugin for momentjs available on github that makes this kind of formating very nice, as you can simply specify a format for your duration. https://github.com/jsmreese/moment-duration-format
var clockedIn = "2017-03-02 09:45:25";
var clockedOut = "2017-03-04 09:49:06";
//sets timestamps to vars
var now = clockedIn;
var then = clockedOut;
var diff = moment.duration(moment(then).diff(moment(now)));
console.log(diff.format("d [days], H [hours], m [minutes] [and] s [seconds] "));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js"></script>
<script>
/*! Moment Duration Format v1.3.0
* https://github.com/jsmreese/moment-duration-format
* Date: 2014-07-15
*
* Duration format plugin function for the Moment.js library
* http://momentjs.com/
*
* Copyright 2014 John Madhavan-Reese
* Released under the MIT license
*/
(function (root, undefined) {
// repeatZero(qty)
// returns "0" repeated qty times
function repeatZero(qty) {
var result = "";
// exit early
// if qty is 0 or a negative number
// or doesn't coerce to an integer
qty = parseInt(qty, 10);
if (!qty || qty < 1) { return result; }
while (qty) {
result += "0";
qty -= 1;
}
return result;
}
// padZero(str, len [, isRight])
// pads a string with zeros up to a specified length
// will not pad a string if its length is aready
// greater than or equal to the specified length
// default output pads with zeros on the left
// set isRight to `true` to pad with zeros on the right
function padZero(str, len, isRight) {
if (str == null) { str = ""; }
str = "" + str;
return (isRight ? str : "") + repeatZero(len - str.length) + (isRight ? "" : str);
}
// isArray
function isArray(array) {
return Object.prototype.toString.call(array) === "[object Array]";
}
// isObject
function isObject(obj) {
return Object.prototype.toString.call(obj) === "[object Object]";
}
// findLast
function findLast(array, callback) {
var index = array.length;
while (index -= 1) {
if (callback(array[index])) { return array[index]; }
}
}
// find
function find(array, callback) {
var index = 0,
max = array.length,
match;
if (typeof callback !== "function") {
match = callback;
callback = function (item) {
return item === match;
};
}
while (index < max) {
if (callback(array[index])) { return array[index]; }
index += 1;
}
}
// each
function each(array, callback) {
var index = 0,
max = array.length;
if (!array || !max) { return; }
while (index < max) {
if (callback(array[index], index) === false) { return; }
index += 1;
}
}
// map
function map(array, callback) {
var index = 0,
max = array.length,
ret = [];
if (!array || !max) { return ret; }
while (index < max) {
ret[index] = callback(array[index], index);
index += 1;
}
return ret;
}
// pluck
function pluck(array, prop) {
return map(array, function (item) {
return item[prop];
});
}
// compact
function compact(array) {
var ret = [];
each(array, function (item) {
if (item) { ret.push(item); }
});
return ret;
}
// unique
function unique(array) {
var ret = [];
each(array, function (_a) {
if (!find(ret, _a)) { ret.push(_a); }
});
return ret;
}
// intersection
function intersection(a, b) {
var ret = [];
each(a, function (_a) {
each(b, function (_b) {
if (_a === _b) { ret.push(_a); }
});
});
return unique(ret);
}
// rest
function rest(array, callback) {
var ret = [];
each(array, function (item, index) {
if (!callback(item)) {
ret = array.slice(index);
return false;
}
});
return ret;
}
// initial
function initial(array, callback) {
var reversed = array.slice().reverse();
return rest(reversed, callback).reverse();
}
// extend
function extend(a, b) {
for (var key in b) {
if (b.hasOwnProperty(key)) { a[key] = b[key]; }
}
return a;
}
// define internal moment reference
var moment;
if (typeof require === "function") {
try { moment = require('moment'); }
catch (e) {}
}
if (!moment && root.moment) {
moment = root.moment;
}
if (!moment) {
throw "Moment Duration Format cannot find Moment.js";
}
// moment.duration.format([template] [, precision] [, settings])
moment.duration.fn.format = function () {
var tokenizer, tokens, types, typeMap, momentTypes, foundFirst, trimIndex,
args = [].slice.call(arguments),
settings = extend({}, this.format.defaults),
// keep a shadow copy of this moment for calculating remainders
remainder = moment.duration(this);
// add a reference to this duration object to the settings for use
// in a template function
settings.duration = this;
// parse arguments
each(args, function (arg) {
if (typeof arg === "string" || typeof arg === "function") {
settings.template = arg;
return;
}
if (typeof arg === "number") {
settings.precision = arg;
return;
}
if (isObject(arg)) {
extend(settings, arg);
}
});
// types
types = settings.types = (isArray(settings.types) ? settings.types : settings.types.split(" "));
// template
if (typeof settings.template === "function") {
settings.template = settings.template.apply(settings);
}
// tokenizer regexp
tokenizer = new RegExp(map(types, function (type) {
return settings[type].source;
}).join("|"), "g");
// token type map function
typeMap = function (token) {
return find(types, function (type) {
return settings[type].test(token);
});
};
// tokens array
tokens = map(settings.template.match(tokenizer), function (token, index) {
var type = typeMap(token),
length = token.length;
return {
index: index,
length: length,
// replace escaped tokens with the non-escaped token text
token: (type === "escape" ? token.replace(settings.escape, "$1") : token),
// ignore type on non-moment tokens
type: ((type === "escape" || type === "general") ? null : type)
// calculate base value for all moment tokens
//baseValue: ((type === "escape" || type === "general") ? null : this.as(type))
};
}, this);
// unique moment token types in the template (in order of descending magnitude)
momentTypes = intersection(types, unique(compact(pluck(tokens, "type"))));
// exit early if there are no momentTypes
if (!momentTypes.length) {
return pluck(tokens, "token").join("");
}
// calculate values for each token type in the template
each(momentTypes, function (momentType, index) {
var value, wholeValue, decimalValue, isLeast, isMost;
// calculate integer and decimal value portions
value = remainder.as(momentType);
wholeValue = (value > 0 ? Math.floor(value) : Math.ceil(value));
decimalValue = value - wholeValue;
// is this the least-significant moment token found?
isLeast = ((index + 1) === momentTypes.length);
// is this the most-significant moment token found?
isMost = (!index);
// update tokens array
// using this algorithm to not assume anything about
// the order or frequency of any tokens
each(tokens, function (token) {
if (token.type === momentType) {
extend(token, {
value: value,
wholeValue: wholeValue,
decimalValue: decimalValue,
isLeast: isLeast,
isMost: isMost
});
if (isMost) {
// note the length of the most-significant moment token:
// if it is greater than one and forceLength is not set, default forceLength to `true`
if (settings.forceLength == null && token.length > 1) {
settings.forceLength = true;
}
// rationale is this:
// if the template is "h:mm:ss" and the moment value is 5 minutes, the user-friendly output is "5:00", not "05:00"
// shouldn't pad the `minutes` token even though it has length of two
// if the template is "hh:mm:ss", the user clearly wanted everything padded so we should output "05:00"
// if the user wanted the full padded output, they can set `{ trim: false }` to get "00:05:00"
}
}
});
// update remainder
remainder.subtract(wholeValue, momentType);
});
// trim tokens array
if (settings.trim) {
tokens = (settings.trim === "left" ? rest : initial)(tokens, function (token) {
// return `true` if:
// the token is not the least moment token (don't trim the least moment token)
// the token is a moment token that does not have a value (don't trim moment tokens that have a whole value)
return !(token.isLeast || (token.type != null && token.wholeValue));
});
}
// build output
// the first moment token can have special handling
foundFirst = false;
// run the map in reverse order if trimming from the right
if (settings.trim === "right") {
tokens.reverse();
}
tokens = map(tokens, function (token) {
var val,
decVal;
if (!token.type) {
// if it is not a moment token, use the token as its own value
return token.token;
}
// apply negative precision formatting to the least-significant moment token
if (token.isLeast && (settings.precision < 0)) {
val = (Math.floor(token.wholeValue * Math.pow(10, settings.precision)) * Math.pow(10, -settings.precision)).toString();
} else {
val = token.wholeValue.toString();
}
// remove negative sign from the beginning
val = val.replace(/^\-/, "");
// apply token length formatting
// special handling for the first moment token that is not the most significant in a trimmed template
if (token.length > 1 && (foundFirst || token.isMost || settings.forceLength)) {
val = padZero(val, token.length);
}
// add decimal value if precision > 0
if (token.isLeast && (settings.precision > 0)) {
decVal = token.decimalValue.toString().replace(/^\-/, "").split(/\.|e\-/);
switch (decVal.length) {
case 1:
val += "." + padZero(decVal[0], settings.precision, true).slice(0, settings.precision);
break;
case 2:
val += "." + padZero(decVal[1], settings.precision, true).slice(0, settings.precision);
break;
case 3:
val += "." + padZero(repeatZero((+decVal[2]) - 1) + (decVal[0] || "0") + decVal[1], settings.precision, true).slice(0, settings.precision);
break;
default:
throw "Moment Duration Format: unable to parse token decimal value.";
}
}
// add a negative sign if the value is negative and token is most significant
if (token.isMost && token.value < 0) {
val = "-" + val;
}
foundFirst = true;
return val;
});
// undo the reverse if trimming from the right
if (settings.trim === "right") {
tokens.reverse();
}
return tokens.join("");
};
moment.duration.fn.format.defaults = {
// token definitions
escape: /\[(.+?)\]/,
years: /[Yy]+/,
months: /M+/,
weeks: /[Ww]+/,
days: /[Dd]+/,
hours: /[Hh]+/,
minutes: /m+/,
seconds: /s+/,
milliseconds: /S+/,
general: /.+?/,
// token type names
// in order of descending magnitude
// can be a space-separated token name list or an array of token names
types: "escape years months weeks days hours minutes seconds milliseconds general",
// format options
// trim
// "left" - template tokens are trimmed from the left until the first moment token that has a value >= 1
// "right" - template tokens are trimmed from the right until the first moment token that has a value >= 1
// (the final moment token is not trimmed, regardless of value)
// `false` - template tokens are not trimmed
trim: "left",
// precision
// number of decimal digits to include after (to the right of) the decimal point (positive integer)
// or the number of digits to truncate to 0 before (to the left of) the decimal point (negative integer)
precision: 0,
// force first moment token with a value to render at full length even when template is trimmed and first moment token has length of 1
forceLength: null,
// template used to format duration
// may be a function or a string
// template functions are executed with the `this` binding of the settings object
// so that template strings may be dynamically generated based on the duration object
// (accessible via `this.duration`)
// or any of the other settings
template: function () {
var types = this.types,
dur = this.duration,
lastType = findLast(types, function (type) {
return dur._data[type];
});
// default template strings for each duration dimension type
switch (lastType) {
case "seconds":
return "h:mm:ss";
case "minutes":
return "d[d] h:mm";
case "hours":
return "d[d] h[h]";
case "days":
return "M[m] d[d]";
case "weeks":
return "y[y] w[w]";
case "months":
return "y[y] M[m]";
case "years":
return "y[y]";
default:
return "y[y] M[m] d[d] h:mm:ss";
}
}
};
})(this);
</script>
You don't have to use any complex method to calculate the difference of the two moment (or Date) objects. Simply calculating the difference gives you the total difference between the two dates in milliseconds.
var now = moment();
var then = moment().add(1231, 'second'); // just to have an example different date
var milliseconds = +then - +now;
var seconds = milliseconds / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
If you would like to get the difference formatted like HH:mm:ss, just convert the diff milliseconds back to moment object and use .format():
var now = moment();
var then = moment().add(1231, 'second'); // just to have an example different date
var diff_m = moment(+then - +now);
console.log(diff_m.format('HH:mm:ss'));
Related
I'm trying to write a script to output JSON according to these constraints.
So far I think my logic is correct.
Any help is appreciated.
CURRENT ISSUES:
[working now]I can't figure out why duration continues to return 0
[working now]how to tackle setting the max/min
tackling how to handle when two excursions of different types occur back to back (“hot” ⇒ “cold” or “cold” ⇒ “hot”)
This is how each new object should appear
let current_excursion = {
'device_sensor' : '',
'start_at' : [],
'stop_at' : 0,
'duration' : 0,
'type': '',
'max/min':0
}
device_sensor
The sId this excursion was detected on.
start_at
The date and time the temperature first is out of range in ISO_8601 format.
stop_at
The date and time the temperature is back in range in ISO_8601 format.
duration
The total time in seconds the temperature was out of range.
type
Either the string “hot” or “cold” depending on the type of excursion.
max/min
The temperature extreme for the excursion. For a “hot” excursion this will be the max and for a “cold” excursion the min.
A temperature excursion event starts
when the temperature goes out of range and ends when the temperature returns
to the range.
For a “hot” excursion this is when the temperature is greater than 8 °C,
and for a “cold” excursion this is when the temperature is less than 2 °C.
If two excursions of different types occur back to back
(“hot” ⇒ “cold” or “cold” ⇒ “hot”) please take the midpoint of the two
timestamps as the end of the first excursion and the start of the second.
If an excursion is occurring at the end of the temperature readings
please end the excursion at the last reading (duration = 0)
Here is the link to the test data
Test Case Data
Here is what I've written so far:
const tempTypeTernary = (num) =>{
if(num < 2){
return 'cold'
} else if(num > 8){
return 'hot'
}
}
const excursion_duration = (x,y) =>{
let start = new Date(x) / 1000
let end = new Date(y) / 1000
return end - start
}
const reset_excursion = (obj) => {
Object.keys(obj).map(key => {
if (obj[key] instanceof Array) obj[key] = []
else obj[key] = ''
})
}
const list_excursion = (array) =>{
let result = [];
let max_min_excursion = 0;
let current_excursion = {
'device_sensor' : '',
'start_at' : [],
'stop_at' : 0,
'duration' : 0,
'type': '',
'max/min':0
}
for(let k = 0; k < array.length;k++){
if( array[k]['tmp'] < 2 || array[k]['tmp'] > 8){
current_excursion['device_sensor'] = array[k]['sId'];
current_excursion['start_at'] = [new Date(array[k]['time']).toISOString(),array[k]['time']];
current_excursion['type'] = tempTypeTernary(array[k]['tmp']);
if( array[k]['tmp'] > 2 || array[k]['tmp'] < 8){
current_excursion['stop_at'] = new Date(array[k]['time']).toISOString();
current_excursion['duration'] = excursion_duration(current_excursion['start_at'][1],array[k]['time'])
}
result.push(current_excursion)
reset_excursion(current_excursion)
}
}
return result
}
list_excursion(json)
Let me be bold and try to answer on just eyeballing the code; please tryout this:
const tempTypeTernary = (num) =>{
if(num < 2){
return 'cold'
} else if(num > 8){
return 'hot'
}
}
const excursion_duration = (x,y) =>{
let start = new Date(x) / 1000
let end = new Date(y) / 1000
return end - start
}
const reset_excursion = (obj) => {
Object.keys(obj).map(key => {
if (obj[key] instanceof Array) obj[key] = []
else obj[key] = ''
})
}
const list_excursion = (array) =>{
let result = [];
let max_min_excursion = 0;
let current_excursion = {
'device_sensor' : '',
'start_at' : [],
'stop_at' : 0,
'duration' : 0,
'type': '',
'max/min':0
}
for(let k = 0; k < array.length;k++){
if( array[k]['tmp'] < 2 || array[k]['tmp'] > 8)
{
if (current_excursion['type']==null)
{
current_excursion['device_sensor'] = array[k]['sId'];
current_excursion['start_at'] = [new Date(array[k]['time']).toISOString(),array[k]['time']];
current_excursion['type'] = tempTypeTernary(array[k]['tmp'])
}
}
else // this is where the second 'if' was
{
if (current_excursion['type']!=null)
{
current_excursion['stop_at'] = new Date(array[k]['time']).toISOString();
current_excursion['duration'] = excursion_duration(current_excursion['start_at'][1],array[k]['time'])
result.push(current_excursion)
reset_excursion(current_excursion)
}
}
}
I have a problem where javascript enters the if statement when the condition should evaluate false. I have the javascript linked to a HTML. The HTML uses form as its input for each variable, when nothing is entered into any of the form input type, the javascript outputs "0".
When 5 is entered into initialVelocity, and 45 is entered into finalVelocity the output is 50.
Feel free to make fun of my coding style, all answers are appreciated!
function physicsFunction() {
var initialVelocity = document.getElementById('formInitialV').elements['initialVName'].value;
var finalVelocity = document.getElementById('formFinalV').elements['finalVName'].value;
var time = document.getElementById('formTime').elements['timeName'].value;
var acceleration = document.getElementById('formAcceleration').elements['accelerationName'].value;
var averageAcceleration = document.getElementById('formAvgAcceleration').elements['avgAccelerationName'].value;
var displacement = document.getElementById('formDisplacement').elements['displacementName'].value;
var averageVelocity = document.getElementById('formAvgVelocity').elements['avgVelocityName'].value;
if (initialVelocity !== undefined && acceleration !== undefined && time !== undefined) {
var finalVelocity = (initialVelocity + acceleration * time);
document.getElementById('paragraphOne').innerHTML = 'The final Velocity is about equal to: ' + finalVelocity +' m/s';
}}
To obtain a real undefined value, you could use a function like:
function UndefinedIfEmpty(value)
{
if(value.trim() == "")
{
return undefined;
}
else
{
return value;
}
}
// Use it:
// var initialVelocity = UndefinedIfEmpty(document.getElementById('formInitialV').elements['initialVName'].value);
// and so on
console.log("`` is ", UndefinedIfEmpty(""));
console.log("` ` is ", UndefinedIfEmpty(" "));
console.log("`12` is ", UndefinedIfEmpty("12"));
You should even convert into number, to avoid: initialVelocity + acceleration * time => "12" + "4" * 13 => "12" + 52 => "1252" (string concatenation).
function NumberOrUndefined(value)
{
value = value.trim();
if ( value == "" )
{
return undefined;
}
else
{
return parseInt(value, 10);
}
}
// 10 in parseInt to avoid octal convertion
console.log("` ` is", NumberOrUndefined(" "));
console.log("12 is a ", typeof NumberOrUndefined("12"));
I'm using Angular "currency" filter to show price in a shopping cart. The prices are fetched from a back end server. So sometimes the price may not be available to show to the user. In that case I just want to show the user that the price is not available in the same field as of currency field. I can not show plain text in a currency filter. The only solution I found is to keep another text field to show/hide when a price is not available.But this is some what unnecessary I think. Is there any way to extend or override the built in "currency" filter of Angular js ?. Kindly appreciate some help.
<div class="large-12 medium-12 small-12 columns pad-none nzs-pro-list-item-price">
{{item.ItmPrice|currency}}
</div>
Create your custom filter which will internally use currency when value is present, otherwise it will return text which you want to show instead.
Markup
{{amount | customFormat:"USD$": "N/A"}}
Filter
.filter('customFormat', function($filter) {
return function(value, format, text) {
if (angular.isDefined(value) && value != null)
return $filter('currency')(value, format);
else
return text;
}
});
Working Plunkr
I feel the best way is to rewrite currency filter, so that you have fill control over Pattern, Grouping Separator, Decimal Separator & symbol position
<span>
{{26666662.5226 | fmtCurrency :"##.###,###" : "." : "," : "$" : "first"}}
</span>
Resluts in: $26.666.662,523
Filter:
app.filter("fmtCurrency", ['CurrencyService', function sasCurrency(CurrencyService) {
return function (amount, pattern, groupingSeparator, decimalSeparator, currencySymbol, symbolPosition) {
var patternInfo = CurrencyService.parsePattern(pattern, groupingSeparator, decimalSeparator);
var formattedCurrency = CurrencyService.formatCurrency(amount, patternInfo, groupingSeparator, decimalSeparator);
if (symbolPosition === 'last')
return formattedCurrency + currencySymbol;
else
return currencySymbol + formattedCurrency;
};
}])
Service: formatNumber which is the same function used in angular currency filter is being used here inside service
app.service("CurrencyService", function () {
var PATTERN_SEP = ';',
DECIMAL_SEP = '.',
GROUP_SEP = ',',
ZERO = '0',
DIGIT = "#";
var MAX_DIGITS = 22;
var ZERO_CHAR = '0';
return {
parsePattern: function (pattern, groupingSeparator, decimalSeparator) {
return parsePattern(pattern, groupingSeparator, decimalSeparator);
},
formatCurrency: function (amount, patternInfo, groupingSeparator, decimalSeparator) {
return formatNumber(amount, patternInfo, groupingSeparator, decimalSeparator);
}
}
/*
* Currency formatter utility
*/
function isUndefined(value) { return typeof value === 'undefined'; }
/**
* main function for parser
* #param str {string} pattern to be parsed (e.g. #,##0.###).
*/
function parsePattern(pattern, groupSep, decimalSep) {
DECIMAL_SEP = decimalSep;
GROUP_SEP = groupSep;
var p = {
minInt: 1,
minFrac: 0,
maxFrac: 0,
posPre: '',
posSuf: '',
negPre: '',
negSuf: '',
gSize: 0,
lgSize: 0
};
var ZERO = '0',
DIGIT = "#";
var parts = pattern.split(PATTERN_SEP),
positive = parts[0],
negative = parts[1];
var parts = positive.split(DECIMAL_SEP),
integer = parts[0],
fraction = parts[1];
console.log(parts);
p.posPre = integer.substr(0, integer.indexOf(DIGIT));
if (fraction) {
for (var i = 0; i < fraction.length; i++) {
var ch = fraction.charAt(i);
console.log(ch, ZERO, DIGIT);
if (ch == ZERO)
p.minFrac = p.maxFrac = i + 1;
else if (ch == DIGIT)
p.maxFrac = i + 1;
else
p.posSuf += ch;
}
}
var groups = integer.split(GROUP_SEP);
p.gSize = groups[1] ? groups[1].length : 0;
p.lgSize = (groups[2] || groups[1]) ? (groups[2] || groups[1]).length : 0;
if (negative) {
var trunkLen = positive.length - p.posPre.length - p.posSuf.length,
pos = negative.indexOf(DIGIT);
p.negPre = negative.substr(0, pos).replace(/\'/g, '');
p.negSuf = negative.substr(pos + trunkLen).replace(/\'/g, '');
} else {
// hardcoded '-' sign is fine as all locale use '-' as MINUS_SIGN. (\u2212 is the same as '-')
p.negPre = '-' + p.posPre;
p.negSuf = p.posSuf;
}
return p;
}
function isString(value) { return typeof value === 'string'; }
function isNumber(value) { return typeof value === 'number'; }
/**
* Format a number into a string
* #param {number} number The number to format
* #param {{
* minFrac, // the minimum number of digits required in the fraction part of the number
* maxFrac, // the maximum number of digits required in the fraction part of the number
* gSize, // number of digits in each group of separated digits
* lgSize, // number of digits in the last group of digits before the decimal separator
* negPre, // the string to go in front of a negative number (e.g. `-` or `(`))
* posPre, // the string to go in front of a positive number
* negSuf, // the string to go after a negative number (e.g. `)`)
* posSuf // the string to go after a positive number
* }} pattern
* #param {string} groupSep The string to separate groups of number (e.g. `,`)
* #param {string} decimalSep The string to act as the decimal separator (e.g. `.`)
* #param {[type]} fractionSize The size of the fractional part of the number
* #return {string} The number formatted as a string
*/
function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
if (!(isString(number) || isNumber(number)) || isNaN(number)) return '';
var isInfinity = !isFinite(number);
var isZero = false;
var numStr = Math.abs(number) + '',
formattedText = '',
parsedNumber;
if (isInfinity) {
formattedText = '\u221e';
} else {
parsedNumber = parse(numStr, '.');
roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac);
var digits = parsedNumber.d;
var integerLen = parsedNumber.i;
var exponent = parsedNumber.e;
var decimals = [];
isZero = digits.reduce(function (isZero, d) { return isZero && !d; }, true);
// pad zeros for small numbers
while (integerLen < 0) {
digits.unshift(0);
integerLen++;
}
// extract decimals digits
if (integerLen > 0) {
decimals = digits.splice(integerLen, digits.length);
} else {
decimals = digits;
digits = [0];
}
// format the integer digits with grouping separators
var groups = [];
if (digits.length >= pattern.lgSize) {
groups.unshift(digits.splice(-pattern.lgSize, digits.length).join(''));
}
while (digits.length > pattern.gSize) {
groups.unshift(digits.splice(-pattern.gSize, digits.length).join(''));
}
if (digits.length) {
groups.unshift(digits.join(''));
}
formattedText = groups.join(groupSep);
// append the decimal digits
if (decimals.length) {
formattedText += decimalSep + decimals.join('');
}
if (exponent) {
formattedText += 'e+' + exponent;
}
}
if (number < 0 && !isZero) {
return pattern.negPre + formattedText + pattern.negSuf;
} else {
return pattern.posPre + formattedText + pattern.posSuf;
}
}
function parse(numStr, decimalSep) {
var exponent = 0, digits, numberOfIntegerDigits;
var i, j, zeros;
DECIMAL_SEP = decimalSep;
// Decimal point?
if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) {
numStr = numStr.replace(DECIMAL_SEP, '');
}
// Exponential form?
if ((i = numStr.search(/e/i)) > 0) {
// Work out the exponent.
if (numberOfIntegerDigits < 0) numberOfIntegerDigits = i;
numberOfIntegerDigits += +numStr.slice(i + 1);
numStr = numStr.substring(0, i);
} else if (numberOfIntegerDigits < 0) {
// There was no decimal point or exponent so it is an integer.
numberOfIntegerDigits = numStr.length;
}
// Count the number of leading zeros.
for (i = 0; numStr.charAt(i) === ZERO_CHAR; i++) {/* jshint noempty: false */ }
if (i === (zeros = numStr.length)) {
// The digits are all zero.
digits = [0];
numberOfIntegerDigits = 1;
} else {
// Count the number of trailing zeros
zeros--;
while (numStr.charAt(zeros) === ZERO_CHAR) zeros--;
// Trailing zeros are insignificant so ignore them
numberOfIntegerDigits -= i;
digits = [];
// Convert string to array of digits without leading/trailing zeros.
for (j = 0; i <= zeros; i++ , j++) {
digits[j] = +numStr.charAt(i);
}
}
// If the number overflows the maximum allowed digits then use an exponent.
if (numberOfIntegerDigits > MAX_DIGITS) {
digits = digits.splice(0, MAX_DIGITS - 1);
exponent = numberOfIntegerDigits - 1;
numberOfIntegerDigits = 1;
}
return { d: digits, e: exponent, i: numberOfIntegerDigits };
}
/**
* Round the parsed number to the specified number of decimal places
* This function changed the parsedNumber in-place
*/
function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) {
var digits = parsedNumber.d;
var fractionLen = digits.length - parsedNumber.i;
// determine fractionSize if it is not specified; `+fractionSize` converts it to a number
fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize;
// The index of the digit to where rounding is to occur
var roundAt = fractionSize + parsedNumber.i;
var digit = digits[roundAt];
if (roundAt > 0) {
// Drop fractional digits beyond `roundAt`
digits.splice(Math.max(parsedNumber.i, roundAt));
// Set non-fractional digits beyond `roundAt` to 0
for (var j = roundAt; j < digits.length; j++) {
digits[j] = 0;
}
} else {
// We rounded to zero so reset the parsedNumber
fractionLen = Math.max(0, fractionLen);
parsedNumber.i = 1;
digits.length = Math.max(1, roundAt = fractionSize + 1);
digits[0] = 0;
for (var i = 1; i < roundAt; i++) digits[i] = 0;
}
if (digit >= 5) {
if (roundAt - 1 < 0) {
for (var k = 0; k > roundAt; k--) {
digits.unshift(0);
parsedNumber.i++;
}
digits.unshift(1);
parsedNumber.i++;
} else {
digits[roundAt - 1]++;
}
}
// Pad out with zeros to get the required fraction length
for (; fractionLen < Math.max(0, fractionSize); fractionLen++) digits.push(0);
// Do any carrying, e.g. a digit was rounded up to 10
var carry = digits.reduceRight(function (carry, d, i, digits) {
d = d + carry;
digits[i] = d % 10;
return Math.floor(d / 10);
}, 0);
if (carry) {
digits.unshift(carry);
parsedNumber.i++;
}
}
})
$provide.decorator('currencyFilter', ['$delegate',
function ($delegate) {
var crncyFilter = $delegate;
var extendsFilter = function () {
var res = crncyFilter.apply(this, arguments);
if (arguments[2]) {
var digi1 = arguments[2] || 2;
return arguments[1] + Number(arguments[0]).toFixed(digi1);
}
else {
if (arguments[1] == "¥") {
return arguments[1] + Number(arguments[0]).toFixed(1);
}
}
};
return extendsFilter;
}]);
This is the way to Override Decimal digit
I'm looking for a way to construct regular expressions to match numeric inputs specified by a given integer range, ie. if I pass in a range of 1,3-4 then a regex would be returned matching just 1, 3 and 4.
I wrote the following method to try and do this:
function generateRegex(values) {
if (values == "*") {
return new RegExp("^[0-9]+$");
} else {
return new RegExp("^[" + values + "]+$");
}
}
I'm having issues however as sometimes I need to match double digits, such as "8-16", and I also need to ensure that if I am passed a single digit value, such as "1", that the generated regex matches only 1, and not say 11.
I really would like this to remain a pretty small snippet of code, but am not sure enough about regexs to know how to do this. Would be massively grateful for any help!
EDIT: I realise I wasn't clear, with my original paragraph, so have edited it. I realise the regex's that I originally generated do not work at all
Regexes don't know anything about numbers, only digits. So [8-16] is invalid because you say match between 8 and 1 (instead of 1 and 8 e.g.) plus the digit 6.
If you want to match numbers, you have to consider them lexically. For example, to match numbers between 1 and 30, you have to write something like (other regexes exist):
/^(30|[1-2]\d|[1-9])$/
I was sure it was 4-8 hours :-) In the end (and in its uselessness) it was a good exercise in composing Regexes. You are free to try it. If we exclude one use of continue and the use of the Array constructor, it's fully jsLint ok.
var BuildRegex = function(matches) {
"use strict";
var splits = matches.split(','),
res = '^(',
i, subSplit, min, max, temp, tempMin;
if (splits.length === 0) {
return new RegExp('^()$');
}
for (i = 0; i < splits.length; i += 1) {
if (splits[i] === '*') {
return new RegExp('^([0-9]+)$');
}
subSplit = splits[i].split('-');
min = BuildRegex.Trim(subSplit[0], '0');
if (min === '') {
return null;
}
if (subSplit.length === 1) {
res += min;
res += '|';
continue;
} else if (subSplit.length > 2) {
return null;
}
max = BuildRegex.Trim(subSplit[1], '0');
if (max === '') {
return null;
}
if (min.length > max.length) {
return null;
}
// For 2-998 we first produce 2-9, then 10-99
temp = BuildRegex.DifferentLength(res, min, max);
tempMin = temp.min;
if (tempMin === null) {
return null;
}
res = temp.res;
// Then here 100-998
res = BuildRegex.SameLength(res, tempMin, max);
}
res = res.substr(0, res.length - 1);
res += ')$';
return new RegExp(res);
};
BuildRegex.Repeat = function(ch, n) {
"use strict";
return new Array(n + 1).join(ch);
};
BuildRegex.Trim = function(str, ch) {
"use strict";
var i = 0;
while (i < str.length && str[i] === ch) {
i += 1;
}
return str.substr(i);
};
BuildRegex.IsOnlyDigit = function(str, start, digit) {
"use strict";
var i;
for (i = start; i < str.length; i += 1) {
if (str[i] !== digit) {
return false;
}
}
return true;
};
BuildRegex.RangeDigit = function(min, max) {
"use strict";
if (min === max) {
return min;
}
return '[' + min + '-' + max + ']';
};
BuildRegex.DifferentLength = function(res, min, max) {
"use strict";
var tempMin = min,
i, tempMax;
for (i = min.length; i < max.length; i += 1) {
tempMax = BuildRegex.Repeat('9', i);
res = BuildRegex.SameLength(res, tempMin, tempMax);
tempMin = '1' + BuildRegex.Repeat('0', i);
}
if (tempMin > tempMax) {
return null;
}
return {
min: tempMin,
res: res
};
};
BuildRegex.SameLength = function(res, min, max) {
"use strict";
var commonPart;
// 100-100
if (min === max) {
res += min;
res += '|';
return res;
}
for (commonPart = 0; commonPart < min.length; commonPart += 1) {
if (min[commonPart] !== max[commonPart]) {
break;
}
}
res = BuildRegex.RecursivelyAddRange(res, min.substr(0, commonPart), min.substr(commonPart), max.substr(commonPart));
return res;
};
BuildRegex.RecursivelyAddRange = function(res, prefix, min, max) {
"use strict";
var only0Min, only9Max, i, middleMin, middleMax;
if (min.length === 1) {
res += prefix;
res += BuildRegex.RangeDigit(min[0], max[0]);
res += '|';
return res;
}
// Check if
only0Min = BuildRegex.IsOnlyDigit(min, 1, '0');
only9Max = BuildRegex.IsOnlyDigit(max, 1, '9');
if (only0Min && only9Max) {
res += prefix;
res += BuildRegex.RangeDigit(min[0], max[0]);
for (i = 1; i < min.length; i += 1) {
res += '[0-9]';
}
res += '|';
return res;
}
middleMin = min;
if (!only0Min) {
res = BuildRegex.RecursivelyAddRange(res, prefix + min[0], min.substr(1), BuildRegex.Repeat('9', min.length - 1));
if (min[0] !== '9') {
middleMin = String.fromCharCode(min.charCodeAt(0) + 1) + BuildRegex.Repeat('0', min.length - 1);
} else {
middleMin = null;
}
}
middleMax = max;
if (!only9Max) {
if (max[0] !== '0') {
middleMax = String.fromCharCode(max.charCodeAt(0) - 1) + BuildRegex.Repeat('9', max.length - 1);
} else {
middleMax = null;
}
}
if (middleMin !== null && middleMax !== null && middleMin[0] <= middleMax[0]) {
res = BuildRegex.RecursivelyAddRange(res, prefix + BuildRegex.RangeDigit(middleMin[0], middleMax[0]), middleMin.substr(1), middleMax.substr(1));
}
if (!only9Max) {
res = BuildRegex.RecursivelyAddRange(res, prefix + max[0], BuildRegex.Repeat('0', max.length - 1), max.substr(1));
}
return res;
};
// ----------------------------------------------------------
var printRegex = function(p) {
"use strict";
document.write(p + ': ' + BuildRegex(p) + '<br>');
};
printRegex('*');
printRegex('1');
printRegex('1,*');
printRegex('1,2,3,4');
printRegex('1,11-88');
printRegex('1,11-88,90-101');
printRegex('1-11111');
printRegex('75-11119');
Test here http://jsfiddle.net/dnqYV/
The C# version is here http://ideone.com/3aEt3E
I'm not sure there is a (sane) way to test integer ranges with RegExp. I believe you're fixated on RegExp, where there are much simpler (more flexible) approaches. Take a look at IntRangeTest().
var range = new IntRangeTest('0,10-20');
console.log(
"0,10-20",
range.test("") == false,
range.test("-5") == false,
range.test("0") == true,
range.test("5") == false,
range.test("11") == true,
range.test("123.23") == false
);
If you feel like it, you can easily add this to Number.prototype. You could also quite easily make this an extension to RegExp, if that's what you're worried about.
Ok so it seems that there are 4 main cases that I need to address:
Single digits, ie 1, would simply generate the regex /^1$/
Multiple digits, ie 12, would require the regex /^12&/
Single digit ranges, ie 3-6, would generate the regex /^[3-6]$/
And finally, multiple digit ranges work in a similar method to multiple digits but with a range, ie 11-14 would become /^1[1-4]$/. These would need to be split into multiple regexes if they span over multiple start digits, Ie 23-31 would become /^2[3-9]|3[0-1]$/
Therefore, all I need to do is identify each of these cases and create a compound regex using | like xanatos suggested. Ie, to match all of the above criteria would generate a regex like:
/^( 1 | 12 | [3-6] | 1[1-4] | 2[3-9]|3[0-1] )$/
Do other agree this seems like a decent way to progress?
I have an array as
arr = [1,2,3,4,6,7,8,9]
Now I want to check if the values in the array are consecutive.
Being more specific, I want this
First Check gives first and second element are consecutive and the next element is not consecutive then the algo must return the first element from where the consecutive number started
Like
First Check will give 1
Second Check will give 6
and so on...
Please help
Thanks in advance
/**
* Given an array of number, group algebraic sequences with d=1
* [1,2,5,4,8,11,14,13,12] => [[1,2],[4,5],[8],[11,12,13,14]]
*/
import {reduce, last} from 'lodash/fp';
export const groupSequences = (array) => (
reduce((result, value, index, collection) => {
if (value - collection[index - 1] === 1) {
const group = last(result);
group.push(value);
} else {
result.push([value]);
}
return result;
}, [])(array)
);
/**
* Given an array of number, group algebraic sequences with d=1
* [1,2,3,4,5,6] => true
* [1,2,4,5,6] => false
*/
const differenceAry = arr.slice(1).map(function(n, i) { return n - arr[i]; })
const isDifference= differenceAry.every(value => value == 1)
console.log(isDifference);
One sidenote is that you want to call it multiple times, so each call should know which array it's working on and what the previous offset in that array was. One thing you can do is to extend the native Array object. [Demo]
Array.prototype.nextCons = (function () {
var offset = 0; // remember the last offset
return function () {
var start = offset, len = this.length;
for (var i = start + 1; i < len; i++) {
if (this[i] !== this[i-1] + 1) {
break;
}
}
offset = i;
return this[start];
};
})();
Usage
var arr = [1,2,3,4,6,8,9];
arr.nextCons(); // 1
arr.nextCons(); // 6
arr.nextCons(); // 8
Check if all numbers in array are consecutives:
Updated March 2022
const allConsecutives = (arr) =>{
if(arr.some(n=> typeof n !== "number" || Number.isNaN(n))) return false;
return arr.every((num, i)=> arr[i+1]-num === 1 || arr[i+1] === undefined)
}
pseudo code:
int count = 0
for i = 0 to array.length - 2
if {array[i + 1] - array[i] = 1 then
count+=1
return i
else count=0}
const array1 = [1,2,3];
const sum = array1.reduce((accumulator, currentValue) =>{
return accumulator + currentValue;
});
const max = Math.max(...array1);
maximum = max
if(sum == maximum * (maximum+1) /2) {
console.log(true);
} else {
console.log(false);
}