Skip to content

Instantly share code, notes, and snippets.

@ArtemAvramenko
Last active March 7, 2023 10:27
Show Gist options
  • Save ArtemAvramenko/a72809d45285e1d75418f96c2318e6cb to your computer and use it in GitHub Desktop.
Save ArtemAvramenko/a72809d45285e1d75418f96c2318e6cb to your computer and use it in GitHub Desktop.
Parses text as time in JavaScript
function parseTime(s, pmByDefault) {
const match = (s || '').toLowerCase().match(/^[^0-9]*([0-9]+)([^0-9]*([0-9]*)(.*))$/);
if (!match) {
return null;
}
let mins = 0;
let hours = 0;
if (match[3]) { // strings like '12:34'
hours = parseInt(match[1].substring(0, 2));
mins = parseInt(match[3].substring(0, 2));
} else { // only one number specified
hours = parseInt(match[1].substring(0, 4));
if (hours > 99) { // convert 1234 to 12:34, 123 to 1:23
mins = hours % 100;
hours = ~~(hours / 100);
}
}
if (hours === 24 && !mins) {
hours = 0; // allow 24:00
} else if (hours > 23) {
hours = 23;
} else if (hours >= 1 && hours <= 12) {
const amPm = (match[3] ? match[4] : match[2])?.match(/[a-z]/)?.[0] || '';
// converts from pm to 24 h format by adding 12. If number is 12 do nothing.
// 12:00 pm in 12h format to => 12:00 in 24 h format.
if (amPm === 'p' && hours != 12) {
hours += 12;
}
// converts from 12:00 am in 12h format to => 00:00 in 24 h format.
else if (amPm === 'a' && hours == 12) {
hours -= 12;
}
// force p.m. in end-time input when start-time is after noon
else if (amPm !== 'a' && pmByDefault && (hours < 12 || !mins)) {
hours += 12;
}
}
if (mins > 59) {
mins = 59;
}
return hours + ':' + (mins < 10 ? '0' : '') + mins
}
const expect = actual => ({
toBe: expected => {
if (actual !== expected) {
console.error(actual + ' should be ' + expected)
}
}
});
expect(parseTime('10am')).toBe('10:00');
expect(parseTime('12pm')).toBe('12:00')
expect(parseTime('12 am')).toBe('0:00')
expect(parseTime('1 p.m.')).toBe('13:00')
expect(parseTime('1:3 p.m.')).toBe('13:03')
expect(parseTime('1:30 p.m.')).toBe('13:30')
expect(parseTime('11:59 am')).toBe('11:59')
expect(parseTime('11:59 pm')).toBe('23:59')
expect(parseTime('xxx 12 30 a.m')).toBe('0:30')
expect(parseTime('1234am')).toBe('0:34')
expect(parseTime('1234')).toBe('12:34')
expect(parseTime('1234:5647')).toBe('12:56')
expect(parseTime('123456')).toBe('12:34')
expect(parseTime('9:2030')).toBe('9:20')
expect(parseTime('10-30 a..m....')).toBe('10:30')
expect(parseTime('10-30 p..m....')).toBe('22:30')
expect(parseTime('10p')).toBe('22:00')
expect(parseTime('10:')).toBe('10:00')
expect(parseTime('')).toBe(null)
expect(parseTime('invalid time')).toBe(null)
expect(parseTime('0')).toBe('0:00')
expect(parseTime('5')).toBe('5:00')
expect(parseTime('05')).toBe('5:00')
expect(parseTime('15')).toBe('15:00')
expect(parseTime('15 am')).toBe('15:00')
expect(parseTime('0 5')).toBe('0:05')
expect(parseTime('time is 5:15')).toBe('5:15')
expect(parseTime('24:00')).toBe('0:00')
expect(parseTime('24:01')).toBe('23:01')
expect(parseTime('23:58')).toBe('23:58')
expect(parseTime('25:99')).toBe('23:59')
expect(parseTime('99:999')).toBe('23:59')
expect(parseTime('999:999')).toBe('23:59')
expect(parseTime('123')).toBe('1:23')
expect(parseTime('1234')).toBe('12:34')
expect(parseTime('1230 p')).toBe('12:30')
expect(parseTime('1 at 30 pm')).toBe('13:30')
expect(parseTime('1 at 30')).toBe('1:30')
expect(parseTime('1 p 30')).toBe('1:30')
expect(parseTime('1230 a')).toBe('0:30')
expect(parseTime('9:20a', true)).toBe('9:20')
expect(parseTime('9:20', true)).toBe('21:20')
expect(parseTime('time is 10:20:30.40 post meridiem')).toBe('22:20')
console.log('Tests finished')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment