Create a unique number with javascript time - javascript
I need to generate unique id numbers on the fly using javascript. In the past, I've done this by creating a number using time. The number would be made up of the four digit year, two digit month, two digit day, two digit hour, two digit minute, two digit second, and three digit millisecond. So it would look something like this: 20111104103912732 ... this would give enough certainty of a unique number for my purposes.
It's been a while since I've done this and I don't have the code anymore. Anyone have the code to do this, or have a better suggestion for generating a unique ID?
A better approach would be:
new Date().valueOf();
instead of
new Date().getUTCMilliseconds();
valueOf() is "most likely" a unique number. http://www.w3schools.com/jsref/jsref_valueof_date.asp.
The shortest way to create a number that you can be pretty sure will be unique among as many separate instances as you can think of is
Date.now() + Math.random()
If there is a 1 millisecond difference in function call, it is 100% guaranteed to generate a different number. For function calls within the same millisecond you should only start to be worried if you are creating more than a few million numbers within this same millisecond, which is not very probable.
For more on the probability of getting a repeated number within the same millisecond see https://stackoverflow.com/a/28220928/4617597
If you just want a unique-ish number, then
var timestamp = new Date().getUTCMilliseconds();
would get you a simple number. But if you need the readable version, you're in for a bit of processing:
var now = new Date();
timestamp = now.getFullYear().toString(); // 2011
timestamp += (now.getMonth < 9 ? '0' : '') + now.getMonth().toString(); // JS months are 0-based, so +1 and pad with 0's
timestamp += ((now.getDate < 10) ? '0' : '') + now.getDate().toString(); // pad with a 0
... etc... with .getHours(), getMinutes(), getSeconds(), getMilliseconds()
This can be achieved simply with the following code:
var date = new Date();
var components = [
date.getYear(),
date.getMonth(),
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
date.getMilliseconds()
];
var id = components.join("");
Here's what I do when I want something smaller than a bunch of numbers - change base.
var uid = (new Date().getTime()).toString(36)
This performs faster than creating a Date instance, uses less code and will always produce a unique number (locally):
function uniqueNumber() {
var date = Date.now();
// If created at same millisecond as previous
if (date <= uniqueNumber.previous) {
date = ++uniqueNumber.previous;
} else {
uniqueNumber.previous = date;
}
return date;
}
uniqueNumber.previous = 0;
jsfiddle: http://jsfiddle.net/j8aLocan/
I've released this on Bower and npm: https://github.com/stevenvachon/unique-number
You could also use something more elaborate such as cuid, puid or shortid to generate a non-number.
I use
Math.floor(new Date().valueOf() * Math.random())
So if by any chance the code is fired at the same time there is also a teeny chance that the random numbers will be the same.
In 2023, you can use the in-browser Crypto API to generate cryptographically strong random values.
function getRandomNumbers() {
const typedArray = new Uint8Array(10);
const randomValues = window.crypto.getRandomValues(typedArray);
return randomValues.join('');
}
console.log(getRandomNumbers());
// 1857488137147725264738
function getRandomNumbers() {
const typedArray = new Uint8Array(10);
const randomValues = window.crypto.getRandomValues(typedArray);
return randomValues.join('');
}
console.log(getRandomNumbers());
both Uint8Array constructor and Crypto.getRandomValues are supported on all major browsers, including IE11
This should do :
var uniqueNumber = new Date().getTime(); // milliseconds since 1st Jan. 1970
if you want a unique number after few mili seconds then use Date.now(), if you want to use it inside a for loop then use Date.now() and Math.random() together
unique number inside a for loop
function getUniqueID(){
for(var i = 0; i< 5; i++)
console.log(Date.now() + ( (Math.random()*100000).toFixed()))
}
getUniqueID()
output:: all numbers are unique
15598251485988384
155982514859810330
155982514859860737
155982514859882244
155982514859883316
unique number without Math.random()
function getUniqueID(){
for(var i = 0; i< 5; i++)
console.log(Date.now())
}
getUniqueID()
output:: Numbers are repeated
1559825328327
1559825328327
1559825328327
1559825328328
1559825328328
From investigating online I came up with the following object that creates a unique id per session:
window.mwUnique ={
prevTimeId : 0,
prevUniqueId : 0,
getUniqueID : function(){
try {
var d=new Date();
var newUniqueId = d.getTime();
if (newUniqueId == mwUnique.prevTimeId)
mwUnique.prevUniqueId = mwUnique.prevUniqueId + 1;
else {
mwUnique.prevTimeId = newUniqueId;
mwUnique.prevUniqueId = 0;
}
newUniqueId = newUniqueId + '' + mwUnique.prevUniqueId;
return newUniqueId;
}
catch(e) {
mwTool.logError('mwUnique.getUniqueID error:' + e.message + '.');
}
}
}
It maybe helpful to some people.
Cheers
Andrew
This also should do:
(function() {
var uniquePrevious = 0;
uniqueId = function() {
return uniquePrevious++;
};
}());
In ES6:
const ID_LENGTH = 36
const START_LETTERS_ASCII = 97 // Use 64 for uppercase
const ALPHABET_LENGTH = 26
const uniqueID = () => [...new Array(ID_LENGTH)]
.map(() => String.fromCharCode(START_LETTERS_ASCII + Math.random() * ALPHABET_LENGTH))
.join('')
Example:
> uniqueID()
> "bxppcnanpuxzpyewttifptbklkurvvetigra"
Always get unique Id in JS
function getUniqueId(){
return (new Date().getTime()).toString(36) + new Date().getUTCMilliseconds();
}
getUniqueId() // Call the function
------------results like
//"ka2high4264"
//"ka2hj115905"
//"ka2hj1my690"
//"ka2hj23j287"
//"ka2hj2jp869"
Updated for 2021, numbers and ids are not guaranteed to be unique but should be satisfactory unique enough:
(oh, and who knew something.toString(36) is even a thing 🙂)
// a pseudo-random floating number based on Date.now()
const generateRandomNumber = () =>
Math.log2(Date.now()) + Math.random();
console.log("a pseudo-random floating number based on Date.now():");
console.log(generateRandomNumber());
// a locally unique-ish HTML id
const generateUniqueId = () => `_${Date.now().toString(36)}${Math.floor(Number.MAX_SAFE_INTEGER * Math.random()).toString(36)}`;
console.log("a locally unique-ish HTML id:");
console.log(generateUniqueId())
// a pseudo-random BigInt
const generateRandomBigInt = () =>
BigInt(Date.now()) * BigInt(Number.MAX_SAFE_INTEGER) +
BigInt(Math.floor(Number.MAX_SAFE_INTEGER * Math.random()));
console.log("a pseudo-random BigInt:");
console.log(generateRandomBigInt().toString());
// same but base32-encoded (each char is 5 bits)
console.log("same but base32-encoded (each char is 5 bits):");
console.log(generateRandomBigInt().toString(32));
// extracting the "Date.now" timestamp of when it was generated:
console.log('extracting the "Date.now" timestamp of when it was generated:');
console.log(Number(generateRandomBigInt() / BigInt(Number.MAX_SAFE_INTEGER)))
// generate a run of random BigInt in ascending order
function generateRandomBigIntFactory() {
let count = 0, prev = 0;
return () => {
const now = Date.now();
if (now === prev) { ++count; }
else { count = 0; prev = now; }
return (BigInt(now) * BigInt(16384) + BigInt(count)) * BigInt(Number.MAX_SAFE_INTEGER) +
BigInt(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER));
}
}
// verify the order is ascending
const generate = generateRandomBigIntFactory();
let prev = 0;
for (let i = 0; i < 65536; i++) {
const num = generate();
if (num <= prev) console.log(`error: ${prev}, ${num}`);
prev = num;
}
console.log("the last random BigInt:");
console.log(prev.toString());
use this:for creating unique number in javascript
var uniqueNumber=(new Date().getTime()).toString(36);
It really works. :)
simple solution I found
var today = new Date().valueOf();
console.log( today );
This creates an almost guaranteed unique 32 character key client side, if you want just numbers change the "chars" var.
var d = new Date().valueOf();
var n = d.toString();
var result = '';
var length = 32;
var p = 0;
var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
for (var i = length; i > 0; --i){
result += ((i & 1) && n.charAt(p) ? '<b>' + n.charAt(p) + '</b>' : chars[Math.floor(Math.random() * chars.length)]);
if(i & 1) p++;
};
https://jsfiddle.net/j0evrdf1/1/
function UniqueValue(d){
var dat_e = new Date();
var uniqu_e = ((Math.random() *1000) +"").slice(-4)
dat_e = dat_e.toISOString().replace(/[^0-9]/g, "").replace(dat_e.getFullYear(),uniqu_e);
if(d==dat_e)
dat_e = UniqueValue(dat_e);
return dat_e;
}
Call 1: UniqueValue('0')
Call 2: UniqueValue(UniqueValue('0')) // will be complex
Sample Output:
for(var i =0;i<10;i++){ console.log(UniqueValue(UniqueValue('0')));}
60950116113248802
26780116113248803
53920116113248803
35840116113248803
47430116113248803
41680116113248803
42980116113248804
34750116113248804
20950116113248804
03730116113248804
Since milliseconds are not updated every millisecond in node, following is an answer. This generates a unique human readable ticket number. I am new to programming and nodejs. Please correct me if I am wrong.
function get2Digit(value) {
if (value.length == 1) return "0" + "" + value;
else return value;
}
function get3Digit(value) {
if (value.length == 1) return "00" + "" + value;
else return value;
}
function generateID() {
var d = new Date();
var year = d.getFullYear();
var month = get2Digit(d.getMonth() + 1);
var date = get2Digit(d.getDate());
var hours = get2Digit(d.getHours());
var minutes = get2Digit(d.getMinutes());
var seconds = get2Digit(d.getSeconds());
var millSeconds = get2Digit(d.getMilliseconds());
var dateValue = year + "" + month + "" + date;
var uniqueID = hours + "" + minutes + "" + seconds + "" + millSeconds;
if (lastUniqueID == "false" || lastUniqueID < uniqueID) lastUniqueID = uniqueID;
else lastUniqueID = Number(lastUniqueID) + 1;
return dateValue + "" + lastUniqueID;
}
let uuid = ((new Date().getTime()).toString(36))+'_'+(Date.now() + Math.random().toString()).split('.').join("_")
sample result "k3jobnvt_15750033412250_18299601769317408"
I came across this question while trying to find a simple UID generation technique that was also sortable (so I can order by uid and items will appear in order of creation / uid generation). The major problem with most (all?) of the solutions here is that they either rely on millisecond accuracy (at best) == clashes(!) or a pseudo-random number == clashes(!) && non-sortable(!).
Technique below uses micro-second precision where available (i.e. not where fingerprinting-resistance techniques are in play, e.g. firefox) combined with an incrementing, stateful suffix. Not perfect, or particularly performant for large numbers of IDs (see example with 1,000,000 below), but it works and is reversible.
// return a uid, sortable by creation order
let increment;
let tuidPrev;
const uid = (uidPrev) => {
// get current time to microsecond precision (if available) and remove decimals
const tuid = ((performance.timing.navigationStart + performance.now()) * 1000)
// convert timestamp to base36 string
.toString(36);
// previous uid has been provided (stateful)
if (uidPrev) {
tuidPrev = uidPrev.slice(0, 10);
increment = uidPrev.length > 10 ? parseInt(uidPrev.slice(10), 36) : 0;
}
// if tuid is changed reset the increment
if (tuid !== tuidPrev) {
tuidPrev = tuid;
increment = 0;
}
// return timed uid + suffix (4^36 values) === very unique id!
return tuid + ('000' + (increment++).toString(36)).slice(-4);
}
// EXAMPLE (check the console!)
const iterations = 1000000;
const uids = [];
const uidMap = {};
const timeMap = {}
const microMap = {};
let time = performance.now();
for (let i = 0; i < iterations; i++) {
const id = uid();
uids.push(id);
uidMap[id] = i;
timeMap[Date.now()] = i;
microMap[performance.now()] = i;
}
console.log(`Time taken: ${performance.now() - time}ms`);
console.log('Unique IDs:', Object.keys(uidMap).length.toLocaleString());
console.log('Clashing timestamps:', (iterations - Object.keys(timeMap).length).toLocaleString());
console.log('Clashing microseconds:', (iterations - Object.keys(microMap).length).toLocaleString());
console.log('Sortable:', !uids.slice().sort().find((id, i) => uids[i] !== id))
The usual way in which I generate unique IDs is by using Date.now();
const ID = Date.now();
console.log(ID);
The other way is by using a library as idgp which can be installed using npm.
The link: https://www.npmjs.com/package/idgp
Assumed that the solution proposed by #abarber it's a good solution because uses (new Date()).getTime() so it has a windows of milliseconds and sum a tick in case of collisions in this interval, we could consider to use built-in as
we can clearly see here in action:
Fist we can see here how there can be collisions in the 1/1000 window frame using (new Date()).getTime():
console.log( (new Date()).getTime() ); console.log( (new Date()).getTime() )
VM1155:1 1469615396590
VM1155:1 1469615396591
console.log( (new Date()).getTime() ); console.log( (new Date()).getTime() )
VM1156:1 1469615398845
VM1156:1 1469615398846
console.log( (new Date()).getTime() ); console.log( (new Date()).getTime() )
VM1158:1 1469615403045
VM1158:1 1469615403045
Second we try the proposed solution that avoid collisions in the 1/1000 window:
console.log( window.mwUnique.getUniqueID() ); console.log( window.mwUnique.getUniqueID() );
VM1159:1 14696154132130
VM1159:1 14696154132131
That said we could consider to use functions like the node process.nextTick that is called in the event loop as a single tick and it's well explained here.
Of course in the browser there is no process.nextTick so we have to figure how how to do that.
This implementation will install a nextTick function in the browser using the most closer functions to the I/O in the browser that are setTimeout(fnc,0), setImmediate(fnc), window.requestAnimationFrame. As suggested here we could add the window.postMessage, but I leave this to the reader since it needs a addEventListener as well. I have modified the original module versions to keep it simpler here:
getUniqueID = (c => {
if(typeof(nextTick)=='undefined')
nextTick = (function(window, prefixes, i, p, fnc) {
while (!fnc && i < prefixes.length) {
fnc = window[prefixes[i++] + 'equestAnimationFrame'];
}
return (fnc && fnc.bind(window)) || window.setImmediate || function(fnc) {window.setTimeout(fnc, 0);};
})(window, 'r webkitR mozR msR oR'.split(' '), 0);
nextTick(() => {
return c( (new Date()).getTime() )
})
})
So we have in the 1/1000 window:
getUniqueID(function(c) { console.log(c); });getUniqueID(function(c) { console.log(c); });
undefined
VM1160:1 1469615416965
VM1160:1 1469615416966
Maybe even better would be to use getTime() or valueOf(), but this way it returns unique plus human understandable number (representing date and time):
window.getUniqNr = function() {
var now = new Date();
if (typeof window.uniqCounter === 'undefined') window.uniqCounter = 0;
window.uniqCounter++;
var m = now.getMonth(); var d = now.getDay();
var h = now.getHours(); var i = now.getMinutes();
var s = now.getSeconds(); var ms = now.getMilliseconds();
timestamp = now.getFullYear().toString()
+ (m <= 9 ? '0' : '') + m.toString()
+( d <= 9 ? '0' : '') + d.toString()
+ (h <= 9 ? '0' : '') + h.toString()
+ (i <= 9 ? '0' : '') + i.toString()
+ (s <= 9 ? '0' : '') + s.toString()
+ (ms <= 9 ? '00' : (ms <= 99 ? '0' : '')) + ms.toString()
+ window.uniqCounter;
return timestamp;
};
window.getUniqNr();
let now = new Date();
let timestamp = now.getFullYear().toString();
let month = now.getMonth() + 1;
timestamp += (month < 10 ? '0' : '') + month.toString();
timestamp += (now.getDate() < 10 ? '0' : '') + now.getDate().toString();
timestamp += (now.getHours() < 10 ? '0' : '') + now.getHours().toString();
timestamp += (now.getMinutes() < 10 ? '0' : '') + now.getMinutes().toString();
timestamp += (now.getSeconds() < 10 ? '0' : '') + now.getSeconds().toString();
timestamp += (now.getMilliseconds() < 100 ? '0' : '') + now.getMilliseconds().toString();
Easy and always get unique value :
const uniqueValue = (new Date()).getTime() + Math.trunc(365 * Math.random());
**OUTPUT LIKE THIS** : 1556782842762
I have done this way
function uniqeId() {
var ranDom = Math.floor(new Date().valueOf() * Math.random())
return _.uniqueId(ranDom);
}
function getUniqueNumber() {
function shuffle(str) {
var a = str.split("");
var n = a.length;
for(var i = n - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
return a.join("");
}
var str = new Date().getTime() + (Math.random()*999 +1000).toFixed() //string
return Number.parseInt(shuffle(str));
}
in reference to #Marcelo Lazaroni solution above
Date.now() + Math.random()
returns a number such as this 1567507511939.4558 (limited to 4 decimals), and will give non-unique numbers (or collisions) every 0.1%.
adding toString() fixes this
Date.now() + Math.random().toString()
returns '15675096840820.04510962122198503' (a string), and
is further so 'slow' that you never get the 'same' millisecond, anyway.
Related
Problems with when trying to sum time using function in javascript
I have tried several suggestions on how to sum hours and minutes but all have failed to me. I'm using this script as a start https://olanaso.github.io/Leaflet-Select-Polygons/# and need to have more rows with other totals from selected polygons, one of them is time (h:mm 00:00). Every polygon has properties with hour and minute, some has 00:00. I have manage to add more totals but when it comes to sum the time it has not worked for me. When you select polygons the totals adds up and when deselect a polygon the totals updates with removing that value. This function "timestrToSec" is one I have been trying, but getting the error "time.split is not a function". Also I don't need days just hours and minutes summed together like "300:15 h:mm" (3 hundred hours and 15 minutes) when selecting polygons och deselecting. $.each(statesData.features, function(index, feature) { var name = `${feature.properties.ZIPCODE} ${feature.properties.Name} ( ${feature.properties.average_time} - ${feature.properties.CITY})` placenames.push(name); zipcodes[name] = feature.properties.ZIPCODE; time = feature.properties.average_time }); More.... // Now get the totals of selected polygons var detailshow = function() { var result = '' var total = 0 var total1 = 0 var total2 = 0 for (var i = 0; i < featuresSelected.length; i++) { var properties = featuresSelected[i].feature.properties result += ` ${properties.CITY}<br> Zipcode: ${properties.ZIPCODE} <a href="#" onclick=dellayer(${properties.ZIPCODE})>Delete</a> <hr>`; total += properties.amount, total1 += properties.average_time, total2 += properties.distance var convertTime = function (input, separator) { var pad = function(input) {return input < 10 ? "0" + input : input;}; return [ pad(Math.floor(input / 3600)), pad(Math.floor(input % 3600 / 60)), pad(Math.floor(input % 60)), ].join(typeof separator !== 'undefined' ? separator : ':' ); } var resultTime = convertTime(total1); } return { result: result, total: total, resultTime: resultTime, total2: total2 }; } detailsselected.update = function(arrayselected) { var details = detailshow() this._div.innerHTML = '<b>Zipcodes</b><br>' + 'Total time: <b>' + details.resultTime + ' hh:mm:ss</b><br>' + 'Amount: <b>' + details.total + ' st</b><br>' + 'Distance: <b>' + details.total2.toFixed(1) + ' km</b><br>'; $('#suma', window.parent.document).val(details.total, details.resultTime, details.total2); }; detailsselected.addTo(map); This is part of the json file structure: var statesData = new L.LayerGroup; var statesData = {"type":"FeatureCollection","features":[{"type":"Feature","properties":{"ZIPCODE":12345,"CITY":"LONDON","REGION":"REGION SOUTH","amount":1088,"average_time":"06:39","distance":2.2},"geometry":{"type":"MultiPolygon","coordinates":...
I didn't really try to follow everything you're doing, but if all you're trying to do is to add together hh:mm times, then something like this should work: const addTimes = (hhmm1, hhmm2) => { const [h1, m1] = hhmm1.split(':').map(Number) const [h2, m2] = hhmm2.split(':').map(Number) const minutes = 60 * h1 + m1 + 60 * h2 + m2 return `${Math.floor(minutes / 60)}:${String(minutes % 60).padStart(2, '0')}` } const addManyTimes = (ts) => ts.reduce(addTimes, '0:00') console .log (addTimes ('3:41', '7:55')) //=> '11:36' console .log (addManyTimes (['2:12', '3:07', '8:39', '6:21', '5:59'])) //=> '26:18' It would be easy enough to extend this to seconds as well if that were necessary.
How to distinguish time from am and pm in the value of a variable?
I have the following values. var list = "09:05, 10:05, 12:30, 16:30 , ... , ..." The type of values ​​in the list is a regular string, not an object. Based on this value, I want to divide from 0 to 12 am and from 13 to 23 pm. Therefore, the result I want is as follows.(If you check the log value) var am = am 09:05 , am 10:05 var pm = pm 12:30 , pm 16:30 It may be a simple question, but it is a very difficult problem for me as a script novice. Please help me.
Create a sort function first var sort = ( a, b ) => convertToMin( a ) - convertToMin( b ); var convertToMin = ( a ) => ( items = a.split( ":" ).map( Number ), items[ 0 ] * 60 + items[ 1 ] ); Now use reduce to segregate the array var output = list.reduce( (a,b) => //using reduce to iterate, a is the accumulator and b is item in array for current iteration ( convertToMin(b) > 12*60 ? a.pm.push( b ) : a.am.push( b ), a ) , { am :[], pm : [] }) ; //accumulator is initialized to { am :[], pm : [] } output.am.sort( sort ); output.pm.sort( sort ); Demo var list = ["09:05", "10:05", "12:30", "16:30"]; var sort = (a, b) => convertToMin(a) - convertToMin(b); var convertToMin = (a) => (items = a.split(":").map(Number), items[0] * 60 + items[1]); var output = list.reduce((a, b) => (convertToMin(b) > 12 * 60 ? a.pm.push(b) : a.am.push(b), a), { am: [], pm: [] }); output.am.sort(sort); output.pm.sort(sort); console.log(output);
Here's what I'd do to solve this problem. Separate the values in the string into an array. I'd Google javascript split string into array. Nothing wrong with Googling stuff; even seasoned devs have to do it all the time! At least I do. :) Then create a for loop that goes through each element of the array. A good search for how to do that is javascript for loop array. Then for each element, split the string again (this time by the :). Then convert the first part into a number (javascript convert string to integer) and see whether it is bigger or smaller than 12.
You could adjusted value with am/pm time and sort it to the wanted array. function format(v) { return ('0' + v).slice(-2); } function getM(t) { var v = t.split(':'); return (v[0] < 12 ? 'am' : 'pm') + ' ' + [v[0] % 12 || 12, v[1]].map(format).join(':'); } var list = '09:05, 10:05, 12:30, 16:30', am = [], pm = [] result = { am: am, pm: pm }; list .split(', ') .map(getM) .forEach(function (s) { result[s.slice(0, 2)].push(s); }); console.log(am); console.log(pm); .as-console-wrapper { max-height: 100% !important; top: 0; }
Split the items using the appropriate separator, process them with a cycle then join them with the appropriate separator var items = list.split(", "); var ams = []; var pms = []; for (var index = 0; index < list.length; index++) { var isPM = ((list[index].substring(0, 2) >= 12); var currentArray = window[isPM ? "pms" : "ams"]; var found = false; var val = (isPM ? "pm" : "am") + " " + items[index]; for (var innerIndex = 0; (!found) && (innerIndex < currentArray.length); innerIndex++) { if (currentArray[innerIndex] > val) { found = true; currentArray.splice(innerIndex, 0, val); } } if (!found) currentArray.push(val); } var am = ams.join(" , "); var pm = pms.join(" , ");
Try with .split method like this, Updated without jQuery var list = "09:05, 10:05, 12:30, 16:30"; var options = list.split(',').map(time => { h = time.split(':')[0]; return parseInt(h) >= 12 ? 'pm ' + time : 'am ' + time; }) console.log(options);
which are alternative of tofixed() in javascript [duplicate]
Suppose I have a value of 15.7784514, I want to display it 15.77 with no rounding. var num = parseFloat(15.7784514); document.write(num.toFixed(1)+"<br />"); document.write(num.toFixed(2)+"<br />"); document.write(num.toFixed(3)+"<br />"); document.write(num.toFixed(10)); Results in - 15.8 15.78 15.778 15.7784514000 How do I display 15.77?
Convert the number into a string, match the number up to the second decimal place: function calc(theform) { var num = theform.original.value, rounded = theform.rounded var with2Decimals = num.toString().match(/^-?\d+(?:\.\d{0,2})?/)[0] rounded.value = with2Decimals } <form onsubmit="return calc(this)"> Original number: <input name="original" type="text" onkeyup="calc(form)" onchange="calc(form)" /> <br />"Rounded" number: <input name="rounded" type="text" placeholder="readonly" readonly> </form> The toFixed method fails in some cases unlike toString, so be very careful with it.
Update 5 Nov 2016 New answer, always accurate function toFixed(num, fixed) { var re = new RegExp('^-?\\d+(?:\.\\d{0,' + (fixed || -1) + '})?'); return num.toString().match(re)[0]; } As floating point math in javascript will always have edge cases, the previous solution will be accurate most of the time which is not good enough. There are some solutions to this like num.toPrecision, BigDecimal.js, and accounting.js. Yet, I believe that merely parsing the string will be the simplest and always accurate. Basing the update on the well written regex from the accepted answer by #Gumbo, this new toFixed function will always work as expected. Old answer, not always accurate. Roll your own toFixed function: function toFixed(num, fixed) { fixed = fixed || 0; fixed = Math.pow(10, fixed); return Math.floor(num * fixed) / fixed; }
Another single-line solution : number = Math.trunc(number*100)/100 I used 100 because you want to truncate to the second digit, but a more flexible solution would be : number = Math.trunc(number*Math.pow(10, digits))/Math.pow(10, digits) where digits is the amount of decimal digits to keep. See Math.trunc specs for details and browser compatibility.
I opted to write this instead to manually remove the remainder with strings so I don't have to deal with the math issues that come with numbers: num = num.toString(); //If it's not already a String num = num.slice(0, (num.indexOf("."))+3); //With 3 exposing the hundredths place Number(num); //If you need it back as a Number This will give you "15.77" with num = 15.7784514;
Update (Jan 2021) Depending on its range, a number in javascript may be shown in scientific notation. For example, if you type 0.0000001 in the console, you may see it as 1e-7, whereas 0.000001 appears unchanged (0.000001). If your application works on a range of numbers for which scientific notation is not involved, you can just ignore this update and use the original answer below. This update is about adding a function that checks if the number is in scientific format and, if so, converts it into decimal format. Here I'm proposing this one, but you can use any other function that achieves the same goal, according to your application's needs: function toFixed(x) { if (Math.abs(x) < 1.0) { let e = parseInt(x.toString().split('e-')[1]); if (e) { x *= Math.pow(10,e-1); x = '0.' + (new Array(e)).join('0') + x.toString().substring(2); } } else { let e = parseInt(x.toString().split('+')[1]); if (e > 20) { e -= 20; x /= Math.pow(10,e); x += (new Array(e+1)).join('0'); } } return x; } Now just apply that function to the parameter (that's the only change with respect to the original answer): function toFixedTrunc(x, n) { x = toFixed(x) // From here on the code is the same than the original answer const v = (typeof x === 'string' ? x : x.toString()).split('.'); if (n <= 0) return v[0]; let f = v[1] || ''; if (f.length > n) return `${v[0]}.${f.substr(0,n)}`; while (f.length < n) f += '0'; return `${v[0]}.${f}` } This updated version addresses also a case mentioned in a comment: toFixedTrunc(0.000000199, 2) => "0.00" Again, choose what fits your application needs at best. Original answer (October 2017) General solution to truncate (no rounding) a number to the n-th decimal digit and convert it to a string with exactly n decimal digits, for any n≥0. function toFixedTrunc(x, n) { const v = (typeof x === 'string' ? x : x.toString()).split('.'); if (n <= 0) return v[0]; let f = v[1] || ''; if (f.length > n) return `${v[0]}.${f.substr(0,n)}`; while (f.length < n) f += '0'; return `${v[0]}.${f}` } where x can be either a number (which gets converted into a string) or a string. Here are some tests for n=2 (including the one requested by OP): 0 => 0.00 0.01 => 0.01 0.5839 => 0.58 0.999 => 0.99 1.01 => 1.01 2 => 2.00 2.551 => 2.55 2.99999 => 2.99 4.27 => 4.27 15.7784514 => 15.77 123.5999 => 123.59 And for some other values of n: 15.001097 => 15.0010 (n=4) 0.000003298 => 0.0000032 (n=7) 0.000003298257899 => 0.000003298257 (n=12)
parseInt is faster then Math.floor function floorFigure(figure, decimals){ if (!decimals) decimals = 2; var d = Math.pow(10,decimals); return (parseInt(figure*d)/d).toFixed(decimals); }; floorFigure(123.5999) => "123.59" floorFigure(123.5999, 3) => "123.599"
num = 19.66752 f = num.toFixed(3).slice(0,-1) alert(f) This will return 19.66
Simple do this number = parseInt(number * 100)/100;
Just truncate the digits: function truncDigits(inputNumber, digits) { const fact = 10 ** digits; return Math.floor(inputNumber * fact) / fact; }
This is not a safe alternative, as many others commented examples with numbers that turn into exponential notation, that scenery is not covered by this function // typescript // function formatLimitDecimals(value: number, decimals: number): number { function formatLimitDecimals(value, decimals) { const stringValue = value.toString(); if(stringValue.includes('e')) { // TODO: remove exponential notation throw 'invald number'; } else { const [integerPart, decimalPart] = stringValue.split('.'); if(decimalPart) { return +[integerPart, decimalPart.slice(0, decimals)].join('.') } else { return integerPart; } } } console.log(formatLimitDecimals(4.156, 2)); // 4.15 console.log(formatLimitDecimals(4.156, 8)); // 4.156 console.log(formatLimitDecimals(4.156, 0)); // 4 console.log(formatLimitDecimals(0, 4)); // 0 // not covered console.log(formatLimitDecimals(0.000000199, 2)); // 0.00
These solutions do work, but to me seem unnecessarily complicated. I personally like to use the modulus operator to obtain the remainder of a division operation, and remove that. Assuming that num = 15.7784514: num-=num%.01; This is equivalent to saying num = num - (num % .01).
I fixed using following simple way- var num = 15.7784514; Math.floor(num*100)/100; Results will be 15.77
My version for positive numbers: function toFixed_norounding(n,p) { var result = n.toFixed(p); return result <= n ? result: (result - Math.pow(0.1,p)).toFixed(p); } Fast, pretty, obvious. (version for positive numbers)
The answers here didn't help me, it kept rounding up or giving me the wrong decimal. my solution converts your decimal to a string, extracts the characters and then returns the whole thing as a number. function Dec2(num) { num = String(num); if(num.indexOf('.') !== -1) { var numarr = num.split("."); if (numarr.length == 1) { return Number(num); } else { return Number(numarr[0]+"."+numarr[1].charAt(0)+numarr[1].charAt(1)); } } else { return Number(num); } } Dec2(99); // 99 Dec2(99.9999999); // 99.99 Dec2(99.35154); // 99.35 Dec2(99.8); // 99.8 Dec2(10265.985475); // 10265.98
The following code works very good for me: num.toString().match(/.\*\\..{0,2}|.\*/)[0];
This worked well for me. I hope it will fix your issues too. function toFixedNumber(number) { const spitedValues = String(number.toLocaleString()).split('.'); let decimalValue = spitedValues.length > 1 ? spitedValues[1] : ''; decimalValue = decimalValue.concat('00').substr(0,2); return '$'+spitedValues[0] + '.' + decimalValue; } // 5.56789 ----> $5.56 // 0.342 ----> $0.34 // -10.3484534 ----> $-10.34 // 600 ----> $600.00 function convertNumber(){ var result = toFixedNumber(document.getElementById("valueText").value); document.getElementById("resultText").value = result; } function toFixedNumber(number) { const spitedValues = String(number.toLocaleString()).split('.'); let decimalValue = spitedValues.length > 1 ? spitedValues[1] : ''; decimalValue = decimalValue.concat('00').substr(0,2); return '$'+spitedValues[0] + '.' + decimalValue; } <div> <input type="text" id="valueText" placeholder="Input value here.."> <br> <button onclick="convertNumber()" >Convert</button> <br><hr> <input type="text" id="resultText" placeholder="result" readonly="true"> </div>
An Easy way to do it is the next but is necessary ensure that the amount parameter is given as a string. function truncate(amountAsString, decimals = 2){ var dotIndex = amountAsString.indexOf('.'); var toTruncate = dotIndex !== -1 && ( amountAsString.length > dotIndex + decimals + 1); var approach = Math.pow(10, decimals); var amountToTruncate = toTruncate ? amountAsString.slice(0, dotIndex + decimals +1) : amountAsString; return toTruncate ? Math.floor(parseFloat(amountToTruncate) * approach ) / approach : parseFloat(amountAsString); } console.log(truncate("7.99999")); //OUTPUT ==> 7.99 console.log(truncate("7.99999", 3)); //OUTPUT ==> 7.999 console.log(truncate("12.799999999999999")); //OUTPUT ==> 7.99
Here you are. An answer that shows yet another way to solve the problem: // For the sake of simplicity, here is a complete function: function truncate(numToBeTruncated, numOfDecimals) { var theNumber = numToBeTruncated.toString(); var pointIndex = theNumber.indexOf('.'); return +(theNumber.slice(0, pointIndex > -1 ? ++numOfDecimals + pointIndex : undefined)); } Note the use of + before the final expression. That is to convert our truncated, sliced string back to number type. Hope it helps!
truncate without zeroes function toTrunc(value,n){ return Math.floor(value*Math.pow(10,n))/(Math.pow(10,n)); } or function toTrunc(value,n){ x=(value.toString()+".0").split("."); return parseFloat(x[0]+"."+x[1].substr(0,n)); } test: toTrunc(17.4532,2) //17.45 toTrunc(177.4532,1) //177.4 toTrunc(1.4532,1) //1.4 toTrunc(.4,2) //0.4 truncate with zeroes function toTruncFixed(value,n){ return toTrunc(value,n).toFixed(n); } test: toTrunc(17.4532,2) //17.45 toTrunc(177.4532,1) //177.4 toTrunc(1.4532,1) //1.4 toTrunc(.4,2) //0.40
If you exactly wanted to truncate to 2 digits of precision, you can go with a simple logic: function myFunction(number) { var roundedNumber = number.toFixed(2); if (roundedNumber > number) { roundedNumber = roundedNumber - 0.01; } return roundedNumber; }
I used (num-0.05).toFixed(1) to get the second decimal floored.
It's more reliable to get two floating points without rounding. Reference Answer var number = 10.5859; var fixed2FloatPoints = parseInt(number * 100) / 100; console.log(fixed2FloatPoints); Thank You !
My solution in typescript (can easily be ported to JS): /** * Returns the price with correct precision as a string * * #param price The price in decimal to be formatted. * #param decimalPlaces The number of decimal places to use * #return string The price in Decimal formatting. */ type toDecimal = (price: number, decimalPlaces?: number) => string; const toDecimalOdds: toDecimal = ( price: number, decimalPlaces: number = 2, ): string => { const priceString: string = price.toString(); const pointIndex: number = priceString.indexOf('.'); // Return the integer part if decimalPlaces is 0 if (decimalPlaces === 0) { return priceString.substr(0, pointIndex); } // Return value with 0s appended after decimal if the price is an integer if (pointIndex === -1) { const padZeroString: string = '0'.repeat(decimalPlaces); return `${priceString}.${padZeroString}`; } // If numbers after decimal are less than decimalPlaces, append with 0s const padZeroLen: number = priceString.length - pointIndex - 1; if (padZeroLen > 0 && padZeroLen < decimalPlaces) { const padZeroString: string = '0'.repeat(padZeroLen); return `${priceString}${padZeroString}`; } return priceString.substr(0, pointIndex + decimalPlaces + 1); }; Test cases: expect(filters.toDecimalOdds(3.14159)).toBe('3.14'); expect(filters.toDecimalOdds(3.14159, 2)).toBe('3.14'); expect(filters.toDecimalOdds(3.14159, 0)).toBe('3'); expect(filters.toDecimalOdds(3.14159, 10)).toBe('3.1415900000'); expect(filters.toDecimalOdds(8.2)).toBe('8.20'); Any improvements?
Another solution, that truncates and round: function round (number, decimals, truncate) { if (truncate) { number = number.toFixed(decimals + 1); return parseFloat(number.slice(0, -1)); } var n = Math.pow(10.0, decimals); return Math.round(number * n) / n; };
function limitDecimalsWithoutRounding(val, decimals){ let parts = val.toString().split("."); return parseFloat(parts[0] + "." + parts[1].substring(0, decimals)); } var num = parseFloat(15.7784514); var new_num = limitDecimalsWithoutRounding(num, 2);
Roll your own toFixed function: for positive values Math.floor works fine. function toFixed(num, fixed) { fixed = fixed || 0; fixed = Math.pow(10, fixed); return Math.floor(num * fixed) / fixed; } For negative values Math.floor is round of the values. So you can use Math.ceil instead. Example, Math.ceil(-15.778665 * 10000) / 10000 = -15.7786 Math.floor(-15.778665 * 10000) / 10000 = -15.7787 // wrong.
Gumbo's second solution, with the regular expression, does work but is slow because of the regular expression. Gumbo's first solution fails in certain situations due to imprecision in floating points numbers. See the JSFiddle for a demonstration and a benchmark. The second solution takes about 1636 nanoseconds per call on my current system, Intel Core i5-2500 CPU at 3.30 GHz. The solution I've written involves adding a small compensation to take care of floating point imprecision. It is basically instantaneous, i.e. on the order of nanoseconds. I clocked 2 nanoseconds per call but the JavaScript timers are not very precise or granular. Here is the JS Fiddle and the code. function toFixedWithoutRounding (value, precision) { var factorError = Math.pow(10, 14); var factorTruncate = Math.pow(10, 14 - precision); var factorDecimal = Math.pow(10, precision); return Math.floor(Math.floor(value * factorError + 1) / factorTruncate) / factorDecimal; } var values = [1.1299999999, 1.13, 1.139999999, 1.14, 1.14000000001, 1.13 * 100]; for (var i = 0; i < values.length; i++) { var value = values[i]; console.log(value + " --> " + toFixedWithoutRounding(value, 2)); } for (var i = 0; i < values.length; i++) { var value = values[i]; console.log(value + " --> " + toFixedWithoutRounding(value, 4)); } console.log("type of result is " + typeof toFixedWithoutRounding(1.13 * 100 / 100, 2)); // Benchmark var value = 1.13 * 100; var startTime = new Date(); var numRun = 1000000; var nanosecondsPerMilliseconds = 1000000; for (var run = 0; run < numRun; run++) toFixedWithoutRounding(value, 2); var endTime = new Date(); var timeDiffNs = nanosecondsPerMilliseconds * (endTime - startTime); var timePerCallNs = timeDiffNs / numRun; console.log("Time per call (nanoseconds): " + timePerCallNs);
Building on David D's answer: function NumberFormat(num,n) { var num = (arguments[0] != null) ? arguments[0] : 0; var n = (arguments[1] != null) ? arguments[1] : 2; if(num > 0){ num = String(num); if(num.indexOf('.') !== -1) { var numarr = num.split("."); if (numarr.length > 1) { if(n > 0){ var temp = numarr[0] + "."; for(var i = 0; i < n; i++){ if(i < numarr[1].length){ temp += numarr[1].charAt(i); } } num = Number(temp); } } } } return Number(num); } console.log('NumberFormat(123.85,2)',NumberFormat(123.85,2)); console.log('NumberFormat(123.851,2)',NumberFormat(123.851,2)); console.log('NumberFormat(0.85,2)',NumberFormat(0.85,2)); console.log('NumberFormat(0.851,2)',NumberFormat(0.851,2)); console.log('NumberFormat(0.85156,2)',NumberFormat(0.85156,2)); console.log('NumberFormat(0.85156,4)',NumberFormat(0.85156,4)); console.log('NumberFormat(0.85156,8)',NumberFormat(0.85156,8)); console.log('NumberFormat(".85156",2)',NumberFormat(".85156",2)); console.log('NumberFormat("0.85156",2)',NumberFormat("0.85156",2)); console.log('NumberFormat("1005.85156",2)',NumberFormat("1005.85156",2)); console.log('NumberFormat("0",2)',NumberFormat("0",2)); console.log('NumberFormat("",2)',NumberFormat("",2)); console.log('NumberFormat(85156,8)',NumberFormat(85156,8)); console.log('NumberFormat("85156",2)',NumberFormat("85156",2)); console.log('NumberFormat("85156.",2)',NumberFormat("85156.",2)); // NumberFormat(123.85,2) 123.85 // NumberFormat(123.851,2) 123.85 // NumberFormat(0.85,2) 0.85 // NumberFormat(0.851,2) 0.85 // NumberFormat(0.85156,2) 0.85 // NumberFormat(0.85156,4) 0.8515 // NumberFormat(0.85156,8) 0.85156 // NumberFormat(".85156",2) 0.85 // NumberFormat("0.85156",2) 0.85 // NumberFormat("1005.85156",2) 1005.85 // NumberFormat("0",2) 0 // NumberFormat("",2) 0 // NumberFormat(85156,8) 85156 // NumberFormat("85156",2) 85156 // NumberFormat("85156.",2) 85156
Already there are some suitable answer with regular expression and arithmetic calculation, you can also try this function myFunction() { var str = 12.234556; str = str.toString().split('.'); var res = str[1].slice(0, 2); document.getElementById("demo").innerHTML = str[0]+'.'+res; } // output: 12.23
Here is what is did it with string export function withoutRange(number) { const str = String(number); const dotPosition = str.indexOf('.'); if (dotPosition > 0) { const length = str.substring().length; const end = length > 3 ? 3 : length; return str.substring(0, dotPosition + end); } return str; }
How can I count the number of zero decimals in JavaScript?
How do I get the number of zero decimals behind the comma (but not the total)? So to illustrate an example: 0.00001 > 4 0.000015 > 4 0.0000105 > 4 0.001 > 2 I am looking for methods that are efficient (meaning that they optimize the calculation time).
You can use logarithms to find the magnitude of the number: var x = 0.00195; var m = -Math.floor( Math.log(x) / Math.log(10) + 1); document.write(m); // outputs 2 Later versions of JavaScript have Math.log10, so it would be: var x = 0.00195; var m = -Math.floor( Math.log10(x) + 1); document.write(m); // outputs 2 How using the base-10 logarithm of the numbers works: x Math.log10(x) Math.floor(Math.log10(x) + 1 ) 0.1 -1 0 0.01 -2 -1 0.015 -1.8239… -1 0.001 -3 -2 0.00001 -5 -4 0.000015 -4.8239… -4 0.0000105 -4.9788… -4
Use a regex to match the number of zeros after a decimal point and then count them. var zeros = float.toString().match(/(\.0*)/)[0].length - 1; DEMO
Use this one: function numberOfZeros(n) { var c = 0; while (!~~n) { c++; n *= 10; } return c - 1; } document.write(numberOfZeros(0.00065)); This code does the following: it multiplies the number by ten as long as it can be truncated to something not equal 0. The truncation operator "~~" is very performant, because it works with byte representation of the number directly. It doesn't use any string operations and does exactly what you want: counts the zeros.
//my answer function t1() { var num = 0.0000005323; numOfZeroes = 0; while(num < 1) { numOfZeroes++; num *= 10; } } //others //Andrew Morton's answer //https://stackoverflow.com/a/31002148/1115360 function t2() { var num = 0.0000005323; var m = -Math.floor( Math.log10(num) + 1); } //Amy's Answer //https://stackoverflow.com/a/31002087/4801298 function t3() { var r = 0.0000005323; var count=0; var splited = r.toString().split(".")[1]; for(var i=0;i<splited.length;i++) { if(splited[i]==0) { count++; } else { break; } } } //Ted's Answer //https://stackoverflow.com/a/31002052/4801298 function t4() { var number = 0.0000005323; var numberAsString = number.toString(); var decimalsAsString = numberAsString.substr(numberAsString.lastIndexOf('.')+1); var leadingZeros = decimalsAsString.substr(0, decimalsAsString.lastIndexOf('0')+1).length; } //Bartłomiej Zalewski's answer //https://stackoverflow.com/a/31001998/4801298 function t5() { var n = 0.0000005323; var c = 0; while (!~~n) { c++; n *= 10; } return c - 1; } //Andy 's answer //https://stackoverflow.com/a/31002135/4801298 function t6() { var float = 0.0000005323; var zeros = float.toString().match(/(\.0*)/)[0].length - 1; } //Praveen's answer //https://stackoverflow.com/a/31002011/4801298 function t7() { var a = 0.0000005323; return (a.toString().replace("0.", "").split("0").length - 1); } //benchmark function function bench(func) { var times = new Array(); for(var t = 0; t < 100; t++) { var start = performance.now(); for(var i = 0; i < 10000; i++) { func(); } var end = performance.now(); var time = end - start; times.push(time); } var total = 0.0; for(var i=0, l=times.length; i<l; i++) total += times[i]; var avg = total / times.length; return avg; } document.write('t1: ' + bench(t1) + "ms<BR>"); document.write('t2: ' + bench(t2) + "ms<BR>"); document.write('t3: ' + bench(t3) + "ms<BR>"); document.write('t4: ' + bench(t4) + "ms<BR>"); document.write('t5: ' + bench(t5) + "ms<BR>"); document.write('t6: ' + bench(t6) + "ms<BR>"); document.write('t7: ' + bench(t7) + "ms<BR>"); Note: This would only work with numbers less than 1 of course. Otherwise, just remove numbers left of the decimal point first, like num -= num % 1; need to compare this to another way. a while later... I would like a better way to bench these function though. I might have my calculation wrong. I'm adding other peoples answers into the test. I'm now attempting to use the performance API a bit later than before AHA! Got it working. Here are some comparisons for you.
You can use something like this: function num (a) { return (a.toString().replace("0.", "").split("0").length - 1) }
Here is a working example (a bit lengthy for clarity): var number = 0.0004342; var numberAsString = number.toString(); var decimalsAsString = numberAsString.substr(numberAsString.lastIndexOf('.')+1); var leadingZeros = decimalsAsString.substr(0, decimalsAsString.lastIndexOf('0')+1).length; // leadingZeros == 3
Convert the number in to a string and split it with the dot (.). Using the for loop to count the zeros occurrences. var r = 0.0000107; var count=0; var splited = r.toString().split(".")[1]; for(var i=0;i<splited.length;i++) { if(splited[i]==0) { count++; } else { break; } } console.log(count);
Node.js 9.0.0 I was looking for a solution without converting or the O(n) approach. Here is what solution I made by O(1). Part of finding decimal by log – caught from #AndrewMorton, but it might be laggy with the divider: log(10) – 2.302585092994046. Example const normalize = (value, zeroCount) => { const total = 10 ** zeroCount const zeros = Math.floor(-Math.log10(value / total)) return value * (10 ** zeros) } Usage normalize(1510869600, 13) // 1510869600000 normalize(1510869600, 10) // 1510869600
Re-write malformed dates yyyy-M-d to yyyy-MM-dd in javascript using RegEx
So I'm rewriting dates in javacript and as familiar js spits dates like 2013-1-1 that isn't very useful always. Instead I'm looking for a routine that will form this date to the correct iso-version 2013-01-01 Today I make this by using string var b = new Date('2013-1-1'); var result = b.getFullYear() + "-" + (b.getMonth().toString().length == 1 ? "0" + parseInt(b.getMonth() + 1) : parseInt(b.getMonth() + 1)) + "-" + (b.getDate().toString().length == 1 ? "0" + b.getDate() : b.getDate()); This works but it is ugly. Is there a better way to perform this using RegEx? Please spare me of any anti-regex comments
A non-regex solution would be a generic padding function. First get your date in the non-padded version then you can split on the separator and pad it as necessary. Something like this: var date = '2013-1-1'; var pad = function(n) { return function(str) { while (str.length < n) { str = '0'+ str; } return str; } }; date = date.split(/-/g).map(pad(2)).join('-'); //=> 2013-01-01
may be this could help: var str="2013-1-1"; var m = str.match(/^(\d{4})-(\d{1})-(\d{1})$/); console.log([m[1], "0".concat([2]-1), "0".concat(m[3])].join('-'));
based on elclanrs suggestion I wrote an extension method // Add 0 to single numbers Number.prototype.padDate = function () { // Add +1 if input is 0 (js months starts at 0) var number = this == 0 ? 1 : this; return number.toString().length == 1 ? "0" + number : number; }; This allows me to build dates like this var b = new Date('2013-1-1'); var result = b.getFullYear() + "-" + b.getMonth().padDate() + "-" + b.getDate().padDate(); Much cleaner, thanks