15.4. 日付および時刻の扱い

Zend_Locale_Format では、日付や時刻を扱うためのメソッドを提供しています。 これらを使用して、さまざまなロケールのさまざまな書式間での変換や正規化を行います。 日付データや Zend_Date がサポートする、さまざまな標準書式や地域化された日付書式 を満たす日付文字列の操作には Zend_Date を使用します。 既存の定義済み書式を使用すると、「十分にテストされたコードが使用できる」 「(一般的な使用法に従う限り) 可搬性や相互運用性を保証できる」といった利点があります。 以下の例は、ここで推奨した内容に従っていません。しかし、 非標準の書式を使用することで、これらの例は不必要にわかりにくくなってしまっています。

15.4.1. 日付および時刻の正規化

getDate() メソッドは、地域化された書式の日付を含む文字列をパースします。 結果は構造化された配列で返されます。この配列のキーが、日付の各部分を表します。 さらに、この配列には 'format' というキーがあり、 入力日付文字列をパースする際に使用する書式文字列がここに含まれます。 地域化された日付文字列が日付/時刻のすべての要素を含んでいるとは限らないので、 配列のすべてのキーが存在するとは限りません。 たとえば年月日のみが指定された場合は、時刻に関する情報は配列から取り除かれます。 逆に時分秒のみが指定された場合も同様です。 入力に日付や時刻が含まれない場合は、例外がスローされます。

また、getCorrectableDate() メソッドは 'fixed' というキーを追加します。ここには数値が格納され、 入力の日付文字列の年月日の順序を入れ替えたりして 使用する書式にあわせるための情報を表します。

表 15.2. getCorrectableDate() の 'fixed' キーの値

意味    
0 なにも修正しません。    
1 無効な月を修正します。    
2 日付と年の位置を入れ替えます。    
3 月と年の位置を入れ替えます。    
4 月と日の位置を入れ替えます。    

BCMath 拡張モジュールが有効な場合に、 以下のような値が返されます。

表 15.3. 返り値

getDate() 書式文字 配列のキー 返される値 最小値 最大値
d day integer 1 31
M month integer 1 12
y year integer 無制限 PHP の整数型の最大値
h hour integer 0 PHP の整数型の最大値
m minute integer 0 PHP の整数型の最大値
s second integer 0 PHP の整数型の最大値

例 15.28. 日付の正規化

<?php
require_once 'Zend/Locale.php';

$date = Zend_Locale_Format::getDate('13.04.2006', 'dd.MM.yyyy');
$dateObject = Zend_Date('13.04.2006', 'dd.MM.yyyy'); // この日付に対応する Zend_Date オブジェクトを作成します

print_r($date); // 出力は、このようになります

Array
(
    [format] => dd.MM.yyyy
    [day] => 13
    [month] => 4
    [year] => 2006
)

// 入力値に何らかの問題がある場合に、自動的に修正します
$date2 = Zend_Locale_Format::getCorrectableDate('04.13.2006', 'dd.MM.yyyy');

print_r($date); // 出力は、このようになります

Array
(
    [format] => dd.MM.yyyy
    [day] => 13
    [month] => 4
    [year] => 2006
    [fixed] => 4
)
?>

getDate() は "ロケール対応" なので、 $locale を指定することで そのロケールの書式の日付文字列を使用できます。 getCorrectableDate() は簡単なテストを行って 日付や月の妥当性を確認します。問題が見つかったら、 経験則によってそれを何とか修正しようとします。

例 15.29. ロケールを指定した日付の正規化

<?php
require_once 'Zend/Locale.php';

$locale = new Zend_Locale('de_AT');
$date = Zend_Locale_Format::getDate('13.04.2006', null, $locale);

print_r ($date);
?>

入力に日付と時刻の両方が含まれている場合に、 完全な日付と時刻が返されます。

例 15.30. 日付と時刻の正規化

<?php
require_once 'Zend/Locale.php';

$locale = new Zend_Locale('de_AT');
$date = Zend_Locale_Format::getDate('13.04.2005 22:14:55', false, $locale);

print_r ($date);
?>

書式を指定したい場合は、 $locale ではなく $format 引数を指定します。 $format としてサポートされるのは、一文字のコード (H, m, s, y, M, d) および MMMM、EEEE だけです。

例 15.31. ユーザ定義の日付書式への正規化

<?php
require_once 'Zend/Locale.php';

$date = Zend_Locale_Format::getDate('13200504T551422', 'ddyyyyMM ssmmHH');

print_r ($date);
?>

書式には次の記号が使用できます。

表 15.4. 書式定義

書式指定文字 説明
d あるいは dd 1 桁あるいは 2 桁の日
M あるいは MM 1 桁あるいは 2 桁の月
y あるいは yy 1 桁あるいは 2 桁の年
yyyy 4 桁の年
h 1 桁あるいは 2 桁の時
m 1 桁あるいは 2 桁の分
s 1 桁あるいは 2 桁の秒

適切な書式の例は、次のようになります。

表 15.5. 書式の例

書式 入力 出力
dd.MM.yy 1.4.6 ['day'] => 1, ['month'] => 4, ['year'] => 6
dd.MM.yy 01.04.2006 ['day'] => 1, ['month'] => 4, ['year'] => 2006
yyyyMMdd 1.4.6 ['day'] => 6, ['month'] => 4, ['year'] => 1
[注意] データベースの日付書式

データベース (たとえば MySql や MsSql など) の日付値をパースするには、 getDate() のかわりに Zend_Date の ISO_8601 書式を使用します。

getCorrectableDate() は簡単なテストを行って 日付や月の妥当性を確認します。問題が見つかったら、 経験則によってそれを何とか修正しようとします。 getDate() は、 入力に問題がある場合にそれを自動で検出し、訂正します。 たとえば年の位置が違っている場合などがこれにあたります。

例 15.32. 入力された日付の訂正処理

<?php
require_once 'Zend/Locale.php';

$date = Zend_Locale_Format::getCorrectableDate('41.10.20', 'ddMMyy');

// 41 は、日付ではなく年として返されます
print_r ($date);
?>

15.4.2. 日付かどうかの確認

isDate($inputString, $format, $locale) を使用して、 指定した文字列が有効な日付を含むかどうかを調べます。 isDate() メソッドは getDate() を使用します。 getCorrectableDate() を使用すると、 入力が日付書式を満たしていない場合にも true を返してしまうので、これは使用しません。 月と日の位置が入れ替わっているなどのエラーが入力で検出された場合、 isCorrectableDate() メソッドは 経験則によってそれを "修正" してから検証します。

例 15.33. 日付かどうかの確認

<?php
require_once 'Zend/Locale.php';

$locale = new Zend_Locale('de_AT');
if (Zend_Locale_Format::isDate('13.Apr.2006', $locale) {
    print "日付です";
} else {
    print "日付ではありません";
} 
?>

15.4.3. 時刻の正規化

通常、入力に日付と時刻が両方含まれている場合は、 時刻は日付とともに返されます。 適切な書式はわからないが、ユーザの入力のロケールがわかるという場合に getTime() を使用します。 これは、選択したロケールに対するデフォルトの時刻書式を使用するからです。

例 15.34. 未知の時刻の正規化

<?php
require_once 'Zend/Locale.php';

$locale = new Zend_Locale('de_AT');
if (Zend_Locale_Format::getTime('13:44:42', $locale) {
    print "時刻です";
} else {
    print "時刻ではありません";
} 
?>

15.4.4. 時刻かどうかの確認

isTime() を使用して、 指定した文字列が有効な時刻を含むかどうかを調べます。

例 15.35. 時刻かどうかの確認

<?php
require_once 'Zend/Locale.php';

$locale = new Zend_Locale('de_AT');
if (Zend_Locale_Format::isTime('13:44:42', $locale) {
    print "時刻です";
} else {
    print "時刻ではありません";
} 
?>