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

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

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

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

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

表 18.4. getDate() のオプション 'fix_date' のキーの値

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

日付文字列の書式を明示的に指定したい場合のために、次のような書式トークン指定子をサポートしています。 Zend_Locale_Format のメソッドでユーザ定義書式に対応しているものの中で無効な書式指定子を使用した場合、 たとえば ISO モードで PHP の 'i' 指定子を使用した場合などには例外がスローされます。

これらの (以下の) 指定子は、Zend_Date の toString() がサポートしている完全な "ISO" セットの一部です。PHP の date() 関数と同じ形式の指定子を使用したい場合は、 まず最初に setOptions('format_type' => 'php') をコールしてください。 特定のひとつの書式文字列だけを PHP の date() 互換形式から "ISO" 形式に変換したい場合は convertPhpToIsoFormat() を使用します。現時点では、分の形式のみが異なっています (ISO のデフォルトでは 'm'、PHP の date 関数では 'i' を使用します)。

表 18.5. 返り値

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 の整数型の最大値

例 18.33. 日付の正規化

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

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

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

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

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

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

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

getDate() は "ロケール対応" なので、 $locale を指定することで そのロケールの書式の日付文字列を使用できます。 オプション 'fix_date' は、簡単なテストを行って 日付や月の妥当性を確認します。問題が見つかったら、 経験則によってそれを何とか修正しようとします。 'Zend_Locale_Format::STANDARD' を 'date_format' の値として指定すると、setOptions() で設定されているクラス全体のデフォルト日付書式を使用しないようにできます。 これにより、getDate は $locale のデフォルトの日付書式を使用するようになります。

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

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

$locale = new Zend_Locale('de_AT');
$date = Zend_Locale_Format::getDate('13.04.2006', array('date_format' => Zend_Locale_Format::STANDARD, 'locale' => $locale));

print_r ($date);
?>

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

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

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

$locale = new Zend_Locale('de_AT');
$date = Zend_Locale_Format::getDate('13.04.2005 22:14:55', array('date_format' => Zend_Locale_Format::STANDARD, 'locale' => $locale);

print_r ($date);
?>

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

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

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

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

print_r ($date);
?>

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

表 18.6. 書式定義

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

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

表 18.7. 書式の例

書式 入力 出力
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 書式を使用します。

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

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

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

$date = Zend_Locale_Format::getDate('41.10.20', array('date_format' => 'ddMMyy', 'fix_date' => true));

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

18.4.2. 日付かどうかの確認

checkDateFormat($inputString, array('date_format' => $format, $locale)) を使用して、 指定した文字列が期待通りの日付を含むかどうかを調べます。 checkDateFormat() メソッドは getDate() を使用します。 しかし、オプション 'fixdate' は使用しません。これを使用すると、 入力が日付書式を満たしていない場合にも true を返してしまうからです。 月と日の位置が入れ替わっているなどのエラーが入力で検出された場合、 オプション 'fixdate' は 経験則によってそれを "修正" してから検証します。

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

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

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

18.4.3. 時刻の正規化

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

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

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

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

18.4.4. 時刻かどうかの確認

checkDateFormat() を使用して、 指定した文字列が有効な時刻を含むかどうかを調べます。 使用法は、日付の確認の場合と同じです。ただし、 date_format には期待するパーツを指定しなければなりません。

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

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

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