[php][PEAR]Date_Holidays_Driver::setYear()が変

カテゴリ: php / author: uechoco / 2008年05月11日 03:39:33
この記事を読む時間:173くらい

正確に言うと、Date_Holidays_Driver_Japanese::setYear()の挙動が変。

※PEAR::Date_Holidays_Driver_Japanese 0.2.2がリリースされました。下記不具合を包括的に解決しています。0.2.0以前を使用してる方は、アップグレードすることを強くお勧めします。

PEAR::Date_Holidays_Driver_Japanese 0.2.2 - Do You PHP はてな

Date_Holidaysクラスのfactory()メソッドはDriver名を指定するのと同時に、西暦を指定して祝日リストを生成します。西暦を指定していない場合は、内部で自動的に現在の西暦が採用されます。もし西暦が違う祝日を一緒に扱う場合(たとえば2008年と2009年)、ドライバをもう1度生成し、翻訳ファイルを登録しなければなりません。

それは面倒だと思って、APIドキュメントをあさっていると、Date_Holidays_Driver::setYear()というメソッドを見つけました。どうやら、西暦をセットしなおした上で祝日の再構築を行ってくれるようです。エンドユーザー・マニュアルがないので100%とは言い切れませんが、ソースコードからはそう判断できます。

で、早速使ってみたソースコードがこちら。

php:
  1. /**
  2. * Date_Holidays_Driver_Japanseを用いて
  3. * 祝日名を取得する(挙動がおかしい)
  4. *
  5. * 2008/05/11
  6. *
  7. * Author:   uechoco
  8. * 動作確認: PHP 5.2.5
  9. * require:  Date_Holidays (推奨バージョン:0.18.0)
  10. * require:  Date_Holidays_Driver_Japanese 0.2.0
  11. *
  12. */
  13.  
  14. // Date_Holidaysクラスの読み込み
  15. require_once "Date/Holidays.php";
  16.  
  17. // 言語ファイルの読み込み(PEARのdataディレクトリ内)
  18. define('LANG_FILE', 'C:/php5/pear/data/Date_Holidays_Driver_Japanese/lang');
  19.  
  20. // Date_Holidaysオブジェクトの生成(西暦を省略すると現在の西暦になる)
  21. $obj =& Date_Holidays::factory('Japanese');
  22. if (Date_Holidays::isError($obj)) {
  23. die('Factory was unable to produce driver-object');
  24. }
  25.  
  26. // 翻訳ファイルをロケール=ja_JPとして登録
  27. $obj->addTranslationFile(LANG_FILE . '/Japanese/ja_JP.xml', 'ja_JP');
  28. if (Date_Holidays::isError($obj)) {
  29. die($obj->getMessage());
  30. }
  31.  
  32. $lastYear = 0;
  33. $beginTime = mktime(0, 0, 0, 1, 1, 2008);
  34. for ($i = 0; $i <731; $i++) {
  35. $t = $beginTime + $i * 86400;
  36. $d = strftime('%Y-%m-%d', $t);
  37. // 西暦が更新されたら祝日の再構成
  38. $y = strftime('%Y', $t);
  39. if ($lastYear != $y) {
  40. $obj->setYear(intval($y));
  41. $lastYear = $y;
  42. //デバッグ用にオブジェクトを直接吐く
  43. //echo "
  44.  
  45. <hr /><span style="color: red;">\n\n";
  46. //print_r($obj-&gt;_internalNames);
  47. //echo "</span>
  48.  
  49. <hr />\n\n";
  50.  
  51. }
  52.  
  53. $holiday = $obj-&gt;getHolidayForDate($d, 'ja_JP');
  54. if (!is_null($holiday))
  55. printHolidayInfo($holiday, $d);
  56. }
  57.  
  58. function printHolidayInfo($holiday, $date = '')
  59. {
  60. echo $date . " =========
  61. \n";
  62. printf("名前:%s
  63. \n", $holiday-&gt;getTitle());
  64. //printf("内部名:%s
  65. \n", $holiday-&gt;getInternalName());
  66. //printf("プロパティ:%s
  67. \n", print_r($holiday-&gt;getProperties(), true));
  68. //printf("Dateクラス:%s
  69. \n", print_r($holiday-&gt;getDate(), true));
  70. }
  71. exit;
  72. ?&gt;

で、出力結果がこちら。

CODE:
  1. 2008-01-01 =========
  2. 名前:元日
  3. 2008-01-14 =========
  4. 名前:成人の日
  5. 2008-02-11 =========
  6. 名前:建国記念の日
  7. 2008-03-20 =========
  8. 名前:春分の日
  9. 2008-04-29 =========
  10. 名前:昭和の日
  11. 2008-05-03 =========
  12. 名前:憲法記念日
  13. 2008-05-04 =========
  14. 名前:みどりの日
  15. 2008-05-05 =========
  16. 名前:こどもの日
  17. 2008-07-21 =========
  18. 名前:海の日
  19. 2008-09-15 =========
  20. 名前:敬老の日
  21. 2008-09-23 =========
  22. 名前:秋分の日
  23. 2008-10-13 =========
  24. 名前:体育の日
  25. 2008-11-03 =========
  26. 名前:文化の日
  27. 2008-11-23 =========
  28. 名前:勤労感謝の日
  29. 2008-12-23 =========
  30. 名前:天皇誕生日
  31. 2009-01-01 =========
  32. 名前:元日
  33. 2009-01-12 =========
  34. 名前:成人の日
  35. 2009-02-11 =========
  36. 名前:建国記念の日
  37. 2009-03-20 =========
  38. 名前:春分の日
  39. 2009-04-29 =========
  40. 名前:昭和の日
  41. 2009-05-03 =========
  42. 名前:憲法記念日
  43. 2009-05-04 =========
  44. 名前:みどりの日
  45. 2009-05-05 =========
  46. 名前:こどもの日
  47. 2009-07-20 =========
  48. 名前:海の日
  49. 2009-09-21 =========
  50. 名前:敬老の日
  51. 2009-09-23 =========
  52. 名前:秋分の日
  53. 2009-10-12 =========
  54. 名前:体育の日
  55. 2009-11-03 =========
  56. 名前:文化の日
  57. 2009-11-23 =========
  58. 名前:勤労感謝の日
  59. 2009-12-23 =========
  60. 名前:天皇誕生日

パッと見でよさそうに見えますが、よく見てみると、振替休日と国民の休日が表示されていないことに気がつきます。動作確認環境はWindows/XAMPP PHP5.2.5です。

少しだけ動作確認してみました。

★まず、オブジェクトを西暦が変わるたびに生成しなおすと、正常な結果になります。

php:
  1. $lastYear = 0;
  2. $beginTime = mktime(0, 0, 0, 1, 1, 2008);
  3. for ($i = 0; $i &lt;731; $i++) {
  4. $t = $beginTime + $i * 86400;
  5. $d = strftime('%Y-%m-%d', $t);
  6. // 西暦が更新されたら祝日の再構成
  7. $y = strftime('%Y', $t);
  8. if ($lastYear != $y) {
  9. // 西暦を指定してDate_Holidaysオブジェクトの生成
  10. $obj =&amp; Date_Holidays::factory('Japanese', $y);
  11. if (Date_Holidays::isError($obj)) {
  12. die('Factory was unable to produce driver-object');
  13. }
  14. // 翻訳ファイルをロケール=ja_JPとして登録
  15. $obj-&gt;addTranslationFile(LANG_FILE . '/Japanese/ja_JP.xml', 'ja_JP');
  16. if (Date_Holidays::isError($obj)) {
  17. die($obj-&gt;getMessage());
  18. }
  19. $lastYear = $y;
  20. }
  21. $holiday = $obj-&gt;getHolidayForDate($d, 'ja_JP');
  22. if (!is_null($holiday))
  23. printHolidayInfo($holiday, $d);
  24. }

★setYear()の直後に、$obj->_internalNamesを吐き出してみると、serYear()する度に$_internalNames配列が初期化されておらず、末尾に追加されていることがわかります。おそらく、$objに含まれる他のプロパティにも似たような現象が見られるかもしれません。

CODE:
  1. Array
  2. (
  3. [0] =&gt; newYearsDay
  4. [1] =&gt; comingOfAgeDay
  5. [2] =&gt; nationalFoundationDay
  6. [3] =&gt; Vernal Equinox Day
  7. [4] =&gt; showaDay
  8. [5] =&gt; constitutionMemorialDay
  9. [6] =&gt; greeneryDay
  10. [7] =&gt; childrensDay
  11. [8] =&gt; marineDay
  12. [9] =&gt; respectfortheAgedDay
  13. [10] =&gt; autumnalEquinoxDay
  14. [11] =&gt; healthandSportsDay
  15. [12] =&gt; nationalCultureDay
  16. [13] =&gt; laborThanksgivingDay
  17. [14] =&gt; emperorsBirthday
  18. [17] =&gt; newYearsDay
  19. [18] =&gt; comingOfAgeDay
  20. [19] =&gt; nationalFoundationDay
  21. [20] =&gt; Vernal Equinox Day
  22. [21] =&gt; showaDay
  23. [22] =&gt; constitutionMemorialDay
  24. [23] =&gt; greeneryDay
  25. [24] =&gt; childrensDay
  26. [25] =&gt; marineDay
  27. [26] =&gt; respectfortheAgedDay
  28. [27] =&gt; autumnalEquinoxDay
  29. [28] =&gt; healthandSportsDay
  30. [29] =&gt; nationalCultureDay
  31. [30] =&gt; laborThanksgivingDay
  32. [31] =&gt; emperorsBirthday
  33. [32] =&gt; substituteHolidayForgreeneryDay
  34. [33] =&gt; substituteHolidayForlaborThanksgivingDay
  35. )
  36. Array
  37. (
  38. [0] =&gt; newYearsDay
  39. [1] =&gt; comingOfAgeDay
  40. [2] =&gt; nationalFoundationDay
  41. [3] =&gt; Vernal Equinox Day
  42. [4] =&gt; showaDay
  43. [5] =&gt; constitutionMemorialDay
  44. [6] =&gt; greeneryDay
  45. [7] =&gt; childrensDay
  46. [8] =&gt; marineDay
  47. [9] =&gt; respectfortheAgedDay
  48. [10] =&gt; autumnalEquinoxDay
  49. [11] =&gt; healthandSportsDay
  50. [12] =&gt; nationalCultureDay
  51. [13] =&gt; laborThanksgivingDay
  52. [14] =&gt; emperorsBirthday
  53. [17] =&gt; newYearsDay
  54. [18] =&gt; comingOfAgeDay
  55. [19] =&gt; nationalFoundationDay
  56. [20] =&gt; Vernal Equinox Day
  57. [21] =&gt; showaDay
  58. [22] =&gt; constitutionMemorialDay
  59. [23] =&gt; greeneryDay
  60. [24] =&gt; childrensDay
  61. [25] =&gt; marineDay
  62. [26] =&gt; respectfortheAgedDay
  63. [27] =&gt; autumnalEquinoxDay
  64. [28] =&gt; healthandSportsDay
  65. [29] =&gt; nationalCultureDay
  66. [30] =&gt; laborThanksgivingDay
  67. [31] =&gt; emperorsBirthday
  68. [34] =&gt; newYearsDay
  69. [35] =&gt; comingOfAgeDay
  70. [36] =&gt; nationalFoundationDay
  71. [37] =&gt; Vernal Equinox Day
  72. [38] =&gt; showaDay
  73. [39] =&gt; constitutionMemorialDay
  74. [40] =&gt; greeneryDay
  75. [41] =&gt; childrensDay
  76. [42] =&gt; marineDay
  77. [43] =&gt; respectfortheAgedDay
  78. [44] =&gt; autumnalEquinoxDay
  79. [45] =&gt; nationalHolidayBeforeAutumnalEquinoxDay
  80. [46] =&gt; healthandSportsDay
  81. [47] =&gt; nationalCultureDay
  82. [48] =&gt; laborThanksgivingDay
  83. [49] =&gt; emperorsBirthday
  84. [50] =&gt; substituteHolidayForconstitutionMemorialDay
  85. )

setYear()を使うと振替休日と国民の休日だけ表示されないので、Date_Holidays_Driver_Japaneseがおかしいのかな?って思ったりもしたんですが、内部名が初期化されていないのはDate_Holidays_Driverもおかしい気がしないでもないのですが、今眠くて深追いする気が起きません(ぉぃ。

解決策としては、西暦が変わったら、オブジェクトを新規に生成しなおすのが早そうです。


コメントはまだありません »

コメントはまだありません。

この投稿へのコメントの RSS フィード。 TrackBack URI

コメントする

Copyright © 2012 うえちょこ@ぼろぐ. WP Theme created by Web Top.