PHP

strftime関数がWindowsだと文字化けする件について

Linux上のPHPでは問題なく使えるんですが、XAMPPで動かしているPHPだとフォーマット文字列の解釈が上手くいかないんです。。。
その原因を探ってみたのでメモ。

例えば下記のようなコードを書きます。

echo strftime('%Y年%m月%d日 %H時%M分');

Linux環境だと期待通りに下記のように出力されます。

2010年02月27日 10時00分

しかしWindows上のXAMPPで試すと。。。

2010年02月%d日 10時%M分

日本語の部分を抜けば問題ないのですが、フォーマット文字に日本語を使うと特定の組み合わせでこのように変換指定子が解釈されない事がある上、おまけに場合によっては化けた文字がくっついてくるという悲惨なことになります。
原因はどうもLC_CTYPEのロケール設定がWindowsではJapanese_Japan.932になっている為のようです。下記コードを実行してみればわかります。

echo setlocale(LC_CTYPE, 0);

ソースコードがCP932(Shift_JIS)で書かれていれば問題ないのでしょうが、本番はLinuxで動かすプログラムを想定すると、やはりUTF-8で書くことが望ましいです。(他にも利点はあるけど)
そこで次のようなコードを実行してロケール変更を試みました。

setlocale(LC_ALL, 'Japanese_Japan.65001');
(65001はUTF-8)

ですが、だめです。LC_CTYPEだけは932から変わりません。ちょっと調べて見ましたが、どうもこれをUTF-8にするのは難しいようです。
仕方ないので、「どうせXAMPP環境で動かすのはテストの為だからパフォーマンスの低下など気にしない!」と妥協策を使用しました。

$format = '%Y年%m月%d日 %H時%M分';
echo strftime($format), PHP_EOL;
echo iconv('CP932', 'UTF-8', strftime(iconv('UTF-8', 'CP932', $format)));

出力結果は、

2010年02月%d日 11時%M分
2010年02月27日 11時59分

こんな感じです。iconv関数でフォーマットを事前にCP932に変換して、strftime関数で処理した後にまたUTF-8に戻すという強引な事やってます。
でも一応これで問題は回避できたかと。なんかもっといい方法ないものかなぁ。。。

Smartyのdate_format修飾子での対応

ここからオマケ。
もともとはSmarty使ってて発生した問題だったので(PHPコードで済ますならdate関数で十分だし)、上記の妥協案を利用したSmartyでの解決方法をご紹介。
pluginsディレクトリ内にあるmodifer.date_format.phpに下記の様に追記します。

function smarty_modifier_date_format($string, $format = '%b %e, %Y', $default_date = '')
{
    //
    // 省略
    //  
    if (DIRECTORY_SEPARATOR == '\\') {
        //
        // 省略
        //
        $format = str_replace($_win_from, $_win_to, $format);
        return iconv('CP932', 'UTF-8', strftime(iconv('UTF-8', 'CP932', $format), $timestamp));
    }
    return strftime($format, $timestamp);
}

とりあえずなんとかしたい人はお試しあれ。

スポンサーリンク
記事を書いた人

システムえんじにゃー🐈
趣味はエレキギター、自転車など。作曲したい。
World of Warshipsやってます。
記事に関する質問はお気軽にどうぞ。

surface0 (さーふぇす)をフォローする
surface0 (さーふぇす)をフォローする

コメント

タイトルとURLをコピーしました