Parsing string into Time format JavaScript - javascript

I have the following time format 2h 34m 22s and I'm parsing it as 02:34:22 using this code:
const splitterArray = '2h 34m 22s'.split(' ');
let h = '00', m = '00', s = '00';
splitterArray.forEach(val => {
if (val.includes('h')) {
h = val.replace('h', '');
} else if (val.includes('m')) {
m = val.replace('m', '');
}
else if (val.includes('s')) {
s = val.replace('s', '');
}
});
console.log(`${h}:${m}:${s}`);
This also handles the case when there's only minutes and seconds, or only hours and seconds or only hours and minutes.
Just checking if there's a better way to do it like a library or so (maybe to accept days too).

You could match in wanted order and get the result with colons.
function convert(string) {
return Array
.from('hms', p => (string.match(new RegExp(`\\d+(?=${p})`))?.[0] || '') .padStart(2, '0'))
.join(':');
}
console.log(convert('2h 34m 22s'));

I suggest using the moment library. it has plenty of examples and documentation for all of your time formatting and parsing needs:
https://momentjs.com/

Related

Sorting dates which are not in right format

I am getting input from the excel sheet and the dates are not in proper ISO format which can be operated on i.e the column looks something like below, I am trying to sort it using converting it to proper date using javascript date and moment however I am not getting proper output I can use a second opinion on this matter.
Input ["28/02/23","31/12/21","31/05/21","30/09/23","31/10/22","30/09/21","30/06/23","31/05/22","30/04/21","31/07/21","30/06/21","28/02/22","31/12/22","30/06/22","31/08/21","30/04/22","31/10/20","31/08/22","31/07/22","31/05/23","31/01/23","30/04/23","30/09/22","28/02/21","30/11/20","30/11/21","31/01/21","31/03/23","31/01/22","31/07/23","31/12/20","31/03/21","31/08/23","30/11/22","31/10/21","31/03/22","30/09/20"]
method I wrote
dateCompare = (d1, d2) => {
let d1Component = d1.toString().split('/')
, d2Component = d2.toString().split('/')
, rD1 = new Date(parseInt(20 + d1Component[2]), d1Component[1] - 1, d1Component[0])
, rD2 = new Date(parseInt(20 + d2Component[2]), d2Component[1] - 1, d2Component[0])
return moment(rD1).isAfter(moment(rD2))
}
The output I am getting from above method is ["30/09/35", "28/02/23", "31/05/21", "31/12/21", "31/10/22", "30/09/21", "30/09/20", "31/05/22", "30/04/21", "31/07/21", "30/06/21", "28/02/22", "31/12/22", "30/06/22", "31/08/21", "30/04/22", "31/10/20", "31/08/22", "31/07/22", "31/03/22", "31/01/23", "31/10/21", "30/09/22", "28/02/21", "30/11/20", "30/11/21", "31/01/21", "30/11/22", "31/01/22", "31/03/21", "31/12/20", "31/01/37", "31/07/23", "31/03/23", "30/04/23", "31/05/23", "30/06/23", "30/04/37", "31/10/23", "31/08/23", "30/09/23", "30/06/37", "29/02/24", "30/11/23", "31/12/23", "31/01/24", "31/08/37", "31/07/24", "31/03/24", "30/04/24", "31/05/24", "30/06/24", "30/11/37", "31/01/25", "31/08/24", "30/09/24", "31/10/24", "30/11/24", "31/12/24", "31/03/38", "31/08/25", "28/02/25", "31/03/25", "30/04/25"] which I believe is not at all sorted in any ways.
A comparison function should return a negative number for less than, a positive number for greater than, and 0 for equal to, not true/false. Also, since you're already using moment, use it to parse the dates as well:
function dateCompare(d1, d2) {
const d1Parsed = moment(d1, "DD/MM/YY");
const d2Parsed = moment(d2, "DD/MM/YY");
if (d1Parsed.isBefore(d2Parsed)) {
return -1;
} else if (d1Parsed.isSame(d2Parsed)) {
return 0;
} else {
return 1;
}
}
Alternatively, take the difference of their timestamps (if d1Parsed is before d2Parsed then its timestamp will be less, so the resulting subtraction will be negative, if they're equal it'll be 0, and if it's greater it'll be positive, doing the same thing as the previous code):
function dateCompare(d1, d2) {
const d1Parsed = moment(d1, "DD/MM/YY");
const d2Parsed = moment(d2, "DD/MM/YY");
return d1Parsed.valueOf() - d2Parsed.valueOf();
}
You can use map and convert the dates, than sort them.
const dates = ["28/02/23", "31/12/21", "31/05/21", "30/09/23", "31/10/22", "30/09/21", "30/06/23", "31/05/22", "30/04/21", "31/07/21", "30/06/21", "28/02/22", "31/12/22", "30/06/22", "31/08/21", "30/04/22", "31/10/20", "31/08/22", "31/07/22", "31/05/23", "31/01/23", "30/04/23", "30/09/22", "28/02/21", "30/11/20", "30/11/21", "31/01/21", "31/03/23", "31/01/22", "31/07/23", "31/12/20", "31/03/21", "31/08/23", "30/11/22", "31/10/21", "31/03/22", "30/09/20"];
const convertedDates = dates.map(d => {
var day = d.split("/")[0];
var month = d.split("/")[1];
var year = d.split("/")[2];
return "20" + year + '-' + ("0" + month).slice(-2) + '-' + ("0" + day).slice(-2);
})
.sort();
;
console.log(convertedDates);
Without using a third party library, you could convert the custorm date to an ISO 8601 compliant date string and sort with
String#localeCompare.
const
getISO = string => string.replace(/(\d\d)\/(\d\d)\/(\d\d)/, '20$3-$2-$1'),
data = ["28/02/23", "31/12/21", "31/05/21", "30/09/23", "31/10/22", "30/09/21", "30/06/23", "31/05/22", "30/04/21", "31/07/21", "30/06/21", "28/02/22", "31/12/22", "30/06/22", "31/08/21", "30/04/22", "31/10/20", "31/08/22", "31/07/22", "31/05/23", "31/01/23", "30/04/23", "30/09/22", "28/02/21", "30/11/20", "30/11/21", "31/01/21", "31/03/23", "31/01/22", "31/07/23", "31/12/20", "31/03/21", "31/08/23", "30/11/22", "31/10/21", "31/03/22", "30/09/20"];
data.sort((a, b) => getISO(a).localeCompare(getISO(b)));
console.log(data);

Change Time format

I have a time string and I want to convert it to have : between the hour and minutes. Any suggestions on how to take the sting and change it. I’m assuming I need to use regular expression but not sure how to format that code. Any suggestions would be great.
var number = '1340';
moment(number).format('hh:mm')
console.log(number)
// The output I want would be 13:40
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
Stick a : before the last 2 digits. This makes the assumption that your minutes are padded with zeroes if not 2 digits long:
console.log('1340'.replace(/\d{2}$/, m => ':' + m));
First off, in the code you show you are outputing the original string not the result from moment.js.
If you want to use moment, you'll need to tell it what format your string is:
var number = '1340';
var time = moment(number, 'hhmm').format('hh:mm')
console.log(time)
var number = '1340';
console.log(number.slice(0, 2)+":"+number.slice(2));
const number = "1340";
const time = `${number.substring(0,2)}:${number.substring(2,4)}`;
console.log(time);
Moment needs a date.
You want something like this
const pad = num => ("00"+num).slice(-2);
const hhmm = str => {
const mm = str.slice(-2)
const hh = str.slice(0,-2)
return `${pad(hh)}:${pad(mm)}`;
};
console.log(hhmm('1340'))
console.log(hhmm('340'))
console.log(hhmm('40'))
console.log(hhmm('0'))
console.log(hhmm(''))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>

How can I convert a time into the correct format? [duplicate]

I am receiving a string in this format 'HH:mm:ss'. I would like to remove the leading zeros but always keeping the the last four character eg m:ss even if m would be a zero. I am formatting audio duration.
Examples:
00:03:15 => 3:15
10:10:10 => 10:10:10
00:00:00 => 0:00
04:00:00 => 4:00:00
00:42:32 => 42:32
00:00:18 => 0:18
00:00:08 => 0:08
You can use this replacement:
var result = yourstr.replace(/^(?:00:)?0?/, '');
demo
or better:
var result = yourstr.replace(/^0(?:0:0?)?/, '');
demo
To deal with Matt example (see comments), you can change the pattern to:
^[0:]+(?=\d[\d:]{3})
If you use 1 h instead of two you will not get the leading 0.
h:mm:ss
Another option is to use moment.js libary.
This supports formats such as
var now = moment('1-1-1981 2:44:22').format('h:mm:ss');
alert(now);
http://jsfiddle.net/8yqxh5mo/
You could do something like this:
var tc =['00:03:15', '10:10:10','00:00:00','04:00:00','00:42:32','00:00:18','00:00:08'];
tc.forEach(function(t) {
var y = t.split(":");
y[0] = y[0].replace(/^[0]+/g, '');
if(y[0] === '') {
y[1] = y[1].replace(/^0/g, '');
}
var r = y.filter(function(p) {return p!=='';}).join(':');
console.log(r);
});
Divide the time in 3 parts. Remove the leading zeroes from first part, if the the first part is empty remove the leading zeroes from the second part otherwise keep it. Then join all of them discarding the empty strings.
I had a problem with ZUL time when simply format with one small 'h' moment(date).format('h:mm A') cuts first digit from time:
and my const arrivalTime = "2022-07-21T12:10:51Z"
const result = moment(arrivalTime).format(('h:mm A')) // 2:10 PM
Solution for that was converting that to ISO format and then format:
const arrivalTimeIsoFormat = arrivalTime.toISOString()
const result = moment(arrivalTimeIsoFormat, "YYYY-MM-DDTHH:mm:ss.SSS").format(('h:mm A')) // 12:10 PM

Efficiently convert string based time into milliseconds

I was given a challenge, to create a function that'd convert a string based time into milliseconds.
That's the string format I was given:
"hours:minutes:seconds.milliseconds"
So this value for example will need to return 3010220.
"0:50:10.220"
The function needs to be short and one lined.
I'd love to know where I could improve the function below as it didn't pass the criteria. how can this be turned into a one liner?
function toMilliseconds(time){
return time.match(/[0-9]+/g).map(function(val,s,a){
return s != 3 ? +val * ((Math.pow(60,a.length - s -2) * 1000)) : +val;
}).reduce(function(a,b){
return a+b;
},0);
}
There are many different ways.
This is the shortest way I can think of (using ES6):
var str = "0:50:10.220";
var ms = (s=>1E3*s[2]+6E4*s[1]+36E5*s[0])(str.split(':'));
console.log(ms);
And another one:
let ms = str.split(':').reduce((a,v,i) => a + v * [3600000, 60000, 1000, 1][i], 0)
EDIT, thanks to #Swonkie:
let ms = str.split(':').reduce((a,v,i) => a + v * [3600000, 60000, 1000][i], 0)
Which leads to (thanks #Arnauld):
let ms = str.split(':').reduce((a,v,i)=>a+v*1E3*[3600,60,1][i],0);
Or, with rounding (not at all tested for validity):
let ms = str.split(':').reduce((a,v,i)=>a+v*1E3*[3600,60,1][i],0.5)|0;
As described here:
https://codereview.stackexchange.com/questions/45335/milliseconds-to-time-string-time-string-to-milliseconds
this looks like good solution:
function timeString2ms(a,b){// time(HH:MM:SS.mss) // optimized
return a=a.split('.'), // optimized
b=a[1]*1||0, // optimized
a=a[0].split(':'),
b+(a[2]?a[0]*3600+a[1]*60+a[2]*1:a[1]?a[0]*60+a[1]*1:a[0]*1)*1e3 // optimized
}
"oneline solution"
function timeString2ms2(a,b){ return a=a.split('.'),b=a[1]*1||0,a=a[0].split(':'),b+(a[2]?a[0]*3600+a[1]*60+a[2]*1:a[1]?a[0]*60+a[1]*1:a[0]*1)*1e3 }
Usage
console.log(timeString2ms('10:21:32.093')); // hh:mm:ss.mss
console.log(timeString2ms('21:32.093')); // mm:ss.mss
console.log(timeString2ms('21:32')); // mm:ss
console.log(timeString2ms('32.093')); // ss.mss
console.log(timeString2ms('32')); // ss
console.log(timeString2ms('32467.784')); // seconds.ms
console.log(timeString2ms(32467.784+'')); // seconds.ms

How to create regex for time with AM/PM in Javascript

How to create a regex for getting only time time in javascript ?
[12/21/2015 1:00:42.016 AM]
I am trying to get
1:00 AM (ie HH:MM AM/PM)
This is what i tried
input.match(/\d+/g) // => [12,21,2015,1,00,42,016]
AM/PM is missing from the result /
It can be done quite simply without the use of a RegExp or library.
var s = '[12/21/2015 1:00:42.016 AM]';
var p = s.split(' ').slice(1);
p[0] = p[0].slice(0, p[0].lastIndexOf(':'));
p = p.join(' ').slice(0, -1);
document.body.textContent = p;
(\d{1,2}:\d{2}):\d{2}\.\d+ ([AP]M)
Now group one will contain the time and group two - AM/PM
See it in action
timeRegex = /(\d{1,2}:\d{2}):\d{2}\.\d+ ([AP]M)/;
found = "[12/21/2015 1:00:42.016 AM]".match(timeRegex);
console.log(found[1]); // => "1:00"
console.log(found[2]); // => "AM"

Categories

Resources