74

ユーザーがテキスト入力に時刻を入力するためのフォームウィジェットに取り組んでいます(カレンダーアプリケーション用)。JavaScript (私たちは jQuery FWIW を使用しています) を使用して、ユーザーが JavaScriptDate()オブジェクトに入力したテキストを解析する最良の方法を見つけて、比較やその他のことを簡単に実行できるようにしたいと考えています。

私はその方法を試しましたparse()が、私のニーズには少しうるさいです。Date()次の例の入力時間 (論理的に類似した他の時間形式に加えて) を同じオブジェクトとして正常に解析できると期待しています。

  • 午後1:00
  • 午後1:00
  • 午後1時
  • 午後1:00
  • 午後1:00。
  • 午後1時
  • 午後1時
  • 午後1時
  • 1p
  • 午後1時
  • 午後1時。
  • 1p
  • 13:00
  • 13

正規表現を使用して入力を分割し、オブジェクトの作成に使用する情報を抽出することを考えていDate()ます。これを行う最善の方法は何ですか?

4

22 に答える 22

76

指定した入力で機能する簡単なソリューション:

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]) );
}

他のいくつかの種類でも機能するはずです (たとえば、 am が使用されていても機能します)。明らかに、これはかなり大雑把ですが、かなり軽量でもあります (たとえば、完全なライブラリを使用するよりもはるかに安価です)。

警告: コードは午前 0 時などでは機能しません。

于 2008-09-26T19:44:31.240 に答える
55

提供されているすべての例は、午前 0 時から午前 12 時 59 分までの間は機能しません。正規表現が時間と一致しない場合にもエラーがスローされます。以下がこれを処理します。

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 時を返します。文字列に時刻のみが含まれる場合にのみ時刻を返すことが望ましい結果である場合は、「time[4]」を「time[6]」に置き換えれば、次の正規表現を使用できます。

/^(\d+)(:(\d\d))?\s*((a|(p))m?)?$/i
于 2010-02-02T23:50:20.430 に答える
32

自分でやる必要はありません。datejsを使用してください。

于 2008-09-26T19:18:52.817 に答える
16

ここでの正規表現ソリューションのほとんどは、文字列を解析できない場合にエラーをスローし1330ます130pm。これらの形式は OP で指定されていませんでしたが、人間が入力した日付を解析するために重要であることがわかりました。

これらすべてのことから、正規表現を使用するのは最善の方法ではないかもしれないと考えるようになりました。

私の解決策は、時間を解析するだけでなく、出力形式と分を丸めるステップ (間隔) を指定できる関数です。約 70 行で、まだ軽量であり、前述のすべての形式とコロンなしの形式を解析します。

function parseTime(time, format, step) {
	
	var hour, minute, stepMinute,
		defaultFormat = 'g:ia',
		pm = time.match(/p/i) !== null,
		num = time.replace(/[^0-9]/g, '');
	
	// Parse for hour and minute
	switch(num.length) {
		case 4:
			hour = parseInt(num[0] + num[1], 10);
			minute = parseInt(num[2] + num[3], 10);
			break;
		case 3:
			hour = parseInt(num[0], 10);
			minute = parseInt(num[1] + num[2], 10);
			break;
		case 2:
		case 1:
			hour = parseInt(num[0] + (num[1] || ''), 10);
			minute = 0;
			break;
		default:
			return '';
	}
	
	// Make sure hour is in 24 hour format
	if( pm === true && hour > 0 && hour < 12 ) hour += 12;
	
	// Force pm for hours between 13:00 and 23:00
	if( hour >= 13 && hour <= 23 ) pm = true;
	
	// Handle step
	if( step ) {
		// Step to the nearest hour requires 60, not 0
		if( step === 0 ) step = 60;
		// Round to nearest step
		stepMinute = (Math.round(minute / step) * step) % 60;
		// Do we need to round the hour up?
		if( stepMinute === 0 && minute >= 30 ) {
			hour++;
			// Do we need to switch am/pm?
			if( hour === 12 || hour === 24 ) pm = !pm;
		}
		minute = stepMinute;
	}
	
	// Keep within range
	if( hour <= 0 || hour >= 24 ) hour = 0;
	if( minute < 0 || minute > 59 ) minute = 0;

	// Format output
	return (format || defaultFormat)
		// 12 hour without leading 0
        .replace(/g/g, hour === 0 ? '12' : 'g')
		.replace(/g/g, hour > 12 ? hour - 12 : hour)
		// 24 hour without leading 0
		.replace(/G/g, hour)
		// 12 hour with leading 0
		.replace(/h/g, hour.toString().length > 1 ? (hour > 12 ? hour - 12 : hour) : '0' + (hour > 12 ? hour - 12 : hour))
		// 24 hour with leading 0
		.replace(/H/g, hour.toString().length > 1 ? hour : '0' + hour)
		// minutes with leading zero
		.replace(/i/g, minute.toString().length > 1 ? minute : '0' + minute)
		// simulate seconds
		.replace(/s/g, '00')
		// lowercase am/pm
		.replace(/a/g, pm ? 'pm' : 'am')
		// lowercase am/pm
		.replace(/A/g, pm ? 'PM' : 'AM');
}

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]) );
}

于 2013-02-09T11:02:13.393 に答える
12

これは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」のように機能します
于 2008-12-03T19:33:01.963 に答える
3

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]) );
}

于 2008-10-31T14:21:17.537 に答える
3

以下をサポートする 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]) );
}

于 2010-10-22T15:29:16.520 に答える
2

これは、ユーザーがこのタイプの入力をどのように使用するかを考慮した、より厳格なアプローチです。たとえば、ユーザーが「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();
于 2010-02-21T20:22:20.250 に答える
2

時間パッケージのサイズは 0.9kbs です。NPM および bower パッケージ マネージャーで利用できます。

から直接の例を次に示しREADME.mdます。

var t = Time('2p');
t.hours();             // 2
t.minutes();           // 0
t.period();            // 'pm'
t.toString();          // '2:00 pm'
t.nextDate();          // Sep 10 2:00 (assuming it is 1 o'clock Sep 10)
t.format('hh:mm AM')   // '02:00 PM'
t.isValid();           // true
Time.isValid('99:12'); // false
于 2017-03-04T01:08:26.007 に答える
1

AnyTime.Converter は、さまざまな形式で日付/時刻を解析できます。

http://www.ama3.com/anytime/

于 2010-03-19T09:32:05.433 に答える
1

たくさんの答えがあるので、もう 1 つは問題ありません。

/**
 * Parse a time in nearly any format
 * @param {string} time - Anything like 1 p, 13, 1:05 p.m., etc.
 * @returns {Date} - Date object for the current date and time set to parsed time
*/
function parseTime(time) {
  var b = time.match(/\d+/g);
  
  // return undefined if no matches
  if (!b) return;
  
  var d = new Date();
  d.setHours(b[0]>12? b[0] : b[0]%12 + (/p/i.test(time)? 12 : 0), // hours
             /\d/.test(b[1])? b[1] : 0,     // minutes
             /\d/.test(b[2])? b[2] : 0);    // seconds
  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]) );
}

適切にロバストにするために、各値が許容値の範囲内にあることを確認する必要があります。たとえば、午前/午後の時間が 1 から 12 までである必要がある場合、そうでない場合は 0 から 24 までであるなどです。

于 2015-01-05T11:48:14.923 に答える
1

上記の関数にいくつかの変更を加えて、さらにいくつかの形式をサポートしました。

  • 14:00 -> 午後 2:00
  • 午後 1 時 30 分 -> 午後 1 時 30 分
  • 午前 1:30 -> 午前 1:30
  • 100 -> 午前 1:00

まだクリーンアップされていませんが、私が考えることができるすべてのもので機能します。

function parseTime(timeString) {
    if (timeString == '') return null;

    var time = timeString.match(/^(\d+)([:\.](\d\d))?\s*((a|(p))m?)?$/i);

    if (time == null) return null;

    var m = parseInt(time[3], 10) || 0;
    var hours = parseInt(time[1], 10);

    if (time[4]) time[4] = time[4].toLowerCase();

    // 12 hour time
    if (hours == 12 && !time[4]) {
        hours = 12;
    }
    else if (hours == 12 && (time[4] == "am" || time[4] == "a")) {
        hours += 12;
    }
    else if (hours < 12 && (time[4] != "am" && time[4] != "a")) {
        hours += 12;
    }
    // 24 hour time
    else if(hours > 24 && hours.toString().length >= 3) {
        if(hours.toString().length == 3) {
           m = parseInt(hours.toString().substring(1,3), 10);
           hours = parseInt(hours.toString().charAt(0), 10);
        }
        else if(hours.toString().length == 4) {
           m = parseInt(hours.toString().substring(2,4), 10);
           hours = parseInt(hours.toString().substring(0,2), 10);
        }
    }

    var d = new Date();
    d.setHours(hours);
    d.setMinutes(m);
    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]) );
}

于 2011-12-06T05:57:33.583 に答える
0

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]) );
}

于 2010-10-22T14:50:50.170 に答える
0
/(\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 );

ありがとう

于 2009-01-11T11:43:47.280 に答える
0

検証を使用して、ユーザーが入力できるものを絞り込み、リストを単純化して、解析可能な (または微調整後に解析できる) 形式のみを含めてみませんか。

サポートされている形式で時間を入力するようにユーザーに要求することは、あまり要求しているとは思いません。

dd:dd A(m)/P(m)

ddA(m)/P(m)

dd

于 2008-09-26T19:40:51.937 に答える
0

タイムパーサー関数が必要で、いくつかの回答に基づいて、この関数になりました

 function parse(time){
  let post_meridiem = time.match(/p/i) !== null;
  let result;
  time = time.replace(/[^\d:-]/g, '');
  let hours = 0;
  let minutes = 0;
  if (!time) return;
  let parts = time.split(':');
  if (parts.length > 2) time = parts[0] + ':' + parts[1];
  if (parts[0] > 59 && parts.length === 2) time = parts[0];
  if (!parts[0] && parts[1] < 60) minutes = parts[1];
  else if (!parts[0] && parts[1] >= 60) return;
  time = time.replace(/^00/, '24');
  time = parseInt(time.replace(/\D/g, ''));
  if (time >= 2500) return;
  if (time > 0 && time < 24 && parts.length === 1) hours = time;
  else if (time < 59) minutes = time;
  else if (time >= 60 && time <= 99 && parts[0]) {
    hours = ('' + time)[0];
    minutes = ('' + time)[1];
  } else if (time >= 100 && time <= 2359) {
    hours = ~~(time / 100);
    minutes = time % 100;
  } else if (time >= 2400) {
    hours = ~~(time / 100) - 24;
    minutes = time % 100;
    post_meridiem = false;
  }
  if (hours > 59 || minutes > 59) return;
  if (post_meridiem && hours !== 0) hours += 12;
  if (minutes > 59) minutes = 59;
  if (hours > 23) hours = 0;
  result = ('' + hours).padStart(2, '0') + ':' + ('' + minutes).padStart(2, '0');
  return result;
}
 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', '0000', '0011', '-1', 'mioaw',
  "0820",
  "32",
  "124",
  "1330",
  "130pm",
  "456",
  ":40",
  ":90",
  "12:69",
  "50:90",
  "aaa12:34aaa",
  "aaa50:00aaa",
 ];

    for ( var i = 0; i < tests.length; i++ ) {
      console.log( tests[i].padStart( 9, ' ' ) + " = " + parse(tests[i]) );
    }
また、それは他の回答の編集表にあります ここにフォークがあります 他の回答の編集表

于 2021-02-25T15:02:07.417 に答える