クイックスタート
チュートリアル
ツールと言語
リファレンス
書評
正規表現の例
数値範囲
浮動小数点数
メールアドレス
IPアドレス
有効な日付
数値日付をテキストに変換
クレジットカード番号
完全な行に一致
重複行の削除
プログラミング
2つの近接する単語
落とし穴
カタストロフィックバックトラッキング
過剰な繰り返し
サービス拒否攻撃
すべてをオプションにする
繰り返しキャプチャグループ
Unicodeと8ビットの混合
このサイトについてさらに詳しく
はじめに
正規表現クイックスタート
正規表現チュートリアル
置換文字列チュートリアル
アプリケーションと言語
正規表現の例
正規表現リファレンス
置換文字列リファレンス
書評
印刷可能なPDF
このサイトについて
RSSフィードとブログ
RegexMagic—Generate regular expressions matching dates and times

有効な日付に一致する正規表現

^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$yyyy-mm-dd形式の日付(1900-01-01~2099-12-31)に4種類の区切り文字で一致させます。アンカーは、変数が日付全体であり、日付を含むテキストの一部ではないことを確認します。年は、(19|20)\d\dで一致させます。オルタネーションを使用して、最初の2桁を19または20にすることができます。括弧は必須です。括弧を省略した場合、正規表現エンジンは19または正規表現の残りの部分を探し始めます。これは2000-01-01~2099-12-31の間の日付に一致します。縦棒が正規表現全体を2つのオプションに分割するのを防ぐ唯一の方法は括弧です。

月は、0[1-9]|1[012]で一致させます。これも括弧で囲んで2つのオプションをまとめています。文字クラスを使用することで、最初のオプションは01~09の数値に、2番目のオプションは10、11、または12に一致します。

正規表現の最後の部分は3つのオプションで構成されています。最初のオプションは01~09の数値に、2番目のオプションは10~29の数値に、3番目のオプションは30または31に一致します。

オルタネーションを巧みに使用することで、オルタネーションを使用せずに除外できなかった2000-00-00などの無効な日付を除外できます。完璧主義者になるには、月の長さを考慮するために、月をさまざまなオプションに分割する必要があります。上記の正規表現は、無効な日付である2003-02-31にもまだ一致します。先頭のゼロをオプションにすることも別の強化策です。

区切り文字の一貫性を要求する場合は、バックリファレンスを使用できます。^(19|20)\d\d([- /.])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$は、1999-01-01には一致しませんが、1999/01-01.

正規表現をどの程度複雑にするかは、使用するデータと、望ましくない一致がすり抜けても問題ない程度によって異なります。スクリプトでユーザーの日付入力を検証する場合は、正規表現の外部で特定のチェックを行う方が簡単です。たとえば、年が閏年でない場合に2月29日を排除することは、スクリプト言語で行う方がはるかに簡単です。単純な算術演算を使用して、年が4で割り切れるかどうか(100で割り切れる場合は400で割り切れる場合を除く)を確認する方が、正規表現を使用するよりもはるかに簡単です。

Perlで有効な日付を確認する方法を次に示します。バックリファレンスに年をキャプチャするために括弧を追加しました。

sub isvaliddate {
  my $input = shift;
  if ($input =~ m!^((?:19|20)\d\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$!) {
    # At this point, $1 holds the year, $2 the month and $3 the day of the date entered
    if ($3 == 31 and ($2 == 4 or $2 == 6 or $2 == 9 or $2 == 11)) {
      return 0; # 31st of a month with 30 days
    } elsif ($3 >= 30 and $2 == 2) {
      return 0; # February 30th or 31st
    } elsif ($2 == 2 and $3 == 29 and not ($1 % 4 == 0 and ($1 % 100 != 0 or $1 % 400 == 0))) {
      return 0; # February 29th outside a leap year
    } else {
      return 1; # Valid date
    }
  } else {
    return 0; # Not a date
  }
}

mm/dd/yyyy形式の日付に一致させるには、正規表現を次のように変更します。^(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d$dd-mm-yyyy形式の場合は、次を使用します。^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$これらの正規表現のバリエーションは、RegexBuddyのライブラリにあります。