Cumbersome time parsing in JavaScript - javascript

I need a function to convert time in text from a format with day-part letters to digits.
E.g. 4:15PM -> 16:15, 4:15AM -> 4:15AM. Currently I have the following solution
function formatTime(text){
var find = '([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9] (AM|PM)';
var reg = new RegExp(find, 'g');
pos = 0;
var result;
var formatedText = "";
while((result = reg.exec(text)) !== null) {
if(result[2] == "PM"){
var hours= parseInt(result[0], 10);
hours = hours + 12;
var hoursStr = hours.toString();
var newTime = hoursStr + result[0].substring(result[1].length,result[0].length - 3);
formatedText += newTime;
pos = reg.lastIndex;
} else {
formatedText += text.replace("AM","").substring(pos, reg.lastIndex);
pos = reg.lastIndex;
}
}
if(pos < text.length){
formatedText += text.substring(pos, text.length);
}
return formatedText;
}
console.log(formatTime("Some Text (11:00AM - 1:00PM)"));
I makes nicely cases like
console.log(formatTime("Some Text (11:00AM - 1:00PM)"));
But I strugle to make it process
console.log(formatTime("Some Text (11:00 AM - 1:00 PM)"));

This works for your examples.
I've added \\s? to the regex and made a minor change in the logic of cutting time (-2 instead of -3). Also I've moved variables definition to the beginning of the function to reflect hoisting in JavaScript.
function formatTime(text){
var find = '([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]\\s?(AM|PM)';
var reg = new RegExp(find, 'g');
var pos = 0;
var formatedText = "";
var result, hours, hoursStr, newTime;
while ((result = reg.exec(text)) !== null) {
if (result[2] === "PM") {
hours= parseInt(result[0], 10);
hours = hours + 12;
hoursStr = hours.toString();
newTime = hoursStr + result[0].substring(result[1].length, result[0].length - 2);
formatedText += newTime;
} else {
formatedText += text.replace("AM","").substring(pos, reg.lastIndex);
}
pos = reg.lastIndex;
}
if (pos < text.length) {
formatedText += text.substring(pos, text.length);
}
return formatedText;
}

Here's an easier way to do this: Just use two functions. One to convert the hours, and another to match against PM times along with the replace() function.
Easy does it...
function convertTime12to24(time12h) {
const [time, modifier] = time12h.split(' ');
let [hours, minutes] = time.split(':');
if (hours === '12') {
hours = '00';
}
if (modifier === 'PM') {
hours = parseInt(hours, 10) + 12;
}
return hours + ':' + minutes;
}
function formatTime(i_string) {
console.log(i_string.replace(/([0-9]|0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])(PM)/gi, function newDate(x) {
return convertTime12to24(x.replace("PM", " PM"))
}));
}
formatTime("The time is now 4:15PM");
formatTime("The time is now 12:15PM");
formatTime("The time is now 4:00AM");
formatTime("The time is now 12:00AM");
formatTime("The time is now 11:00PM");

Related

Expected identifier in array variable

I still need my function to work in internet explorer for compatibility reasons. The rest of the browsers support my array variable: var [sHour, sMinute, sSecond] but internet explorer does not. below is my full function.
function time_interval(start, end) {
var [sHour, sMinute, sSecond] = start.split(":");
var [eHour, eMinute, eSecond] = end.split(":");
var s = new Date();
s.setHours(sHour, sMinute, sSecond);
var e = new Date();
e.setHours(eHour, eMinute, eSecond);
var a;
if (s.getTime() < e.getTime()) {
a = e.getTime() - s.getTime();
} else {
e.setDate(e.getDate() + 1);
a = e.getTime() - s.getTime();
}
a = a / 1000;
var h = Math.floor(a / 3600);
var m = Math.floor((a % 3600) / 60);
var s = a % 60;
return (
(h ? h + ' hour ' : '') +
(m ? m + ' minute ' : '') +
(s ? s + ' second ' : '')
).trim();
}
const example = time_interval("10:00:00", "10:30:00");
console.log(example);
an example of the values taken by my array var is for instance, 10:30:00. This is why I added .split. How do I separate the arrays so that it is compatible and remove the Expected identifier error? I tried separating it in single variables but this does not work because of the split.
var sHour
var sMinute
var sSecond
Any help would be appreciated.
It's not the ideal solution, but you could just refactor your code like this:
var splitStart = start.split(":");
var sHour = splitStart[0];
var sMinute = splitStart[1];
var sSecond = splitStart[2];
You could also consider using a function and an object:
function convertTimeArrayToObject(arr) {
return {
hour: arr[0],
minute: arr[1],
second: arr[2]
}
}
var startObject = convertTimeArrayToObject(start.split(":"));
console.log(startObject.hour) // Will print the hour

Calculate time difference and sum the difference using Javascript

i am trying to find the difference for end time and start time, followed by adding all the time difference
may i know how can i do so?
the code is as followed
function THcheck() {
var a, s, timeDiff, hr = 0;
var hdate, startTime, endTime, totalTime, timeDiff;
var output = "Date StartTime: EndTime: TimeDiff <br>";
var msg = "";
var DStime, DEtime;
var e = document.getElementsByTagName('input');
for (a = 0; e !== a; a++) {
if (e[a].type == "time" && e[a].name == "THStime[]") {
if (e[a].value && e[a].value !== "") {
startTime = e[a].value;
endTime = e[a + 1].value;
hdate = e[a - 1].value
alert(hdate + " " + startTime + " " + endTime);
timeDiff = endTime - startTime;
alert(timeDiff);
hr = parseInt(timeDiff.asHours());
alert(timeDiff);
totalTime += timeDiff;
alert(totalTime);
output += hdate + " " + startTime + " " + endTime + " " + timeDiff + "<br>";
if (hr >= 24) {
msg = "<br> Exceed 24 hrs! ";
}
}
}
}
alert(output + " Total time: " + totalTime + msg);
return true;
}
thanks in advance for your kind assistance and help on this!
I think you need to parse the hours first, converting from string to date and then convert the dates to milliseconds and use the milliseconds for the difference calculation. After this you convert the difference milliseconds into hours.
Here is some sample code which performs these steps:
const dateRegex = /(\d{2}):(\d{2})/;
function diffDatesInHours(d1Str, d2Str) {
const r1 = dateRegex.exec(d1Str);
const r2 = dateRegex.exec(d2Str);
if (!checkDate(r1)) {
console.log("First date format incorrect: " + d1Str);
return null;
}
if (!checkDate(r2)) {
console.log("Second date format incorrect: " + d2Str);
return null;
}
const d1 = createDateFrom(r1);
const d2 = createDateFrom(r2);
const diff = d1.getTime() - d2.getTime();
return Math.abs(diff) / (1000 * 60 * 60);
}
function checkDate(r) {
if (r === null) {
return null;
}
return r.length > 0;
}
function createDateFrom(r) {
let date = new Date();
date.setHours(r[1], r[2]);
return date;
}
console.log(diffDatesInHours("09:30", "21:00"));
console.log(diffDatesInHours("09:30", "21:"));

output correct format 24 hour after calculation

I'm currently using this function to calculate 2 fields and the results are good but sometimes missing a zero. sample
10:20 + 10:30 current output 0.10
10:20 + 10:30 I want the output to be 00.10
$(function () {
function calculate() {
time1 = $("#start").val().split(':'),
time2 = $("#end").val().split(':');
hours1 = parseInt(time1[0], 10),
hours2 = parseInt(time2[0], 10),
mins1 = parseInt(time1[1], 10),
mins2 = parseInt(time2[1], 10);
hours = hours2 - hours1,
mins = 0;
if(hours < 0) hours = 24 + hours;
if(mins2 >= mins1) {
mins = mins2 - mins1;
} else {
mins = (mins2 + 60) - mins1;
}
// the result
$("#hours").val(hours + ':' + mins);
}
});
also when there is an invalid character I keep getting a nan message is possible to change this to 00 instead?
Instead of dealing with the strings and each value independently, you can use the javascript Date object to calculate the difference...
function calculate() {
// Get time values and convert them to javascript Date objects.
var time1 = new Date('01/01/2017 ' + $('#start').val());
var time2 = new Date('01/01/2017 ' + $('#end').val());
// Get the time difference in minutes. If is negative, add 24 hours.
var hourDiff = (time2 - time1) / 60000;
hourDiff = (hourDiff < 0) ? hourDiff+1440 : hourDiff;
// Calculate hours and minutes.
var hours = Math.floor(hourDiff/60);
var minutes = Math.floor(hourDiff%60);
// Set the result adding '0' to the left if needed
$("#hours").val((hours<10 ? '0'+hours : hours) + ':' + (minutes<10 ? '0'+minutes : minutes));
}
Or even better, you can make the function independent of the DOM elements, so you can reuse it...
function calculate(startTime,endTime) {
// Get time values and convert them to javascript Date objects.
var time1 = new Date('01/01/2017 ' + startTime);
var time2 = new Date('01/01/2017 ' + endTime);
// Get the time difference in minutes. If is negative, add 24 hours.
var hourDiff = (time2 - time1) / 60000;
hourDiff = (hourDiff < 0) ? hourDiff+1440 : hourDiff;
// Calculate hours and minutes.
var hours = Math.floor(hourDiff/60);
var minutes = Math.floor(hourDiff%60);
// Return the response, adding '0' to the left of each field if needed.
return (hours<10 ? '0'+hours : hours) + ':' + (minutes<10 ? '0'+minutes : minutes);
}
// Now you can use the function.
$("#hours").val(calculate($('#start').val(),$('#end').val()));
Add a function
function checkTime(i) {
if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
and call this function before displaying result
I propose you that :
$(".calculator").on("change",function(){
var isNegative = false;
var hours = "00:00";
var inputStart = $("#start").val();
var inputEnd = $("#end").val();
if(inputStart!="" && inputEnd != ""){
// calculate only if the 2 fields have inputs
// convert to seconds (more convenient)
var seconds1 = stringToSeconds(inputStart);
var seconds2 = stringToSeconds(inputEnd);
var secondsDiff = seconds2 - seconds1;
var milliDiffs = secondsDiff * 1000;
if(milliDiffs < 0){
milliDiffs = milliDiffs *-1;
isNegative = true;
}
// Convert the difference to date
var diff = new Date(milliDiffs);
// convert the date to string
hours = diff.toUTCString();
// extract the time information in the string 00:00:00
var regex = new RegExp(/[0-9]{2}:[0-9]{2}:[0-9]{2}/);
var arr = hours.match(regex);
hours = arr[0];
// Take only hours and minutes and leave the seconds
arr = hours.split(":");
hours=arr[0]+":"+arr[1];
// put minus in front if negative
if(isNegative){
hours = "-"+hours;
}
// Show the result
$("#hours").val(hours);
// Put back the inputs times in case there were somehow wrong
// (it's the same process)
var date1 = new Date(seconds1*1000);
var str1 = date1.toUTCString();
arr = str1.match(regex);
hours = arr[0];
arr = hours.split(":");
hours=arr[0]+":"+arr[1];
$("#start").val(hours);
// idem for time 2
var date2 = new Date(seconds2*1000);
var str2 = date2.toUTCString();
arr = str2.match(regex);
hours = arr[0];
arr = hours.split(":");
hours=arr[0]+":"+arr[1];
$("#end").val(hours);
}
});
function timeElementToString(timeElement){
var output = timeElement.toString();
if(timeElement < 10 && timeElement >=0)
output = "0"+output;
else if(timeElement < 0 && timeElement >=-10)
output = "-0"+Math.abs(output);
return output;
}
function stringToSeconds(input){
var hours = 0;
var arr=input.split(":");
if(arr.length==2){
hours=parseInt(arr[0]);
minutes=parseInt(arr[1]);
if(isNaN(hours)){
hours = 0;
}
if(isNaN(minutes)){
minutes = 0;
}
}
return hours*3600+60*minutes;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<label for="start">Start</label><input type="text" id="start" class="calculator"></input><br />
<label for="end">End</label><input type="text" id="end" class="calculator"></input><br />
<label for="hours">Hours</label><input type="text" id="hours" readonly="readonly"></input>
</form>

Javascript counter continuously updating with specific rate run from terminal

JS counter continuously updating
Hey, first of all: I'm a newbie to coding, I'm a student and I've been struggling so much with this bit that I thought it's finally time to ask someone else. So I've been looking at this question and it works perfectly in html. However I want to run it from the terminal (I'm using node to execute the file).
I've tried to modify the code for that. But the calculation doesn't seem to work. It prints: £NaN.00
//counter
var amount = formatMoney(amount);
var startDate = new Date(2012, 07, 21);
var currentDate = new Date();
var seconds = (startDate - currentDate) / 1000;
var modifier = seconds * .158;
var current = 138276343 + modifier;
update();
function update() {
amount.innerText = formatMoney(current);
}
setInterval(function(){
current += .158;
update();
},1000);
function formatMoney(amount) {
var pounds = Math.floor(amount).toString().split('');
var cents = (Math.round((amount%1)*100)/100).toString().split('.')[1];
if(typeof cents == 'undefined'){
cents = '00';
}else if(cents.length == 1){
cents = cents + '0';
}
var str = '';
for(i=pounds.length-1; i>=0; i--){
str += pounds.splice(0,1);
if(i%3 == 0 && i != 0) str += ',';
}
return '£' + str + '.' + cents;
}
console.log(amount);
I'm completely out of ideas, so I would really appreciate any kind of help. Thanks!
Why are you trying to set amount.innertext in your update function and not just amount? Works when you use amount instead of amount.innertext.
//counter
var amount = formatMoney(amount);
var startDate = new Date(2012, 07, 21);
var currentDate = new Date();
var seconds = (startDate - currentDate) / 1000;
var modifier = seconds * .158;
var current = 138276343 + modifier;
update();
function update() {
amount = formatMoney(current);
}
setInterval(function(){
current += .158;
update();
},1000);
function formatMoney(amount) {
var pounds = Math.floor(amount).toString().split('');
var cents = (Math.round((amount%1)*100)/100).toString().split('.')[1];
if(typeof cents == 'undefined'){
cents = '00';
}else if(cents.length == 1){
cents = cents + '0';
}
var str = '';
for (i=pounds.length-1; i>=0; i--) {
str += pounds.splice(0,1);
if(i%3 == 0 && i != 0) {
str += ",";
}
}
return '£' + str + '.' + cents;
}
console.log(amount);

Javascript toggling time type

So recently, for fun and to learn more about Javascript since I haven't ever done much web development, I've been making a site which will function as a clock which picks a color by making a color hex code from the time. Fairly basic, but I'm having a bit of an issue with a feature I want to implement.
A feature I'd like to have is to use a button on the webpage to toggle between UTC and local time. To accomplish this, I have the button (onclick) multiply a number by -1, to have a positive and negative representing each state. I have verified through console.log that the value itself is changed, but there is no visible change in the time being displayed.
So, I'd appreciate it if someone could take a look. Perhaps I'm misunderstanding how the code itself flows, or repeats.
Thanks! I can put up the HTML if need be, but I think only the JS will be necessary.
var h, m, s;
window.onload = function startTime() {
var today = new Date();
var buttonHasBeenPressed = -1; // -1 = false
document.getElementById("utcbtn").onclick = function() {
buttonHasBeenPressed = buttonHasBeenPressed * -1; // reverses value
console.log(buttonHasBeenPressed);
}
if (buttonHasBeenPressed == 1) {
getUTCTime(today);
} else {
getNormalTime(today);
}
h = checkTime(h);
m = checkTime(m);
s = checkTime(s);
var timeString = "" + h + ":" + m + ":" + s;
var colorString = "#" + h + m + s;
document.getElementById("main").innerHTML = timeString;
document.getElementById("hexcolor").innerHTML = colorString;
document.body.style.backgroundColor = colorString;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
function getUTCTime(today) {
h = today.getUTCHours();
m = today.getUTCMinutes();
s = today.getUTCSeconds();
}
function getNormalTime(today) {
h = today.getHours();
m = today.getMinutes();
s = today.getSeconds();
}
Like I said as far as javascript I'm pretty much a novice, so this code probably isn't all that great - suggestions to improve it are always welcome!
The reason your code is not changing from UTC to normal time, is because you are setting a timeout for var t = setTimeout(startTime, 500);. In startTime you are immediately setting it to -1 var buttonHasBeenPressed = -1; // -1 = false. So each time it runs you set it back to -1. If you move the var buttonHasBeenPressed = -1; // -1 = false outside of the startTime function it will work. See updated code.
var h, m, s;
var buttonHasBeenPressed = -1; // -1 = false
window.onload = function startTime() {
var today = new Date();
document.getElementById("utcbtn").onclick = function() {
buttonHasBeenPressed = buttonHasBeenPressed * -1; // reverses value
console.log(buttonHasBeenPressed);
}
if (buttonHasBeenPressed == 1) {
getUTCTime(today);
} else {
getNormalTime(today);
}
h = checkTime(h);
m = checkTime(m);
s = checkTime(s);
var timeString = "" + h + ":" + m + ":" + s;
var colorString = "#" + h + m + s;
document.getElementById("main").innerHTML = timeString;
document.getElementById("hexcolor").innerHTML = colorString;
document.body.style.backgroundColor = colorString;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) {
i = "0" + i
}; // add zero in front of numbers < 10
return i;
}
function getUTCTime(today) {
h = today.getUTCHours();
m = today.getUTCMinutes();
s = today.getUTCSeconds();
}
function getNormalTime(today) {
h = today.getHours();
m = today.getMinutes();
s = today.getSeconds();
}
Edit:
I would also make buttonHasBeenPressed a boolean and setup a init() function where you add the onclick handler and start startTime so you are not adding the onclick handler each time.
var h, m, s;
var buttonHasBeenPressed = false;
window.onload = init;
function init() {
document.getElementById("utcbtn").onclick = function() {
buttonHasBeenPressed = !buttonHasBeenPressed;
console.log(buttonHasBeenPressed);
}
startTime();
}
function startTime() {
var today = new Date();
if (buttonHasBeenPressed) {
getUTCTime(today);
} else {
getNormalTime(today);
}
h = checkTime(h);
m = checkTime(m);
s = checkTime(s);
var timeString = "" + h + ":" + m + ":" + s;
var colorString = "#" + h + m + s;
document.getElementById("main").innerHTML = timeString;
document.getElementById("hexcolor").innerHTML = colorString;
document.body.style.backgroundColor = colorString;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) {
i = "0" + i
}; // add zero in front of numbers < 10
return i;
}
function getUTCTime(today) {
h = today.getUTCHours();
m = today.getUTCMinutes();
s = today.getUTCSeconds();
}
function getNormalTime(today) {
h = today.getHours();
m = today.getMinutes();
s = today.getSeconds();
}
buttonHasBeenPressed and setTimeout should not have been local to the startTime function.
Here's a working JSFiddle.

Categories