从Java用户输入中将时间解析为Date对象的最佳方法是什么?
我正在使用一个表单小部件,供用户在文本输入中输入一天中的某个时间(对于日历应用程序)。使用JavaScript(我们使用的是jQuery FWIW),我想找到解析用户输入到JavaScriptDate()
对象中的文本的最佳方法,以便我可以轻松地对其进行比较和其他操作。
我尝试了parse()
方法,它对于我的需求有点挑剔。我希望它能够成功地将以下示例输入时间(除了其他逻辑上相似的时间格式)解析为相同的Date()
对象:
- 1:00 PM
- 1:00 PM。
- 下午1:00
- 1:00 PM
- 1:00 PM。
- 1:00p
- 下午1点
- 下午1点
- 1个
- 下午1点
- 下午1点
- 1p
- 13:00
- 13
我在想我可能会使用正则表达式来分割输入并提取要用于创建Date()
对象的信息。做这个的最好方式是什么?
解决方案
不用自己动手,只需使用datejs。
为什么不使用验证来缩小用户可以输入的内容,并简化列表,使其仅包含可以解析(或者在某些调整后解析)的格式。
我认为要求用户以受支持的格式放置时间并不要求太多。
dd:dd A(m)/ P(m)
dd A(m)/ P(m)
dd
一种适用于我们指定的输入的快速解决方案:
function parseTime( t ) { var d = new Date(); var time = t.match( /(\d+)(?::(\d\d))?\s*(p?)/ ); d.setHours( parseInt( time[1]) + (time[3] ? 12 : 0) ); d.setMinutes( parseInt( time[2]) || 0 ); return d; } var tests = [ '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', '1a', '12', '12a', '12p', '12am', '12pm', '2400am', '2400pm', '2400', '1000', '100', '123', '2459', '2359', '2359am', '1100', '123p', '1234', '1', '9', '99', '999', '9999', '99999', '0000', '0011', '-1', 'mioaw' ]; for ( var i = 0; i < tests.length; i++ ) { console.log( tests[i].padStart( 9, ' ' ) + " = " + parseTime(tests[i]) ); }
它也应该适用于其他几个品种(即使使用了上午,例如仍然可以使用)。显然,这很粗糙,但也很轻巧(例如,使用它比完整的库便宜得多)。
Warning: The code doe not work with 12:00 AM, etc.
在实施John Resig的解决方案时,我遇到了一些麻烦。这是根据他的回答我一直在使用的修改后的函数:
function parseTime(timeString) { if (timeString == '') return null; var d = new Date(); var time = timeString.match(/(\d+)(:(\d\d))?\s*(p?)/); d.setHours( parseInt(time[1]) + ( ( parseInt(time[1]) < 12 && time[4] ) ? 12 : 0) ); d.setMinutes( parseInt(time[3]) || 0 ); d.setSeconds(0, 0); return d; } // parseTime() var tests = [ '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', '1a', '12', '12a', '12p', '12am', '12pm', '2400am', '2400pm', '2400', '1000', '100', '123', '2459', '2359', '2359am', '1100', '123p', '1234', '1', '9', '99', '999', '9999', '99999', '0000', '0011', '-1', 'mioaw' ]; for ( var i = 0; i < tests.length; i++ ) { console.log( tests[i].padStart( 9, ' ' ) + " = " + parseTime(tests[i]) ); }
这是对Joe版本的改进。随时对其进行进一步编辑。
function parseTime(timeString) { if (timeString == '') return null; var d = new Date(); var time = timeString.match(/(\d+)(:(\d\d))?\s*(p?)/i); d.setHours( parseInt(time[1],10) + ( ( parseInt(time[1],10) < 12 && time[4] ) ? 12 : 0) ); d.setMinutes( parseInt(time[3],10) || 0 ); d.setSeconds(0, 0); return d; } var tests = [ '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', '1a', '12', '12a', '12p', '12am', '12pm', '2400am', '2400pm', '2400', '1000', '100', '123', '2459', '2359', '2359am', '1100', '123p', '1234', '1', '9', '99', '999', '9999', '99999', '0000', '0011', '-1', 'mioaw' ]; for ( var i = 0; i < tests.length; i++ ) { console.log( tests[i].padStart( 9, ' ' ) + " = " + parseTime(tests[i]) ); }
变化:
- 在parseInt()调用中添加了基数参数(因此jslint不会抱怨)。
- 使正则表达式具有区分大小写的功能,因此" 2:23 PM"的工作方式类似于" 2:23 pm"
/(\d+)(?::(\d\d))(?::(\d\d))?\s*([pP]?)/ // added test for p or P // added seconds d.setHours( parseInt(time[1]) + (time[4] ? 12 : 0) ); // care with new indexes d.setMinutes( parseInt(time[2]) || 0 ); d.setSeconds( parseInt(time[3]) || 0 );
谢谢
提供的所有示例在从12:00 am到12:59 am的时间内都无法正常工作。如果正则表达式与时间不匹配,它们也会引发错误。以下是处理此问题的方法:
function parseTime(timeString) { if (timeString == '') return null; var time = timeString.match(/(\d+)(:(\d\d))?\s*(p?)/i); if (time == null) return null; var hours = parseInt(time[1],10); if (hours == 12 && !time[4]) { hours = 0; } else { hours += (hours < 12 && time[4])? 12 : 0; } var d = new Date(); d.setHours(hours); d.setMinutes(parseInt(time[3],10) || 0); d.setSeconds(0, 0); return d; } var tests = [ '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', '1a', '12', '12a', '12p', '12am', '12pm', '2400am', '2400pm', '2400', '1000', '100', '123', '2459', '2359', '2359am', '1100', '123p', '1234', '1', '9', '99', '999', '9999', '99999', '0000', '0011', '-1', 'mioaw' ]; for ( var i = 0; i < tests.length; i++ ) { console.log( tests[i].padStart( 9, ' ' ) + " = " + parseTime(tests[i]) ); }
这将适用于其中包含时间的字符串。因此,将解析" abcde12:00pmdef"并返回12 pm。如果期望的结果是仅在字符串中仅包含时间的情况下返回一个时间,则可以使用以下正则表达式,前提是我们将" time [4]"替换为" time [6]"。
/^(\d+)(:(\d\d))?\s*((a|(p))m?)?$/i
这是一种更坚固的方法,它考虑了用户打算如何使用这种类型的输入。例如,如果用户输入" 12",则他们希望它是下午12点(中午)而不是上午12点。下面的函数可以处理所有这一切。也可以在这里找到:http://blog.de-zwart.net/2010-02/javascript-parse-time/
/** * Parse a string that looks like time and return a date object. * @return Date object on success, false on error. */ String.prototype.parseTime = function() { // trim it and reverse it so that the minutes will always be greedy first: var value = this.trim().reverse(); // We need to reverse the string to match the minutes in greedy first, then hours var timeParts = value.match(/(a|p)?\s*((\d{2})?:?)(\d{1,2})/i); // This didnt match something we know if (!timeParts) { return false; } // reverse it: timeParts = timeParts.reverse(); // Reverse the internal parts: for( var i = 0; i < timeParts.length; i++ ) { timeParts[i] = timeParts[i] === undefined ? '' : timeParts[i].reverse(); } // Parse out the sections: var minutes = parseInt(timeParts[1], 10) || 0; var hours = parseInt(timeParts[0], 10); var afternoon = timeParts[3].toLowerCase() == 'p' ? true : false; // If meridian not set, and hours is 12, then assume afternoon. afternoon = !timeParts[3] && hours == 12 ? true : afternoon; // Anytime the hours are greater than 12, they mean afternoon afternoon = hours > 12 ? true : afternoon; // Make hours be between 0 and 12: hours -= hours > 12 ? 12 : 0; // Add 12 if its PM but not noon hours += afternoon && hours != 12 ? 12 : 0; // Remove 12 for midnight: hours -= !afternoon && hours == 12 ? 12 : 0; // Check number sanity: if( minutes >= 60 || hours >= 24 ) { return false; } // Return a date object with these values set. var d = new Date(); d.setHours(hours); d.setMinutes(minutes); return d; } var tests = [ '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', '1a', '12', '12a', '12p', '12am', '12pm', '2400am', '2400pm', '2400', '1000', '100', '123', '2459', '2359', '2359am', '1100', '123p', '1234', '1', '9', '99', '999', '9999', '99999', '0000', '0011', '-1', 'mioaw' ]; for ( var i = 0; i < tests.length; i++ ) { console.log( tests[i].padStart( 9, ' ' ) + " = " + tests[i].parseTime() ); }
这是一个字符串原型,因此我们可以像这样使用它:
var str = '12am'; var date = str.parseTime();
AnyTime.Converter可以解析许多不同格式的日期/时间:
http://www.ama3.com/anytime/
对Patrick McElhaney解决方案的改进(他无法正确处理凌晨12点)
function parseTime( timeString ) { var d = new Date(); var time = timeString.match(/(\d+)(:(\d\d))?\s*([pP]?)/i); var h = parseInt(time[1], 10); if (time[4]) { if (h < 12) h += 12; } else if (h == 12) h = 0; d.setHours(h); d.setMinutes(parseInt(time[3], 10) || 0); d.setSeconds(0, 0); return d; } var tests = [ '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', '1a', '12', '2400', '1000', '100', '123', '2459', '2359', '2359am', '1100', '123p', '1234', '1', '9', '99', '999', '9999', '99999', '0000', '0011', '-1', 'mioaw' ]; for ( var i = 0; i < tests.length; i++ ) { console.log( tests[i].padStart( 9, ' ' ) + " = " + parseTime(tests[i]) ); }
对于所有使用以下24小时时钟的人,这里提供的解决方案更多:
- 0820-> 08:20
- 32-> 03:02
- 124-> 12:04
function parseTime(text) { var time = text.match(/(\d?\d):?(\d?\d?)/); var h = parseInt(time[1], 10); var m = parseInt(time[2], 10) || 0; if (h > 24) { // try a different format time = text.match(/(\d)(\d?\d?)/); h = parseInt(time[1], 10); m = parseInt(time[2], 10) || 0; } var d = new Date(); d.setHours(h); d.setMinutes(m); return d; } var tests = [ '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', '1a', '12', '12a', '12p', '12am', '12pm', '2400am', '2400pm', '2400', '1000', '100', '123', '2459', '2359', '2359am', '1100', '123p', '1234', '1', '9', '99', '999', '9999', '99999', '0000', '0011', '-1', 'mioaw' ]; for ( var i = 0; i < tests.length; i++ ) { console.log( tests[i].padStart( 9, ' ' ) + " = " + parseTime(tests[i]) ); }