28
3月
1

厄介なActiveDirectoryの日付


LINUXなWEBサーバーからLdapを使用してWindows 2003 Server上のActiveDirectoryに接続して、lockoutTimeやlastLogon等の日付を取得してきて、これらをブラウザ上から確認できるようにするPHPスクリプトを仕事で作成したのですが、これがまぁかなりの曲者だったので参考になればと思いここでちょっと紹介したいと思います。

なにが曲者なのかと言いますと、Windows 2003 ServerのActiveDirectory(Windowsすべての日付がそうなのかは不明ですが)上の日付というのは1601年1月1日から100ナノ秒(10000000分の1秒?)間隔というワケのワカラン仕様なのです・・・詳細はコチラ

(´A`).。oO(1601年から起算していったい何がしたいんだろう)

つまりPHPでこれを正しい日付で表示するにはtime()関数の1970年1月1日からの秒(SEC)に変換すればよいので、
・取得した日付を秒(SEC)に変換
・秒(SEC)に変換した日付から1601年1月1日から1969年12月31日までの秒(SEC)を引く
という処理が必要なのです。

●取得した日付を秒(SEC)に変換
$lastLogon = $ATTRS[“lastLogon”][0]; //ActiveDirectoryからlastLogonを取得
$lastLogon = floor($lastLogon / 10000000); //lastLogonを秒(SEC)に変換して小数点以下を切り捨て

●秒(SEC)になった$lastLogonから1601年1月1日から1969年12月31日までの秒(SEC)を引く
$lastLogon = $lastLogon – 11644473600;

11644473600という数字が1601年1月1日から1969年12月31日までの秒(SEC)です。
これの算出方法は過去にCmfDiaryのカレンダー機能でその年が閏年かどうかを判定する手法を取り入れたことがあったので、これを応用しました。

閏年は
・4で割り切れて100で割り切れない
・400で割り切れる
というのが条件です。

PHPで書くとこんな感じ
for($SEC = 0,$C = 1601; $C < 1970; $C++) {   $SEC += 60 * 60 * 24 * (365 + (($C % 4 == 0 and $C % 100 != 0) or $C % 400 == 0)); } で最後に $lastLogon = date("Y/m/d H:i:s",$lastLogon); とすれば正しい日付に変換することができます。 面倒くさい仕様だな〜もう・・・(A`)

Enjoyed reading this post?
Subscribe to the RSS feed and have all new posts delivered straight to you.
1 Comment:
  1. uryossa 10 11月, 2016

    11644473600の検算のためにやってみました。

    $ date -d “1601/1/1 00:00:00 GMT” “+%s”
    -11644473600

Post your comment



now loading...