4

有効な日付を確認するために JavaScript で「無効な日付」の日付インスタンスを検出するからの 2 つの一般的な回答を試しました。どちらも IE8 でテストしましたが、残念ながらどちらも期待外れです。ここでそれを参照してくださいhttp://jsfiddle.net/Lijo/uzSU6/2/

IE8 + Chrome + Firefox で動作するより良い JavaScript コードはありますか?

注: 驚いたことに、Firefox でもうまく動作しません...

調子

日付形式は、スラッシュ (/) を含む米国の日付形式である必要があります

ここに画像の説明を入力

コード

isValidDateCheck2('12/33/2012') ;
isValidDateCheck1('12/12/2012') ;

function isValidDateCheck1(d) 
{
  alert(Object.prototype.toString.call(d));
  if ( Object.prototype.toString.call(d) !== "[object Date]" )
  {
    alert('Not Valid');
  }
  if(!isNaN(d.getTime()))
  {
  alert(d.getTime());
  }
  }

  function  isValidDateCheck2(d)
  {    
    var timestamp=Date.parse(d);
    alert(timestamp);

    if (isNaN(timestamp)==false)
    {
        var date=new Date(timestamp);
        alert(date);                    
    }
   }

編集

@mplungjan アプローチ (最初に提案) はhttp://jsfiddle.net/Lijo/uzSU6/7/にリストされています。これは、IE8 で 1 つのシナリオ ( http://jsfiddle.net/Lijo/uzSU6/12/ ) で失敗しました。

4

3 に答える 3

8

ここで2つのことを混同しているようです。有効な日付オブジェクトと有効な日付。これらは同じ問題ではありません。

リンクした質問は、日付オブジェクトの有効性をテストする方法に答えます(日付オブジェクトが「無効な日付」インスタンスであるかどうか)。作成時に無効なパラメーターを使用すると、無効な日付オブジェクトが生成されます。new Date('?')

必要なのは、日付文字列が事前定義された日付形式に準拠しているかどうかをテストすることです。これは、日付オブジェクトのみを使用して解決すべきではない、まったく別の問題です。

一般的に言えば、これにはいくつかの理由があります。1 つ目は、ブラウザーがオーバーフローした月/日/時間を正しい日付 ( new Date(2012,0,290)=== 2012 年 10 月 6 日) に計算するのに役立つことです。

第二に、パーサーがロケールに依存している可能性があるためです (mm/dd と dd/mm?)。日付がブラウザーによって解析されると、私のロケールが原因でタイムゾーン/DST にロールバックされる可能性があり、その結果、日付がゆがみ、検出が台無しになります (.getDate次の日に戻る可能性があります)。さらに悪いことに、これは 1 年の特定の時期の一部のタイムゾーンでのみ発生する可能性があります。

日付はあなたが思っているよりもはるかに難しいので、 date.jsのようなライブラリを使用してこの処理を行うことを強くお勧めします。どうしても手動で検証する必要がある場合は、次のように詳細に検証することをお勧めします。

function isValidDate (str) {
  // parse to numbers
  const rm = str.split('/');
  const m = 1 * rm[0];
  const d = 1 * rm[1];
  const y = 1 * rm[2];
  if (isNaN(m * d * y)) {
    return false;
  }
  // day can't be 0
  if (d < 1) {
    return false;
  }
  // month must be 1-12
  if (m < 1 || m > 12) {
    return false;
  }
  // february
  if (m === 2) {
    const isLeapYear = ((y % 4 === 0) && (y % 100 !== 0)) || (y % 400 === 0);
    // leap year
    if (isLeapYear && d > 29) {
      return false;
    }
    // non-leap year
    if (!isLeapYear && d > 28) {
      return false;
    }
  }
  // test any other month
  else if (
    ((m === 4 || m === 6 || m === 9 || m === 11) && d > 30) ||
    ((m === 1 || m === 3 || m === 5 || m === 7 || m === 8 || m === 10 || m === 12) && d > 31)) {
    return false;
  }
  return true;
}

jsFiddle として: http://jsfiddle.net/3pMPp/1/
jsPerf として: http://jsperf.com/silly-date-valiation

于 2012-12-15T23:56:59.827 に答える
3

これにより、実際の日付が処理され、 DATE OBJECTを使用して、日付のどの部分が無効であったかを見つけることができます。

: いくつかのブラウザーは、無効な日付と思われるものを喜んで解析し、そこから日付オブジェクトを作成します。たとえば、2013 年 2 月 29 日は 2013 年 3 月 1 日として解析されるため、入力された部分が実際の日付で使用された場合に意味があるかどうかを確認するテストを行いました。

デモ

テスト済み

Win7:

  • Chrome 23 (最初のデートで isNaN を与えるのは 1 つだけ)
  • IE9

ウィン XP:

  • FX17
  • IE8
  • サファリ5
  • オペラ11と12
function isValidDateCheck(dString) {

    // test it is nn/nn/nnnn or nn/nn/nn
    var dRe = /^(\d{1,2})([\-\/])(\d{1,2})\2(\d{4}|\d{2})$/

    if (!dRe.exec(dString)) {
      return false; 
    }   

    // make sure it parses as date 
    // replace this part if you do not allow dashes        
    dString.replace(/-/g,"/"); 

    var date = new Date(dString); // create a date object
    if (!isNaN(date)) { // it may give NaN - if not test the parts
        var parts = dString.split("/"); // split on slash
        var dd = parseInt(parts[1],10); // day number
        var mm = parseInt(parts[0],10)-1; // month - JS months start at 0
        var yyyy = parseInt(parts[2],10); // year
        // return true if all parts match
        return dd===date.getDate() && mm === date.getMonth() && yyyy===date.getFullYear();
    }
    // here the date was not parsed as a date
    return false;
}


window.onload=function() {
  document.getElementById("output").innerHTML+="<br/>12/33/2012: "+isValidDateCheck('12/33/2012');
  document.getElementById("output").innerHTML+="<br/>12/12/2012: "+isValidDateCheck('12/12/2012') ;
  document.getElementById("output").innerHTML+="<br/>02/29/2012: "+isValidDateCheck('02/29/2012') ;
  document.getElementById("output").innerHTML+="<br/>02/29/2013: "+isValidDateCheck('02/29/2013') ;
  document.getElementById("output").innerHTML+="<br/>01/01/2013A: "+isValidDateCheck('01/01/2013A') ;
}
于 2012-12-14T12:35:25.507 に答える
1

@mplungjanに感謝します。私はその答えに賛成しました。

@mplungjanアプローチ(最初に提案された)はhttp://jsfiddle.net/Lijo/uzSU6/7/にリストされています。これは、IE8で1つのシナリオ(http://jsfiddle.net/Lijo/uzSU6/12/ )で失敗しました。

だから私は日付を検証する方法を参照した後、少し異なるアプローチを使用しましたか?。こちらをご覧くださいhttp://jsfiddle.net/Lijo/uzSU6/20/

編集

空白を処理するシナリオについては、 http://jsfiddle.net/uzSU6/37/を参照してください。

このアプローチであなたの提案/挑戦を自由に与えてください。

参考文献

  1. トリムを使用せずに空白が存在するかどうかを確認します
  2. JavaScriptの比較では、どの等しい演算子(== vs ===)を使用する必要がありますか?
  3. 日付を検証する方法は?

コード

function isValidDate(s) 
{
var bits = s.split('/');

if(s.indexOf(' ') != -1)
{
    //White space exists in the original date string
    return false;
}

//Javascript month starts at zero
var d = new Date(bits[2], bits[0] - 1, bits[1]);


if ( isNaN( Number(bits[2]) ) ) 
{
    //Year is not valid number
    return false;
}

if ( Number(bits[2]) < 1 ) 
{
    //Year should be greater than zero
    return false;
}



//1. Check whether the year is a Number
//2. Check whether the date parts are eqaul to original date components
//3. Check whether d is valid

return d && ( (d.getMonth() + 1) == bits[0]) && (d.getDate() == Number(bits[1]) );

} 

</ p>

于 2012-12-14T14:35:43.743 に答える