サンプル・プログラムの実行例

サンプル・プログラム
date2yyyymmdd.php | サンプル・プログラム本体 |
日付の表現形式
かならず年月日の3つ組でなければならない。
数字は半角でも全角でも構わないが、漢数字は対応しない。
また、区切り文字は「/」「-」「.」「年」「月」「日」で、半角・全角ともに対応する。

これを正規表現で表現すると、
/([0-90-9]{1,4})[\/\-\.\/-.年]{1}([0-90-9]{1,2})[\/\-\.\/-.月]{1}([0-90-9]{1,2})[\/\-\.\/-.日]?$/iuとなる。順に説明していこう。
今回使った正規表現
- (...)
- サブパターン。 マッチングだけであれば不要だが、置換を行うために、マッチした部分文字列に番号を付けてやる必要がある。その場合にサブパターンを用いる。
- [...]
- 文字クラス。 この中に記述された文字の並びのうちの1文字を表す。
- -
- 文字の範囲指定。 0-9 は半角数字に、0-9は全角数字にマッチする。
- {a,b}
- 直前文字の a 回以上 b 回以下の繰り返し。bは省略できる。 年は4桁以下、月と日は2桁以下の数字になるので、これを用いた。
- ?
- 直前1文字の0または1回の繰り返し。
- $
- 文字列の終端を表す。
- i
- 修飾子。パターンの中の文字は大文字にも小文字にもマッチする。
- u
- 修飾子。パターンと対象文字列はUTF-8として処理する。
解説:文字コードと正規表現
10: // 初期化処理 ================================================================
11: define('INTERNAL_ENCODING', 'UTF-8');
12: mb_internal_encoding(INTERNAL_ENCODING);
13: mb_regex_encoding(INTERNAL_ENCODING);
PHP の仕様上は関数 mb_internal_encoding だけで十分であるが、念のため、 mb_regex_encoding も指定した。

なお、PHP のマルチバイト文字列関数では、「JIS, SJIS, ISO-2022-JP, BIG-5」は「動作しないと思われる」とあるので、UTF-8 を用いることにした。PHP のマルチバイト系正規表現エンジンは、PHP4.x では Ruby のものを、PHP5.x では「鬼車」(Ruby 1.9.0 で搭載予定)を利用しているので、正規表現に限っては SJIS に対応している可能性は高いのだが、念のため UTF-8 を使うことにした。
36: //日付表示の分解パターン
37: $pat = '/([0-90-9]{1,4})[\/\-\.\/-.年]{1}([0-90-9]{1,2})[\/\-\.\/-.月]{1}([0-90-9]{1,2})[\/\-\.\/-.日]?/iu';
解説:分解処理
206: //テキストを分解
207: if (preg_match($pat, $sour, $arr) == 1) {
208: if (count($arr) != 4) { //分解に失敗
209: $yyyy = 'error!';
210: $mm = 'error!';
211: $dd = 'error!';
212: } else {
213: $yyyy = intval(mb_convert_kana($arr[1], 'n'));
214: if ($yyyy < 100) $yyyy += 2000; //西暦2桁なら2000を加算
215: $mm = intval(mb_convert_kana($arr[2], 'n'));
216: $dd = intval(mb_convert_kana($arr[3], 'n'));
217: }
218:
219: //分解に失敗
220: } else {
221: $yyyy = 'error!';
222: $mm = 'error!';
223: $dd = 'error!';
224: }

年月日の3つ組が入力されていることが前提なので、入力された文字列自身($arr[0])を含め、配列変数 $arr の要素数は必ず4になるはずである。そこで、関数 count を使って要素数をチェックする。そうでなければ、変数に文字列 "error!" を代入する。

正常に3つに分解できたら、関数 mb_convert_kana 関数で全角数字を半角数字に変換し、関数 intval で整数化する。
また、西暦年が2桁の場合は、自動的に 2000 を加算するようにした。

必要に応じて、分解された年月日が正しい値かどうかチェックする仕組みも追加するといいだろう(例:2月30日はエラー)。
(2021年8月1日)PHP8対応,リファラ・チェック追加.