回答編集履歴

2

追記

2016/08/10 12:19

投稿

hirohiro
hirohiro

スコア2068

test CHANGED
@@ -3,6 +3,10 @@
3
3
  正規表現で取り出した「日付と思しき」文字列をifと[checkdate](http://php.net/manual/ja/function.checkdate.php)などで別途判別するのが簡単かと。
4
4
 
5
5
 
6
+
7
+
8
+
9
+ ###追記(2016.08.10)
6
10
 
7
11
  > 2555.1000.3999だと単語境界を使わなくても「正しい西暦と月日を入力しよう」とでてくる
8
12
 

1

追記

2016/08/10 12:18

投稿

hirohiro
hirohiro

スコア2068

test CHANGED
@@ -1,3 +1,37 @@
1
1
  うるう年などdateの持つ複雑さを正規表現でパターン化するのは難しいのではないかと思います。
2
2
 
3
3
  正規表現で取り出した「日付と思しき」文字列をifと[checkdate](http://php.net/manual/ja/function.checkdate.php)などで別途判別するのが簡単かと。
4
+
5
+
6
+
7
+ > 2555.1000.3999だと単語境界を使わなくても「正しい西暦と月日を入力しよう」とでてくる
8
+
9
+ ```php
10
+
11
+ $seireki = "2550.1000-3999";//変な年、日にちでもマッチしてしまう。
12
+
13
+ if(preg_match("/([1-2]\d\d\d)[\/.\-]([0-1]*[0-9])[\/.\-]([0-3]*[0-9])/",$seireki,$data)) {
14
+
15
+ echo "<p>".$data[1]."年".$data[2]."月".$data[3]."日</p>";
16
+
17
+ } else {
18
+
19
+ echo "正しい西暦と月日を入力しよう";
20
+
21
+ }
22
+
23
+ ```
24
+
25
+ [paiza](https://paiza.io/)でこのコードを試してみましたが、出力は「<p>2550年1000月39日</p>」でした。2550.10.399でも「<p>2550年10月39日</p>」です。
26
+
27
+ 「*」は直前の文字の0回以上の繰り返しなので、
28
+
29
+ 月のところは00009にも117にもマッチしますが、123にはマッチしません。0か1が複数あった後に0-9のどれかが来る塊って意味ですね
30
+
31
+ 日の所も、0-3のどれかが複数続いた後、0-9のどれかが1文字やってくる塊って意味です。
32
+
33
+
34
+
35
+ もしかすると、「/\b([1-2]\d\d\d)[\/.\-]([0-1]{0,1}[0-9])[\/.\-]([0-3]{0,1}[0-9])\b/」これの方が目的に一致しているかも知れませんね。{0,1}は直前の文字が無いか1つだけ存在するって意味です。
36
+
37
+ この場合は単語境界を書くことで、12009.01.20や2009.02.299をNGにすることが出来ます。