読者です 読者をやめる 読者になる 読者になる

HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

日付文字列のフォーマットのメモ

PHP Linux

RFC 2822に従った日付文字列の生成

一発で出力できる指定子があることに気付かず、試行錯誤したのだが、せっかくなのでメモしておく。

RFC 2822に従った日付文字列は以下のような形式。

Thu, 18 Jun 2015 16:43:47 +0900

メールのヘッダなんかに使われることになっているもの。 ものによっては以下の形式も見かける。

Thu, 18 Jun 2015 16:43:47 +0900 (JST)

これをPHPで出力しようと思ったら、以下のように書けばいい。なお、PHPの初期設定をちゃんとやっていない環境なので余計な処理が冒頭に入っているが気にしない(謎)。

<?php
date_default_timezone_set('Asia/Tokyo');
mb_internal_encoding('UTF-8');

$time = strtotime('2015-06-09 17:02:03');

printf("===date===\n");
printf("    %s\n", 'RFC 2822');
printf("        %s\n", date('r', $time));
printf("        %s\n", date('D, d M Y H:i:s O', $time));

printf("    %s\n", 'RFC 2822 with Timezone abbreviation');
printf("        %s\n", date('r (T)', $time));
printf("        %s\n", date('D, d M Y H:i:s O (T)', $time));

出力は以下のような感じ。

===date===
    RFC 2822
        Tue, 09 Jun 2015 17:02:03 +0900
        Tue, 09 Jun 2015 17:02:03 +0900
    RFC 2822 with Timezone abbreviation
        Tue, 09 Jun 2015 17:02:03 +0900 (JST)
        Tue, 09 Jun 2015 17:02:03 +0900 (JST)

ISO 8601拡張形式

ついでなのでやってみた(謎)。

ISO 8601拡張形式に従った日付文字列は以下のような形式。

2015-06-18T16:43:47+0900

これも、一発で出力できる指定子がある。

<?php
date_default_timezone_set('Asia/Tokyo');
mb_internal_encoding('UTF-8');

$time = strtotime('2015-06-09 17:02:03');

printf("===date===\n");
printf("    %s\n", 'ISO 8601 date');
printf("        %s\n", date('c', $time));
printf("        %s\n", date('Y-m-d\TH:i:sP', $time));

出力。

===date===
    ISO 8601 date
        2015-06-09T17:02:03+09:00
        2015-06-09T17:02:03+09:00

(ダメ)strftimeでRFC 2822形式

さらについでなので、strftime関数で色々やってみた。setLocale呼び出しに影響を受ける関数なので、当然ながら汎用性はないのだが‥

<?php
date_default_timezone_set('Asia/Tokyo');
mb_internal_encoding('UTF-8');

$time = strtotime('2015-06-09 17:02:03');

printf("===strftime===\n");
$locales = array(
    '英語(US)            ' => 'en_US',
    '英語(UK)            ' => 'en_GB',
    '日本語              ' => 'ja_JP',
    'ドイツ語            ' => 'de_DE',
    'オランダ語          ' => 'nl_NL',
    'フランス語(フランス)' => 'fr_FR',
    'フランス語(カナダ)  ' => 'fr_CA',
    'スペイン語          ' => 'es_ES',
    'ポルトガル語        ' => 'pt_PT',
    '中国語(繁体字)      ' => 'zh_TW',
    '中国語(簡体字)      ' => 'zh_CN',
    '韓国語              ' => 'ko_KR',
);
$formats = array(
    'RFC 2822'
        => '%a, %d %b %Y %H:%M:%S %z',
    'RFC 2822 with Timezone abbreviation'
        => '%a, %d %b %Y %H:%M:%S %z (%Z)',
);
foreach ($formats as $name => $format) {
    printf("%s\n", $name);
    foreach ($locales as $country => $locale) {
        printf("    %s(%s): ", setLocale(LC_ALL, $locale . '.UTF-8'), $country);

        printf("        %s\n", strftime($format, $time));
    }
}

出力。

===strftime===
RFC 2822
    en_US.UTF-8(英語(US)            ):         Tue, 09 Jun 2015 17:02:03 +0900
    en_GB.UTF-8(英語(UK)            ):         Tue, 09 Jun 2015 17:02:03 +0900
    ja_JP.UTF-8(日本語              ):         火, 09  6月 2015 17:02:03 +0900
    de_DE.UTF-8(ドイツ語            ):         Di, 09 Jun 2015 17:02:03 +0900
    nl_NL.UTF-8(オランダ語          ):         di, 09 jun 2015 17:02:03 +0900
    fr_FR.UTF-8(フランス語(フランス)):         mar., 09 juin 2015 17:02:03 +0900
    fr_CA.UTF-8(フランス語(カナダ)  ):         mar, 09 jun 2015 17:02:03 +0900
    es_ES.UTF-8(スペイン語          ):         mar, 09 jun 2015 17:02:03 +0900
    pt_PT.UTF-8(ポルトガル語        ):         Ter, 09 Jun 2015 17:02:03 +0900
    zh_TW.UTF-8(中国語(繁体字)      ):         二, 09  6月 2015 17:02:03 +0900
    zh_CN.UTF-8(中国語(簡体字)      ):         二, 09 6月 2015 17:02:03 +0900
    ko_KR.UTF-8(韓国語              ):         화, 09  6월 2015 17:02:03 +0900
RFC 2822 with Timezone abbreviation
    en_US.UTF-8(英語(US)            ):         Tue, 09 Jun 2015 17:02:03 +0900 (JST)
    en_GB.UTF-8(英語(UK)            ):         Tue, 09 Jun 2015 17:02:03 +0900 (JST)
    ja_JP.UTF-8(日本語              ):         火, 09  6月 2015 17:02:03 +0900 (JST)
    de_DE.UTF-8(ドイツ語            ):         Di, 09 Jun 2015 17:02:03 +0900 (JST)
    nl_NL.UTF-8(オランダ語          ):         di, 09 jun 2015 17:02:03 +0900 (JST)
    fr_FR.UTF-8(フランス語(フランス)):         mar., 09 juin 2015 17:02:03 +0900 (JST)
    fr_CA.UTF-8(フランス語(カナダ)  ):         mar, 09 jun 2015 17:02:03 +0900 (JST)
    es_ES.UTF-8(スペイン語          ):         mar, 09 jun 2015 17:02:03 +0900 (JST)
    pt_PT.UTF-8(ポルトガル語        ):         Ter, 09 Jun 2015 17:02:03 +0900 (JST)
    zh_TW.UTF-8(中国語(繁体字)      ):         二, 09  6月 2015 17:02:03 +0900 (JST)
    zh_CN.UTF-8(中国語(簡体字)      ):         二, 09 6月 2015 17:02:03 +0900 (JST)
    ko_KR.UTF-8(韓国語              ):         화, 09  6월 2015 17:02:03 +0900 (JST)

試した環境では「ja_JP.UTF-8」のようにしないと、マルチバイト文字がうまく見えなかったが、きっと環境のせい。

英語なんかだと、当然ながら期待する出力になっている。 ただし、期待する出力になっているlocaleでも、Windows環境など、環境によっては全然違う文字列が生成されることもあるので注意するようにということがマニュアルには書いてある。

(ダメ)strftimeでISO 8601拡張形式

さらにさらについでなので、strftime関数で色々やってみた。当然ながら(ry

<?php

/*
 * http://php.net/manual/ja/function.strftime.php
 * http://php.net/manual/ja/function.date.php
 */

date_default_timezone_set('Asia/Tokyo');
mb_internal_encoding('UTF-8');

$time = strtotime('2015-06-09 17:02:03');

printf("===strftime===\n");
$locales = array(
    '英語(US)            ' => 'en_US',
    '英語(UK)            ' => 'en_GB',
    '日本語              ' => 'ja_JP',
    'ドイツ語            ' => 'de_DE',
    'オランダ語          ' => 'nl_NL',
    'フランス語(フランス)' => 'fr_FR',
    'フランス語(カナダ)  ' => 'fr_CA',
    'スペイン語          ' => 'es_ES',
    'ポルトガル語        ' => 'pt_PT',
    '中国語(繁体字)      ' => 'zh_TW',
    '中国語(簡体字)      ' => 'zh_CN',
    '韓国語              ' => 'ko_KR',
);
$formats = array(
    'ISO 8601 date'
        => '%Y-%m-%dT%H:%M:%S%z',
);
foreach ($formats as $name => $format) {
    printf("%s\n", $name);
    foreach ($locales as $country => $locale) {
        printf("    %s(%s): ", setLocale(LC_ALL, $locale . '.UTF-8'), $country);

        printf("        %s\n", strftime($format, $time));
    }
}

出力。

===strftime===
ISO 8601 date
    en_US.UTF-8(英語(US)            ):         2015-06-09T17:02:03+0900
    en_GB.UTF-8(英語(UK)            ):         2015-06-09T17:02:03+0900
    ja_JP.UTF-8(日本語              ):         2015-06-09T17:02:03+0900
    de_DE.UTF-8(ドイツ語            ):         2015-06-09T17:02:03+0900
    nl_NL.UTF-8(オランダ語          ):         2015-06-09T17:02:03+0900
    fr_FR.UTF-8(フランス語(フランス)):         2015-06-09T17:02:03+0900
    fr_CA.UTF-8(フランス語(カナダ)  ):         2015-06-09T17:02:03+0900
    es_ES.UTF-8(スペイン語          ):         2015-06-09T17:02:03+0900
    pt_PT.UTF-8(ポルトガル語        ):         2015-06-09T17:02:03+0900
    zh_TW.UTF-8(中国語(繁体字)      ):         2015-06-09T17:02:03+0900
    zh_CN.UTF-8(中国語(簡体字)      ):         2015-06-09T17:02:03+0900
    ko_KR.UTF-8(韓国語              ):         2015-06-09T17:02:03+0900

こっちは、localeに依存しない指定子しかつかっていないからか、localeに関係なく、試した範囲では同じ出力だった。 まぁ、変な心配をするより、素直にdate関数を使えという話だが‥