Converting human string time between different units of time - javascript

Are you aware of a npm module capable of converting human string time to days, hours, seconds or milliseconds preferably using moment.js time units?
It's a little difficult to explain, so here are a few examples:
'1hours' to minutes = 60
'2days' to seconds = 172800
'60seconds' to minutes = 1
'30minutes' to seconds = 1800
Same as above using short hand:
'1h' to minutes = 60
'2d' to seconds = 172800
'60s' to minutes = 1
'30m' to seconds = 1800
These are the string units used by moment.js
Key Shorthand
----------------------
years y
quarters Q
months M
weeks w
days d
hours h
minutes m
seconds s
milliseconds ms
Or expressed as a function:
const convertUnits = (input, format) => {
// Implementation
};
convertUnits('1hours', 'minutes') // 60
convertUnits('1h', 'm') // 60
Or is it possible to do this just using moment? Remember that I don't care about the actual date or time - I merely want the unit conversions mixed in with the human readable units.
Thanks in advance.

I ended up using below:
import * as _ from 'lodash'
import moment from 'moment'
import momentDurationFormat from 'moment-duration-format'
export const convertTime = (time, format = 's') => {
if(!_.isString(time) || !_.isString(format)){
return 0;
}
const components = time.trim().split(/(\d+)/);
const digits = parseInt(components[1]);
const unit = components[2];
return moment
.duration(digits, unit)
.format(format);
};

Try to use timestring library. It parse a human readable time string into a time based value (by default in seconds). As I see, it can all you need:
const timestring = require('timestring')
let str = '1d 3h 25m 18s'
let time = timestring(str)
console.log(time) // will log 98718
str input param can be set without spaces, for example, '1d3h25m18s'

Related

How can I convert float number into minutes to be added to the current UTC time with Javascript?

I apologise in advance for being a complete dunce but these are in fact my very first shaky steps into trying to get something done with Javascript and I feel somewhat lost and confused.
I have the following float: 53.93
This decimal value represents minutes and seconds and it comes from multiplying the longitude I get from the web-browser´s Geolocation API times four (x4). I have this value stored in a variable which I want to convert into minutes and seconds so that I can then add it to the current UTC time so that I can get a new HH:MM:SS time on screen with the added difference(current UTC Time + 53 minutes and 93 seconds.)
I understand that I should first convert times into milliseconds in order to be able to calculate the time difference but I'm stuck at converting the float into minutes and seconds (or should I convert it directly into milliseconds?)
Thank you kindly.
JavaScript's Date works in milliseconds, so if you have a number representing minutes (whether or not including fractional minutes), you can convert that to milliseconds by multiplying it by 60 (to get seconds) and 1000 (to get milliseconds), e.g., multiply by 60,000. But, you've said you have the value 13.48 and later in the text of your question you've said "...current UTC Time + 13 minutes and 48 seconds..." Those are two different things. .48 of a minute is roughly 28.79 seconds, not 48 seconds. So if you really mean that the figure 13.48 is supposed to mean 13 minutes and 48 seconds, the calculation is more compliated:
const value = 13.48;
const wholeMinutes = Math.trunc(value);
const milliseconds = (wholeMinutes * 60 + (value - wholeMinutes)) * 1000;
You can get the current date/time via Date.now(), which gives you milliseconds since The Epoch UTC (Jan 1st 1970 at midnight).
You can create a Date instance from a given milliseconds-since-The-Epoch value via new Date(value).
So if 13.48 represents fractional minutes (13 minutes and roughly 28.79 seconds):
const minutes = 13.48;
const nowPlusThoseMinutes = new Date(Date.now() + (minutes * 60000));
Live Example:
const minutes = 13.48;
const now = Date.now();
const nowPlusThoseMinutes = new Date(now + (minutes * 60000));
console.log(nowPlusThoseMinutes);
console.log(`now = ${new Date(now)}`);
console.log(`nowPlusThoseMinutes = ${nowPlusThoseMinutes}`);
(The () around minutes * 60000 aren't necessary, the * will happen before the + either way because of operator precedence, but they can help make your intent clear to human readers.)
But you mean it to mean 13 minutes and 48 seconds:
const value = 13.48;
const wholeMinutes = Math.trunc(value);
const milliseconds = (wholeMinutes * 60 + (value - wholeMinutes)) * 1000;
const nowPlusValue = new Date(Date.now() + milliseconds);
Live Example:
const value = 13.48;
const wholeMinutes = Math.trunc(value);
const milliseconds = (wholeMinutes * 60 + (value - wholeMinutes)) * 1000;
const now = Date.now();
const nowPlusValue = new Date(now + milliseconds);
console.log(`now = ${new Date(now)}`);
console.log(`nowPlusValue = ${nowPlusValue}`);

Proper way to manipulate date string with wrong year, but correct time

I'm having to hit an API I have no access to fixing and I need to start a timer showing how long someone has been in a queue for. The date I get back is in this format 1556214336.316. The problem is the year always shows up as 1970, but the time is the correct start time. I need to calculate the difference between the time now, and the time the conversation was created at. I have tried this with little success and was wondering if there is an elegant way to only get the difference in time and not the total amount of seconds.
convertDateToTimerFormat = (time) => {
const now = new Date();
const diff = Math.round((now - parseInt(time.toString().replace('.', ''))) / 1000);
const hours = new Date(diff).getHours();
const minutes = new Date(diff).getMinutes();
const seconds = new Date(diff).getSeconds();
return `${hours}:${minutes}:${seconds}`;
}
The weird parseInt(time.toString().replace('.', ''))) seems to fix the 1970 issue, but I still can't get the data to be manipulated how I need.
I tried the momentjs library, but their diff method only appears to allow for days and hours.
Any help/guidance, would be much appreciated.
Edit with working code:
convertDateToTimerFormat = (time) => {
const now = new Date();
// eslint-disable-next-line radix
const diff = new Date(Number(now - parseInt(time.toString().replace(/\./g, ''))));
const hours = diff.getHours();
const minutes = diff.getMinutes();
const seconds = diff.getSeconds();
return `${hours}:${minutes}:${seconds}`;
}
Unix time values are the number of seconds since the Epoch and won't have a decimal like your 1556214336.316
If I take 1556214336 (without the .316) and put it in a converter I get the output 04/25/2019 # 5:45pm (UTC) which is not 1970 — it seems an accurate time (I haven't independently verified)
It seems, then, your 1556214336.316 is the seconds.milliseconds since the epoch.
Javascript uses the same epoch, but is the number of milliseconds since the epoch, not seconds, so if I'm correct about the time you're getting you should be able to just remove the decimal place and use the resulting number string. Indeed
var d = new Date(1556214336316);
console.log('Date is: ' + d.toUTCString());
produces
Date is: Thu, 25 Apr 2019 17:45:36 GMT
which exactly matches the converter's time of "5:45pm"
var d = new Date(1556214336316);
console.log('Date is: ' + d.toUTCString());
Assuming your value 1556214336.316 is a String coming back from a web API, you can remove the decimal and your conversion can be done like this (note you don't have to keep creating new Date objects):
convertDateToTimerFormat = (time) => {
const d = new Date( Number(time.replace(/\./g, '')) );
return `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`;
};
console.log( 'time: ' + convertDateToTimerFormat('1556214336.316') );
Depending on your use, you may want to use getUTCHours() etc. instead.
I don't know about elegant, but this calculates and displays the expired time in h:mm:ss format:
console.log(convertDateToTimerFormat(1556215236.316));
function convertDateToTimerFormat(time){
// Converts `time` to milliseconds to make a JS Date object, then back to seconds
const expiredSeconds = Math.floor(new Date()/1000) - Math.floor(new Date(time * 1000)/1000);
// Calculates component values
const hours = Math.floor(expiredSeconds / 3600), //3600 seconds in an hour
minutes = Math.floor(expiredSeconds % 3600 / 60),
seconds = expiredSeconds % 3600 % 60;
// Adds initial zeroes if needed
if (minutes < 10) { minutes = "0" + minutes; }
if (seconds < 10) { seconds = "0" + seconds; }
// Returns a formatted string
return `${hours}:${minutes}:${seconds}`;
}

Converting to duration from milliseconds

I am trying to convert time duration from the format of mm:ss.mss to entirely milliseconds and back.
I've already have a working function for converting from milliseconds to duration but I cannot seem to get it the other way around.
Lets say for instance that I have the duration 32:29.060, I want to convert it to milliseconds. For that I use this function:
function millisecondsToTime(ms, digits) {
digits = digits || 12;
return new Date(ms).toISOString().slice(23-digits, -1);
}
var a = millisecondsToTime(5549060, 9);
but whenever I try to convert back to time duration, I fail. I've tried parsing individually the minutes, seconds and milliseconds but it doesn't seem to work.
Here is the code that I've used for it:
var firstSplit = a.split(':')
var minutes = firstSplit[0]; //1
var secondSplit = firstSplit[1].split('.');
var seconds = secondSplit[0]; //2
var millisec = secondSplit[1]; //3
var conversion = ((+minutes) * 60 + (+seconds) * 60 + (+millisec))*1000;
I have an input bar which takes the format of mm:ss.mss and I need to convert it to milliseconds. How can I do that?
you can just return a
new Date(ms)
to get a date from ms.
And to get the same date as ms,
date.getTime() // returns ms from date object
Full example:
const ms = 5549060
const date = new Date(ms) // get a date from ms
console.log(date.getTime) // logs 5569060
If your input is a string in the format of mm:ss.mss, and you want to get a date from it, you can use moment.
const moment = require('moment')
const date = moment('22:15.143', 'mm:ss.SSS') // get date from pre specified format
You can use the string methods indexOf() and substr() to get the individual numbers out of your string and calculate the time accordingly.
I'm afraid though your millisecondsToTime() function isn't working properly.
5549060 milliseconds are roughly 92 minutes and it's returning 32:29.060
function backToTime(time) {
var index = time.indexOf(":");
var minutes = time.substr(0, index);
var seconds = time.substr(index + 1, time.indexOf(".") - (index + 1));
var milliseconds = time.substr(time.indexOf(".") + 1, time.length);
return parseInt(minutes * 60 * 1000) + parseInt(seconds * 1000) + parseInt(milliseconds);
}
console.log(backToTime("32:29.060"));
Your conversion to milliseconds is not working, this is basic math approach to both conversions:
let input = 5549060
//toDuration
let seconds = Math.floor(input / 1000);
let ms = input - seconds*1000;
let m = Math.floor(seconds / 60);
let s = seconds - m*60;
duration = m + ":" + s + "." + ms
console.log(duration)
//toMilliseconds
let holder = duration.split(":");
m = parseInt(holder[0]);
holder = holder[1].split(".");
s = parseInt(holder[0]);
ms = parseInt(holder[1]);
milliseconds = (m*60 + s)*1000 + ms
console.log(milliseconds)
If needed add check for ms length to add 0s, if you need it to have length of 3
I think your milliseconds to duration converter will be broken for durations above 60 minutes. This is because using Date the minutes field will wrap over into the minutes after 59 seconds have passed. If you want to get good support for values beyond 59 in your first field, I think maybe moving to a regex-based parser and using multiplication and addition, division and modulo to extract and reduce the fields manually might be nice. Something like this maybe:
var duration = ms => `${(ms / 60000) | 0}`.padStart(2, '0') + `:` + `${ms % 60000 / 1000 | 0}`.padStart(2, '0') + `.` + `${ms % 1000}`.padStart(3, '0')
var millisec = durat => (match => match && Number(match[1]) * 60000 + Number(match[2]) * 1000 + Number(match[3]))(/^([0-9]+)\:([0-5][0-9])\.([0-9]{3})$/.exec(durat))
You can see given the input 5549060, this function provides output 92:29.60, which is exactly 60 seconds greater than your own, and I believe to be correct. Maybe it's intentional for your usecase, but I can't imagine that being so desirable generally...

Javascript: finding the time difference between two 'time' strings without involving date

I have two <input type="time">. By default, each input collects a time value as a string. For example, "08:30".
How can I convert this string into an object which would then enable computation? Is it possible to avoid involving the use of date in this approach?
In the end, I would like to compute the difference between two time strings and then return the result in minutes. For example, the expected return value of08:00 and 09:00 would be 60 minutes.
Just do it as if you only had pen and paper:
12:45 => 12 × 60 + 45 = 765 minutes
08:30 => 8 × 60 + 30 = 510 minutes
765 - 510 = 255
Integer division: 255 / 60 = 4 hours
Remainer: 255 - 60 × 4 = 15 minutes
Result: 04:15
You can parse from string using regular expressions:
var parts = "08:45".match(/^(\d+):(\d+)$/);
console.log(+parts[1], +parts[2], +parts[1] * 60 + +parts[2]);
... and formatting back to string should not be very difficult either.
Assuming you want to use a 24h clock:
function minutesBetween (a, b) {
return Math.abs(toMinutes(b) - toMinutes(a))
}
function toMinutes (time) {
time = /^(\d{1,2}):(\d{2})$/.exec(time)
return time[1]*60 + +time[2]
}
console.log(minutesBetween('8:30', '9:30')) //=> 60
Generally speaking I whould suggest using Date insted of using custom functions, but just for your case this is the example function:
const timeStart = "8:00:00";
const timeEnd = "8:10:00";
//Handles only time with format in hh:mm or hh:mm:ss
//For more complicated cases use Date
function diff(start, end) {
const startMinutes = getMinutes(start);
const endMinutes = getMinutes(end);
return endMinutes - startMinutes
}
function getMinutes(strTime) {
const time = strTime.split(':');
return (time[0] * 60 + time[1]*1);
}
alert(diff(timeStart, timeEnd));
Note that this function is not responsible for validation of the time difference only the computation. You should validate you input

Javascript, how to find the difference between two datetimes in mysql timestamp style

Let's say I have
a = "2011-11-09 08:00:00"
b = "2011-11-10 08:30:00"
What's the best way of finding how many days, hours, minutes the difference between these two timestamps are in Javascript?
So the output should be "1 day" (ignore the minutes since there is a larger unit (day) in the difference) ?
The only reliable way to convert a string to a date in javascript is to parse it manually. If the format is consistent with what you have posted, then you can convert it to a date as follows:
function stringToDate(s) {
var dateParts = s.split(' ')[0].split('-');
var timeParts = s.split(' ')[1].split(':');
var d = new Date(dateParts[0], --dateParts[1], dateParts[2]);
d.setHours(timeParts[0], timeParts[1], timeParts[2])
return d
}
so you can do:
var a = "2011-11-09 08:00:00"
var b = "2011-11-10 08:30:00"
alert(stringToDate(a) - stringToDate(b));
to get the difference in milliseconds. However, the difference in days between two dates may not be a simple matter of dividing the difference by 8.64e7 (milliseconds in one da). You need to confirm the business logic in regard to that.
EDITED to work in any browser
var matchDate = /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/;
var firstDateParsed = matchDate.exec("2011-11-09 08:00:00");
var secondDateParsed = matchDate.exec("2011-11-10 08:30:00");
var a = new Date(firstDateParsed[1], firstDateParsed[2], firstDateParsed[3], firstDateParsed[4], firstDateParsed[5], firstDateParsed[6], 0);
var b = new Date(secondDateParsed[1], secondDateParsed[2], secondDateParsed[3], secondDateParsed[4], secondDateParsed[5], secondDateParsed[6], 0);
var differenceInMilliseconds = a.getTime() - b.getTime();
// minutes
alert(differenceInMilliseconds / 1000 / 60);
// hours
alert(differenceInMilliseconds / 1000 / 60 / 60);
// days
alert(differenceInMilliseconds / 1000 / 60 / 60 / 24);
Tested in IE and Firefox as well as Chrome: http://jsfiddle.net/xkBTS/4/
You'll have to parse the timestamp to a date yourself:
function parseMySQLTimestamp(timestamp) {
var parts = timestamp.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/);
return new Date(+parts[1], (+parts[2] - 1), +parts[3], +parts[4], +parts[5], +parts[6]);
}
Get the difference in milliseconds by subtracting one date from the other:
var msDifference = parseMySQLTimestamp(b) - parseMySQLTimestamp(a);
Simple arithmetic will let you convert milliseconds to seconds, minutes, or whatever.
By the way, this function will throw an error if a timestamp is passed in that doesn't match the expression. From a software design point of view, this behavior makes sense to me. However, if you want to be able to use that function with strings that may not be in the correct format, you can just do a null check against parts and return null if there is no match.

Categories