Convert Text to Integer in JS - javascript

I am trying to use Tampermonkey to find a UTC time offset and return it as as a time. The website shows an offset which I pull here
waitForKeyElements (".UTCText", getTZ_Offset);
which returns a string
console.log ("Found timezone offset: ", tzOffset);
usually like this 08:00 It can be + or -
Then i want to convert that into actual time. Eg if UTC time is 00:00, I would like to print a string "The users time is 08:00" if the offset was +08:00.
I thought i could use momentjs to get UTC time moment().utcOffset(tzOffset) and pass the offset.
When i do that it just returns NaN
What am I doing wrong?

Multiply the part before the : by 60, and add it to the second part:
const tzOffset = '08:00';
const [hourOffset, minuteOffset] = tzOffset.split(':').map(Number);
const totalMinuteOffset = hourOffset * 60 + minuteOffset;
console.log(totalMinuteOffset);
If the input may be negative, then check that as well:
const tzOffset = '-08:00';
const [_, neg, hourOffset, minuteOffset] = tzOffset.match(/(-)?(\d{2}):(\d{2})/);
const totalMinuteOffset = (neg ? -1 : 1) * (hourOffset * 60 + Number(minuteOffset));
console.log(totalMinuteOffset);
A few time zones differ from UTC not only by hours, but by minutes as well (eg, UTC +5:30, UTC +9:30), so just parseInt, even if it worked, wouldn't be reliable everywhere.

Related

Detect when the current date and time is now in Javascript

Im trying to find if the current time and date is equal to a date coming from an API.
The api data is in the following format: 2021-01-02T08:00:00+01:00
The code i currently have is:
if (new Date() === new Date(apiData) {
alert('its the current time accurate to seconds')
}
The problem is that i don't think that this takes in account different timezones, I only want to run the code if the time is exactly as the one from api, no matter where the client is coming from.
The timestamp 2021-01-02T08:00:00+01:00 represents a unique moment in time. If parsed according to ECMA-262, it will produce a time value that is a millisecond offset from the ECMAScript epoch: 1970-01-01T00:00:00Z.
The generated time value is independent of host system settings, i.e. the host offset has no effect. So:
Date.parse('2021-01-02T08:00:00+01:00');
will produce exactly the same value (1609570800000) in every implementation consistent with ECMA-262.
If passed to the Date constructor, the timestamp will be parsed in exactly the same way, with the time value being used for a Date instance such that:
let ts = '2021-01-02T08:00:00+01:00';
Date.parse(ts) == new Date(ts).getTime();
As mentioned in comments, ECMAScript time values have millisecond precision, so the chance that the above will return true is extremely small. Reducing precision to one second (say by rounding or truncating the decimal seconds) won't help much.
If you want to run some code at the time indicated by the timestamp, you are best to work out the time left and, if it's in the future, set a timeout, something like:
let timeLeft = Date.parse(timestamp) - Date.now();
if (timeLeft >= 0) {
setTimeout(doStuff, timeLeft);
}
E.g.
/* Create timestamp in future with specified offset
* #param {string} timeAhead - time in future in H[:m[:s[.sss]]] format
* #param {string} offset - offset as [-]H[:mm]
* #returns {string} ISO 8601 formatted timestamp with offset
*/
function getFutureTimestamp(timeAhead, offset) {
let pad = n => ('0' + n).slice(-2);
let [h, m, s, ms] = timeAhead.split(/\D/);
let timems = (h||0)*3.6e6 + (m||0)*6e4 + (s||0)*1e3 + (ms||0)*1;
let oSign = /^-/.test(offset)? -1 : +1;
let [oH, om] = offset.match(/\d+/g) || [];
let oms = oSign * (oH*3.6e6 + (om||0)*6e4);
let d = new Date(Date.now() + oms + timems);
return d.toISOString().replace('Z', `${oSign < 0? '-':'+'}${pad(oH)}:${pad(om||0)}`);
}
// timestamp for 5 seconds from now with offset +1
let ts = getFutureTimestamp('0:0:5','1');
// Calculate ms from now to ts
let delay = Date.parse(ts) - Date.now();
console.log('Run at ' + ts);
// Show timestamp after lag
if (delay >= 0) {
setTimeout(()=>console.log('done: ' + new Date().toISOString()), delay);
}
Note that in the above, the first displayed timestamp will be +1, the second +0 so they will be 1 hour different.
Timeouts don't necessarily run after exactly the time specified. However, the above seems to be a few milliseconds. As far as I know, the accuracy of the timeout (based on the system clock) isn't dependent on the length of the delay but on how busy the system is when it's elapsed.
Use This Code
if (new Date().getTime() === new Date(apiData).getTime()) {
alert('its the current time accurate to seconds')
}

How to check if open to close time has elapse using timezone in javascript

I have this below functionin my webapp to check if from OPEN to CLOSE time has elapse using a country timezone and it's working fine. Am trying to optimize my website, so my question is how can i make a function like this in javascript without the use of moment timezone? The moment timezone file is large and this is the only usage of it on my website.
function isOpen(openTime, closeTime, timezone) {
// handle special case
if (openTime === "24HR") {
return "open";
}
// get the current date and time in the given time zone
const now = moment.tz(timezone);
// Get the exact open and close times on that date in the given time zone
const date = now.format("YYYY-MM-DD");
const storeOpenTime = moment.tz(date + ' ' + openTime, "YYYY-MM-DD h:mmA", timezone);
const storeCloseTime = moment.tz(date + ' ' + closeTime, "YYYY-MM-DD h:mmA", timezone);
let check;
if (storeCloseTime.isBefore(storeOpenTime)) {
// Handle ranges that span over midnight
check = now.isAfter(storeOpenTime) || now.isBefore(storeCloseTime);
} else {
// Normal range check using an inclusive start time and exclusive end time
check = now.isBetween(storeOpenTime, storeCloseTime, null, '[)');
}
return check ? "open" : "closed";
}
const zone = "Asia/Kuala_Lumpur";
console.log("24HR", isOpen("24HR", undefined, zone));
console.log("2:00AM-8:00AM", isOpen("2:00AM", "8:00AM", zone));
console.log("8:00AM-10:00AM", isOpen("8:00AM", "10:00PM", zone));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.27/moment-timezone-with-data-10-year-range.min.js"></script>
You can use the Intl.DateTimeFormat constructor to do the same thing. As I understand it, you want to know if a store that is open say from 8:00 to 12:00 in say Asia/Kuala_Lumpur is currently open.
It's probably possible to convert your code more or less line by line, but I've just refactored it and simplified the logic (call me lazy…). This way it gets the current time in the desired location, converts it to minutes since midnight, then sees if that is before the start time or on or after the closing time.
For midnight (12:00 AM), the time converts to 0 minutes so if closingTime is 0, it's assumed to be end of day so is set to 1,440 (i.e. midnight at end of day).
The test times only work on the same day, if the open time runs over midnight you'll need to refactor it. I've just tested midnight to noon and noon to midnight so one should always show "open" and the other "closed".
You might also consider using Luxon, it does what moment.js + moment.tz does but uses the Intl object instead of included data.
Edit
To deal with times that go over midnight, you can either include dates in the time (not convenient if you want to use a regular daily schedule) or you can have an "inside" and "outside" test so that if closing time is before the open time, you test if the time is not between open and close times. That can be done by comparing openMin and close times and adjusting the test.
This will not deal with overlapping start and end times, but that doesn't really fit a regular daily schedule (though it might fit a weekly or longer schedule).
/* #param {string} location: IANA representative location
** #param {Date} date: date instance to get time from, default is now
** #returns {string} time in location in h:mm ap format
*/
function getTime(location, date = new Date()) {
return date.toLocaleString('en', {
timeZone: location,
hour : 'numeric',
minute: '2-digit',
dayPeriod: 'short'
});
}
/* #param {string} time: h:mm A
** #returns {number} time converted to minutes
*/
function timeToMin(time) {
let [h, m] = time.match(/\d\d?/g);
h = h%12;
if (/pm$/i.test(time)) h +=12
return h * 60 + parseInt(m);
}
/* #param {string} openTime: opening time in h:mm ap format
** #param {string} closeTime: closing time in h:mm ap format
** #param {string} location: IANA representative location
** #return {string} open if current time is within openTime and closeTime in location,
** closed otherwise
*/
function isOpen(openTime, closeTime, location) {
if (openTime == '24HR') return 'open';
let nowTime = getTime(location);
let nowMin = timeToMin(nowTime);
let openMin = timeToMin(openTime);
let closeMin = timeToMin(closeTime) || 1440;
// Open and close on same day
if (openMin < closeMin) {
return nowMin < openMin || nowMin >= closeMin ? 'closed' : 'open';
// Close on day after open
} else {
return nowMin >= openMin && nowMin < closeMin ? 'open' : 'closed';
}
}
// Time in KL
let loc = "Asia/Kuala_Lumpur";
console.log(`In ${loc} it's ${getTime(loc)}`);
// Examples
[["24HR", undefined, loc], // Open 24 hrs
["12:00AM", "12:00PM", loc], // Midnight to noon
["12:00PM", "12:00AM", loc], // Noon to midnight
["6:30PM", "04:00AM", loc], // Over midnight
].forEach(args => console.log(
`${args[0]}${args[1]? '-' + args[1] : ''} ${isOpen(...args)}`
));

calculate difference in dates, get difference in hours mins and seconds - ideally by js, otherwise moment.js

I've managed in calculating date differences by:
converting unix date received into js date,
Saving current date as js date,
passing both to moment.js together with their format to get diff
converting to milliseconds
difference in ms is converted to a moment and returns hours mins secs
I've run into an issue where specific versions of moment works this out, and others throws exception as nan internally when calc differences. Would love to do it using just plain js, hopefully circumventing this scenario.
Uploaded a fiddle, it doesnt run unless you comment out the moment part since didnt find a moment.js version on cdn.
I'm more after the logic and a bit of pseudocode/syntax rather than a working example. The JS version's issue is that when the calculated difference between both unix dates is then converted into a date *1000 for milliseconds, it becomes a 1970 date. also the getMinutes() in js get the literal minute at that timestamp, not to overall amount of minutes ,same for hours etc..
This is the moment JS example:
var now = new Date(Date.now()),
ms = moment(then, "DD/MM/YYYY HH:mm:ss").diff(moment(now, "DD/MM/YYYY HH:mm:ss")),
d = moment.duration(ms),
formattedMomentDateDifference = Math.floor(d.asHours()) + ":";
formattedMomentDateDifference += Math.floor(d.minutes()) + ":";
formattedMomentDateDifference += Math.floor(d.seconds());
$('#momentdifference').val(formattedMomentDateDifference);
and below is the js dates example:
var then = cleanedReceivedDate, //cleaned received date in unix
difference = Math.floor(then - now)*1000, /* difference in milliseconds */
msDifferenceInDate = new Date(difference),
hoursDiff = msDifferenceInDate.getHours(),
minutesDiff = "0"+msDifferenceInDate.getHours(),
secondsDiff = "0"+msDifferenceInDate.getSeconds(),
formattedTime = hoursDiff + ':' + minutesDiff.substr(-2) + ':' + secondsDiff.substr(-2);
$('#jsdifference').val(formattedMomentDateDifference);
JS fiddle
Matt has linked to a duplicate for moment.js, so this is just a POJS solution.
UNIX time values are seconds since the epoch, ECMAScript time values are milliseconds since the same epoch. All you need to do is convert both to the same unit (either seconds or milliseconds) and turn the difference into hours, minutues and seconds.
The UNIX time value for say 2016-10-02T00:00:00Z is 1475366400, so to get the hours, minutes and seconds from then to now in your host system's time zone, do some simple mathematics on the difference from then to now:
var then = 1475366400, // Unix time value for 2016-10-02T00:00:00Z
now = Date.now(), // Current time value in milliseconds
diff = now - then*1000, // Difference in milliseconds
sign = diff < 0? '-' : '';
diff *= sign == '-'? -1 : 1;
var hrs = diff/3.6e6 | 0,
mins = diff%3.6e6 / 6e4 | 0,
secs = diff%6e4 / 1e3 ;
// Helper to pad single digit numbers
function z(n){return (n<10?'0':'') + n}
console.log(sign + hrs + ':' + z(mins) + ':' + z(secs));
PS
Using Date.now in new Date(Date.now()) is entirely redundant, the result is identical to new Date().

Javascript time difference

I am trying to simply calculate the time difference of 5:30:00 - 2:30:00. Obviously this should result in 3:00:00
However when I execute following code in console
var a = new Date(0,0,0,5,30,0)
var b = new Date(0,0,0,2,30,0)
var c = new Date(a-b)
console.log(c.getHours() + ":" + c.getMinutes() + ":" + c.getSeconds())
The result is 4:00:00.
What is causing this problem? And how should I handle it?
Date constructor is not suitable to either represent or deal the time spans.
There are no built-in tools to handle time spans in JS, so you need to implement one yourself.
Thankfully the time string -> seconds conversion is trivial:
const timeToSec = time => time.split(':').reduce((acc, v) => acc * 60 + parseInt(v), 0);
Then you can deal with seconds:
const diffInSeconds = timeToSec('5:30:00') - timeToSec('2:30:00'); // 10800
The reverse transformation of seconds -> time string is also trivial (and tbh it's simple reversed of the timeToSec implementation) and I'm leaving it as a home work.
The reason why people get different results is timezone.
When you calculate c as the difference between two dates, you actually get a date relative to 01.01.1970. In this case, when you do:
console.log(c);
You get something like:
1970-01-01T03:00:00.000Z
This is in UTC Date format.
But now if you would display c in the local time zone:
console.log(c.toLocaleDateString()+ ' ' + c.toLocaleTimeString());
... then you get maybe this:
1-1-1970 04:00:00
If you then take the hours of that date with getHours(), you get them from the date/time as it is in your time zone, in your case you are on GMT+1, which means the outcome is 4.
To avoid this time zone conversion, use the UTC versions of the getXXXX functions, like getUTCHours. Note that some time zones have non-integer hour differences with UTC (with an half-hour part), so they would need to use getUTCMinutes as well.
Be aware that converting date differences to Date format will start to give wrong results when you cover larger spans, crossing 29 February, ...etc. Differences are best calculated by taking the date differences (in milliseconds) without conversion to Date. From there it is straightforward to calculate the number of seconds, minutes, ...etc.
I would like to assume that your question is not merely about the difference between two numbers, but it is a real problem.
Then, the answer is: without specifying the day(s), the difference between two hours is meaningless, you must always specify which day(s) you are talking about.
For example Europe, Berlin:
Sunday, 27 March 2016, 02:00:00 clocks were turned
forward 1 hour.
Like in your example, this would lead to pay someone 1 hour more than it had worked...
Sunday, 30 October 2016, 03:00:00 clocks are turned backward 1 hour
..calculating the same interval Sunday, 30 October 2016 would do the opposite.
Moreover, be aware that daylight saving time has become standard in the U.S., Canada, and most European countries. However, most of the world doesn't even use it.
Moreover, during the past, starting day and ending day of saving time has been changed from year to year, and the starting hour has been also changed, i.e. you cannot assume always 2.00 at night - so reconstruct an interval without knowing this information would not lead to a correct result.
A possible solution to calculate correctly a duration, is always to store next the Local Date/Time also the UTC Date/Time and do the calculation keeping both in account, so you have both the Timezone and the Daylight Saving Time Shift to get back the exact start date/time and ending date/time.
If you don't have this information already stored, then you should retrieve them, for example, from a online Time Database.
usage
node time_diff.js 5:30:00 2:30:00
will output: 03:00:00
code of time_diff.js:
#!/usr/bin/env node
if (!process.argv[2] || !process.argv[3]) {
console.log('usage: time_diff hh:mm:ss hh:mm:ss');
process.exit(1);
}
const timeToSec = (time) => time.split(':').reduce((acc, v) => acc * 60 + parseInt(v), 0);
const diffInSeconds = (time1, time2) => timeToSec(time2) - timeToSec(time1);
const hhmmss = (secs) => {
var minutes = Math.floor(secs / 60);
secs = secs % 60;
var hours = Math.floor(minutes / 60);
minutes = minutes % 60;
return pad(hours) + ":" + pad(minutes) + ":" + pad(secs);
function pad(num) {
return ("0" + num).slice(-2);
}
};
try {
console.log(hhmmss(diffInSeconds(process.argv[3], process.argv[2])));
}
catch (err) {
console.log('usage: time_diff hh:mm:ss hh:mm:ss');
process.exit(1);
}
Try this simple plugin to get time differences.
https://github.com/gayanSandamal/good-time
import the goodTimeDiff method from good-time.js to your project
import {goodTimeDiff} from './scripts/good-time.js'
declare an object to give settings like below. let settings = {}
now assign time values to the declared object variable. *time must be in standard format and must be a string! *'from' is optional the default value will be the browser current time.
let settings = {
'from': '2019-01-13T00:00:29.251Z',
'to': '2018-09-22T17:15:29.251Z'
}
now calllback the method called goodTimeDiff() and pass the settings object variable as a parameter.
goodTimeDiff(settings)
Finally assign the method to any variable you want.
let lastCommentedTime = goodTimeDiff(timeSettings)
a - b results in three hours, but in milliseconds. You just need to convert milliseconds to hours (which is not new Date(milliseconds)).
try: (a-b)/1000/60/60
Formatted:
var a = new Date(0,0,0,5,30,0)
var b = new Date(0,0,0,2,30,0)
var diff = (a.getTime()-b.getTime())
var h = Math.floor(diff/1000/60/60)
var m = ('0' + Math.floor((diff/1000/60)%60) ).substr(-2)
var s = ('0' + Math.floor((diff/1000)%60) ).substr(-2)
console.log(h + ':' + m + ':' + s)
EDIT
For those who want to treat a time span as a date... just get the UTC date, which means Coordinated Universal Time. In other words, don't use timezone aware methods:
var a = new Date(0,0,0,5,30,0)
var b = new Date(0,0,0,2,30,0)
var c = new Date(a-b)
console.log(c.getUTCHours() + ":" + c.getUTCMinutes() + ":" + c.getUTCSeconds())
Be aware though, this will fall apart on edge cases...

Javascript: how to add n minutes to unix timestamp

I have a unix timestamp: 1368435600. And a duration in minutes: 75 for example.
Using javascript I need to:
Convert the timestamp to a string format hours:mins (09:00)
Add n minutes to the timestamp: timestamp + 75mins
I tried the moment.js library:
end_time = moment(start_time).add('m', booking_service_duration);
booking_service_duration was 75 but it added an hour. I'd also rather not have to use another js library
To add 75 minutes, just multiply by 60 to get the number of seconds, and add that to the timestamp:
timestamp += 75 * 60
To convert to hours:mins you will have to do a bit more math:
var hours = Math.floor(timestamp/60/60),
mins = Math.floor((timestamp - hours * 60 * 60) / 60),
output = hours%24+":"+mins;
Unix time is the number of seconds that have elapsed since 1 January 1970 UTC.
To move that time forward you simply add the number of seconds.
So once you have the minutes, the new timestamp is oldTime + 60*minutes
For the conversion look up parsing libraries, there is code out there for this, do some research.
So you want to convert a timestamp you have, timestamp, to locale time string after adding some time interval, specifically minutes, to it.
Whether you have a kind of date-time string or a kind of epoch mili/seconds, just create a Date object:
const date = new Date(timestamp);
Keep in mind since what you need to do require to add/substract some numbers (your case: minutes) to another number, not some date object or some date-time string, and that number is the epoch mili/secods of your date. So, always you will need the number representation of your date in mili/seconds. JavaScript Date.prototype.getTime() does return epoch miliseconds of your date. Use it:
const miliseconds = date.getTime();
Add as many as miliseconds to it:
const newMiliseconds = miliseconds + (75 * 60 * 1000);
After that, as you said you need a date-time string, well a portion of it; locale time string, you will need to go all the way back; from numbers to date object and to a date-time string:
const newDate = new Date(newMiliseconds);
const newTimestamp = newDate.toString();
Or instead of getting the whole string of it, use the following specialized method to get the format/portion of the string representation of the date object that you like directly:
const newTimestamp = newDate.toLocaleTimeString(); // "12:41:43"
Finally, all you have to do is to just strip the last semicolon and seconds to get hours:minutes format:
const newHoursMins = newTimestamp.slice(0, -3);
Better make a function of it:
function timestampPlus(timestamp, milisecondsDifference, toStringFunc = Date.prototype.toString) {
const date = new Date(timestamp);
const miliseconds = date.getTime();
const newMiliseconds = miliseconds + milisecondsDifference;
const newDate = new Date(newMiliseconds);
const newTimestamp = toStringFunc.call(newDate); // a bit advanced stuff here to let you define once and use whatever kind to string method you want to use, defaults to toString()
return newTimestamp;
}
I left the final formatting out here. You can use this for substraction as well by pasing a negative second argument. Note the seconds argument is in miliseconds and unix timestamp varies and might given to you as seconds instead, in which case you will need to convert it to miliseconds or change the above funciton definition.
function timestampPlus(timestamp, milisecondsDifference, toStringFunc = Date.prototype.toString) {
const date = new Date(timestamp);
const miliseconds = date.getTime();
const newMiliseconds = miliseconds + milisecondsDifference;
const newDate = new Date(newMiliseconds);
const newTimestamp = toStringFunc.call(newDate); // a bit advanced stuff here to let you define once and use whatever kind to string method you want to use, defaults to toString()
return newTimestamp;
}
console.log("new Date(1368435600*1000).toLocaleTimeString(): ", new Date(1368435600*1000).toLocaleTimeString())
console.log("timestampPlus(1368435600*1000, 75*60*1000, Date.prototype.toLocaleString): ", timestampPlus(1368435600*1000, 75*60*1000, Date.prototype.toLocaleTimeString))
Apart from what you need, for last parameter, toStringFunc, your options vary and encompasses all related Date methods, the are on Date.prototype:
toString
toDateString
toTimeString
toLocaleString
toLocaleDateString
toLocaleTimeString
toIsoString
toUTCString
toGMTString
toJSON

Categories