我对其他答案不满意,所以我又做了一个。这个版本:
- 识别秒和毫秒
- 返回
undefined
无效输入,例如“13:00pm”或“11:65”
- 如果您提供
localDate
参数,则返回本地时间,否则返回 Unix 纪元(1970 年 1 月 1 日)的 UTC 时间。
- 支持军事时间
1330
(要禁用,请在正则表达式中设置第一个':')
- 单独允许一个小时,24 小时制(即“7”表示早上 7 点)。
- 允许 24 小时作为 0 小时的同义词,但不允许 25 小时。
- 要求时间在字符串的开头(禁用,
^\s*
在正则表达式中删除)
- 具有实际检测输出何时不正确的测试代码。
编辑:它现在是一个包含格式化程序的包:timeToString
npm i simplertime
/**
* Parses a string into a Date. Supports several formats: "12", "1234",
* "12:34", "12:34pm", "12:34 PM", "12:34:56 pm", and "12:34:56.789".
* The time must be at the beginning of the string but can have leading spaces.
* Anything is allowed after the time as long as the time itself appears to
* be valid, e.g. "12:34*Z" is OK but "12345" is not.
* @param {string} t Time string, e.g. "1435" or "2:35 PM" or "14:35:00.0"
* @param {Date|undefined} localDate If this parameter is provided, setHours
* is called on it. Otherwise, setUTCHours is called on 1970/1/1.
* @returns {Date|undefined} The parsed date, if parsing succeeded.
*/
function parseTime(t, localDate) {
// ?: means non-capturing group and ?! is zero-width negative lookahead
var time = t.match(/^\s*(\d\d?)(?::?(\d\d))?(?::(\d\d))?(?!\d)(\.\d+)?\s*(pm?|am?)?/i);
if (time) {
var hour = parseInt(time[1]), pm = (time[5] || ' ')[0].toUpperCase();
var min = time[2] ? parseInt(time[2]) : 0;
var sec = time[3] ? parseInt(time[3]) : 0;
var ms = (time[4] ? parseFloat(time[4]) * 1000 : 0);
if (pm !== ' ' && (hour == 0 || hour > 12) || hour > 24 || min >= 60 || sec >= 60)
return undefined;
if (pm === 'A' && hour === 12) hour = 0;
if (pm === 'P' && hour !== 12) hour += 12;
if (hour === 24) hour = 0;
var date = new Date(localDate!==undefined ? localDate.valueOf() : 0);
var set = (localDate!==undefined ? date.setHours : date.setUTCHours);
set.call(date, hour, min, sec, ms);
return date;
}
return undefined;
}
var testSuite = {
'1300': ['1:00 pm','1:00 P.M.','1:00 p','1:00pm','1:00p.m.','1:00p','1 pm',
'1 p.m.','1 p','1pm','1p.m.', '1p', '13:00','13', '1:00:00PM', '1300', '13'],
'1100': ['11:00am', '11:00 AM', '11:00', '11:00:00', '1100'],
'1359': ['1:59 PM', '13:59', '13:59:00', '1359', '1359:00', '0159pm'],
'100': ['1:00am', '1:00 am', '0100', '1', '1a', '1 am'],
'0': ['00:00', '24:00', '12:00am', '12am', '12:00:00 AM', '0000', '1200 AM'],
'30': ['0:30', '00:30', '24:30', '00:30:00', '12:30:00 am', '0030', '1230am'],
'1435': ["2:35 PM", "14:35:00.0", "1435"],
'715.5': ["7:15:30", "7:15:30am"],
'109': ['109'], // Three-digit numbers work (I wasn't sure if they would)
'': ['12:60', '11:59:99', '-12:00', 'foo', '0660', '12345', '25:00'],
};
var passed = 0;
for (var key in testSuite) {
let num = parseFloat(key), h = num / 100 | 0;
let m = num % 100 | 0, s = (num % 1) * 60;
let expected = Date.UTC(1970, 0, 1, h, m, s); // Month is zero-based
let strings = testSuite[key];
for (let i = 0; i < strings.length; i++) {
var result = parseTime(strings[i]);
if (result === undefined ? key !== '' : key === '' || expected !== result.valueOf()) {
console.log(`Test failed at ${key}:"${strings[i]}" with result ${result ? result.toUTCString() : 'undefined'}`);
} else {
passed++;
}
}
}
console.log(passed + ' tests passed.');