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

macのPHPのstrptimeの挙動がおかしい

strptime関数を使って「20081122」のように区切りのない日付文字列を「%Y%m%d」というフォーマット文字列で解析したところ以下のような結果に。
Linux

  • 2008年11月22日

mac

  • 20081122年・・・?

Linux

[mikeda@cent ~]$ php -v
PHP 5.2.6 (cli) (built: Nov 16 2008 01:09:46) 
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies

配列として取り出し。

[mikeda@cent ~]$ php -r 'print_r(strptime("20081122","%Y%m%d"));'
Array
(
    [tm_sec] => 0
    [tm_min] => 0
    [tm_hour] => 0
    [tm_mday] => 22
    [tm_mon] => 10
    [tm_year] => 108
    [tm_wday] => 6
    [tm_yday] => 326
    [unparsed] => 
)

出力。

[mikeda@cent ~]$ php -r 'extract(strptime("20081122","%Y%m%d"));
printf("%4d.%02d.%02d\n",$tm_year+1900 ,$tm_mon+1,$tm_mday);'
2008.11.22

あぶれたものはunparsedに入る。

[mikeda@cent ~]$ php -r 'print_r(strptime("20081122","%Y"));'
Array
(
    [tm_sec] => 0
    [tm_min] => 0
    [tm_hour] => 0
    [tm_mday] => 0
    [tm_mon] => 0
    [tm_year] => 108
    [tm_wday] => 1
    [tm_yday] => -1
    [unparsed] => 1122
)

mac

mini:~ mikeda$ php -v
PHP 5.2.6 (cli) (built: Jul 17 2008 23:04:49) 
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies

あれ、なにも表示されない。

mini:~ mikeda$ php -r 'print_r(strptime("20081122","%Y%m%d"));'

%Yが全部のみこんで年数が西暦20081122になってる・・・?

mini:~ mikeda$ php -r 'print_r(strptime("20081122","%Y"));'
Array
(
    [tm_sec] => 0
    [tm_min] => 0
    [tm_hour] => 0
    [tm_mday] => 0
    [tm_mon] => 0
    [tm_year] => 20079222
    [tm_wday] => 0
    [tm_yday] => 0
    [unparsed] => 
)

どうもstrftime()やstrptime()の実装はCライブラリに丸投げされている模様。
Cで動作確認プログラムを書いてみる。

#include <time.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
  char* str="20081122";
  struct tm* t;

  t = (struct tm*)malloc(sizeof(struct tm));
  strptime(str, "%Y%m%d", t);
  printf("%d.%d.%d\n", t->tm_year+1900, t->tm_mon+1, t->tm_mday);

  return 0;
}


Linuxで実行

[mikeda@cent c]$ ./a.out 
2008.11.22

macで実行

mini:c mikeda$ ./a.out 
20081122.1.0


はい、挙動が違う。ライブラリのバージョンの問題かな。
Windowsだと使用できるフォーマット指定子なんかも違うらしいし、
おとなしくgetdate()とdate()使うが吉。
(長々と書いたのにw)

[mikeda@cent ~]$ php -r 'echo date("Y.m.d\n", strtotime("20090101"));'
2009.01.01
[mikeda@cent ~]$ php -r 'print_r(getdate(strtotime("20090122")));'
Array
(
    [seconds] => 0
    [minutes] => 0
    [hours] => 0
    [mday] => 22
    [wday] => 4
    [mon] => 1
    [year] => 2009
    [yday] => 21
    [weekday] => Thursday
    [month] => January
    [0] => 1232550000
)