Problems with when trying to sum time using function in javascript - 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.

Related

Compounding interest monthly with a deposit

I want to compound interest on a weekly/fortnightly/monthly/annual basis.
I also want an option to have a deposit amount that can be added in.
I have already tried the standard formula of calculating the final amount accrued, as seen here:
(source: gstatic.com)
For example here is my method for calculating the interest compounding weekly:
function calculateWeekly(state: any) {
const { savings, deposit ,interest, timePeriodSelector, timePeriodLength } = state;
let numberOfYears = 0;
if (timePeriodSelector === "weekly") {
numberOfYears = timePeriodLength / weeksInAYear;
} else if (timePeriodSelector === "fortnightly") {
numberOfYears = (timePeriodLength / weeksInAYear) * 2;
} else if (timePeriodSelector === "monthly") {
numberOfYears = (timePeriodLength / weeksInAYear) * weeksInAMonth;
} else if (timePeriodSelector === "annually") {
numberOfYears = (timePeriodLength / weeksInAYear) * weeksInAYear;
}
const weeklyRate = interest / 100 / weeksInAYear;
const lengthOfCompunding = numberOfYears * weeksInAYear;
let startingFigure = parseInt(savings) + parseInt(deposit);
//total gets added on for every time cycle of week
let total =
(startingFigure * (Math.pow(1 + weeklyRate, lengthOfCompunding) - 1)) / weeklyRate;
return roundToTwoDP(total);
}
The issue with the above code is that the deposit gets added into the calculation every time the interest accrues. So a deposit of $10 weekly for 10 weeks will actually get added up to $100.
I attempted a method to accrue the interest using a loop for each week here:
// loops how many times to compound the interest
for(let i = numberOfYears - (1/weeksInAYear); i > 0; i-= (1/weeksInAYear)){
let interestGained = (total * (Math.pow((1 + weeklyRate), lengthOfCompunding))) - total;
total += interestGained + savings;
}
Thanks for any help!
This should do what you want:
const range = (min, max) => {
const size = 1 + max - min
return [...Array(size).keys()].map(n => n + min)
}
const weeksInAYear = 52
const addWeeklyInterest = interestRatePerWeek => (savings, _) => savings + savings * interestRatePerWeek
const calculateTotal = (savings, numberOfYears, interestRatePerWeek) => {
const numberOfWeeks = numberOfYears * weeksInAYear
return range(1, numberOfWeeks).reduce(addWeeklyInterest(interestRatePerWeek), savings)
}
console.log(calculateTotal(1000.00, 1, 0.02))
Output is 2800.328185448178. You might want to round that for display purposes, but also keep in mind that if accuracy is important, you can't use floating-point numbers.

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);

JQuery setting a number format

I'm using JQuery and I'm having a problem trying to sort out how to increase a number.
The record number is something like 1364-14-1234.
The number format works like this:
1364 - Member number
14 - Year in 2 digit format
1234 - in the number which needs to be increased.
The problem is how do I add a leading zero to the number to keep a 4 digit number if the number is 0123.
<div id="member_id">1364-14-0001</div>
var data = $('#member_id').text();
var arr = data.split('-');
var num = arr[2];
num++;
$("#member_id").html(arr[0] + " - " + arr[1] + " - " + num);
My JSfiddle
Something like this maybe
function pad(numb, len) {
while (numb.toString().length < len) numb = '0' + numb;
return numb;
}
$('#member_id').text(function(_, txt) {
var arr = txt.split('-'),
len = arr[2].length;
arr[2] = pad(+(arr[2]) + 1, len);
return arr.join('-')
});
FIDDLE

image based count down clock

I have a count down clock which works absolutely fine. Now the question is can I display images as digits instead of html. I cant seem to figure out the logic how would I approach it. I really dont want to use a plugin for this so that is really not an option.
and the JS for the clock is this
setInterval(function(){
var future = new Date("Jan 20 2014 21:15:00 GMT+0200");
var now = new Date();
var difference = Math.floor((future.getTime() - now.getTime()) / 1000);
var seconds = fixIntegers(difference % 60);
difference = Math.floor(difference / 60);
var minutes = fixIntegers(difference % 60);
difference = Math.floor(difference / 60);
var hours = fixIntegers(difference % 24);
difference = Math.floor(difference / 24);
var days = difference;
$(".seconds").text(seconds + "s");
$(".minutes").text(minutes + "m");
$(".hours").text(hours + "h");
$(".days").text(days + "d");
}, 1000);
function fixIntegers(integer)
{
if (integer < 0)
integer = 0;
if (integer < 10)
return "0" + integer;
return "" + integer;
}
I have stored the images in an array which is this
var linkCons = 'http://soumghosh.com/otherProjects/Numbers/'
var num = [];
var linkCons = "http://soumghosh.com/otherProjects/Numbers/";
for(var i = 0; i < 10; i++) {
num.push(linkCons + "nw" + i + ".png");
}
Thanks to stack overflow folks helping me cleaning the array. Really appriciate it
And here is the working fiddle
http://jsfiddle.net/sghoush1/wvbPq/3/
You can do it using only one sprite image and this bit of code I created:
jQuery(function($) { // DOM ready shorthand
// CLOCK
// Just a date in the future... Say 5 days from now
var fut = new Date().setDate(new Date().getDate() + 5);
// Number splitter
function intSpl(i) {
i = Math.floor(i);
return [Math.floor(i / 10), i % 10]; // 37=[3,7] // 5=[0,5] // 0=[0,0]
}
var obj = {}; // {d:[7,7], h:[1,9], .....}
function drawTime() {
var now = new Date().getTime();
var dif = now < fut ? Math.floor((fut - now) / 1000) : 0;
obj.s = intSpl(dif % 60);
obj.m = intSpl(dif / 60 % 60);
obj.h = intSpl(dif / 60 / 60 % 24);
obj.d = intSpl(dif / 60 / 60 / 24);
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
for (var i = 0; i < 2; i++) { // get el ID number (0,1)
$('#' + key + i).css({
backgroundPosition: -obj[key][i] * 50
});
}
}
}
}
drawTime();
setInterval(drawTime, 1000);
});
#clock span {
display: inline-block;
width: 50px;
height: 85px;
background: url('http://i.imgur.com/uBTxTTD.jpg');
background-position: 0 0;
}
#clock span:nth-child(even) {
margin-right: 15px;
}
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<div id="clock">
<span id="d0"></span>
<span id="d1"></span>
<span id="h0"></span>
<span id="h1"></span>
<span id="m0"></span>
<span id="m1"></span>
<span id="s0"></span>
<span id="s1"></span>
</div>
To explain the idea:
Create elements, each will hold a one digit of the current 2 digits value;
Set a common bg image to all spans in CSS
Every second move each element's background-image left by -(witdh * number) px
While the listed above seems logic, the first problem you can see here is how to retrieve separately a JS time number (1 or 2 digits) keep leading zero if needed, and reference each digit to target the right element in HTML?
Let's start by splitting numbers:
35 == 3, 5 /// 0 == 0, 0 // this is an example of what we need.
var n = 35; // Set any 1 or 2 digit number.
var n1 = ~~(n/10); // 3 //// ~~ "Double Bitwise NOT"
// just instead of parseInt(time/10, 10).
var n2 = n%10; // 5 //// % "Mudulus operator" (reminder).
Example playground
JS Grouping
Now, how to group this two separated digits and say: "Hey you two are for my clock seconds!" ?
By simply putting them into an array! [3, 5], and for we'll have also minutes, hours and day - let's simply put all those arrays into an Object and assign a Key Name which will result in having an object like:
obj = {d:[7,4], h:[1,9], m:[2,9], s:[0,7]}
Reference to HTML
Having that Object and knowing that inside an for...in loop we can retrieve the Key name and the array value like eg: obj['d'][0] === 7 obj['d'][5] === 4
means that we'll need a for loop to retrieve the 0 and 1 to get the values in our array positions [pos0, pos1]
all inside a for...in loop that will get the KEY names : d, h, m, s
2pos x 4keyNames = 8 elements iterations/second
means that now we'll be able to target an ID element eg: #s0 and #s1
and all we need now is to retrieve the value and animate that element background by
-width * digit
Well, there's another way that you may use to solve the same problem. Here are the steps. Firstly I wrote one CSS class selector for each image position.
.list-group-item .digit-display{
display:inline-block;
width:50px;
height:85px;
background:url('http://i.imgur.com/uBTxTTD.jpg');
}
.position-0 {
background-position: 0 0;
}
.position-1 {
background-position: -50px 0px !important;
}
Then I wrote a JavaScript function which takes a digit as an input and return the CSS class selector for that digit as below.
displayDigit(digit) {
const baseSelector = "digit-display position-";
return `${baseSelector}${digit}`;
}
Finally this function is called inside the JSX element as below.
<span className = {this.displayDigit(remainingTime["h"].charAt(0))}></span>
That solved the issue.
However, if someone really needs to go with the jquery based approach specified above, we can still condense down that same code as below.
secondsToTime(secs) {
let hours = `${constants.ZERO}${Math.floor(secs / (60 * 60))}`.slice(-2);
let divisorForMinutes = secs % (60 * 60);
let minutes = `${constants.ZERO}${Math.floor(divisorForMinutes / 60)}`.slice(-2);
let divisorForSeconds = divisorForMinutes % 60;
let seconds = `${constants.ZERO}${Math.ceil(divisorForSeconds)}`.slice(-2);
let obj = {
"h": hours,
"m": minutes,
"s": seconds
};
return obj;
}
handleFlipClockImage = () => {
var myObj = this.secondsToTime(seconds);
Object.keys(myObj).forEach(key => {
let obj = myObj[key];
var digits = obj.split(constants.EMPTY_SPACE_CHAR);
digits.forEach((digit, index) => {
jquery(`#${this.state.label}${key}${index}`).css({backgroundPosition: -digit*50 });
});
});
}

Create a unique number with javascript time

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.

Categories