7

I have an intranet running on a linux box, which authenticates against Active Directory on a Windows box, using LDAP through PHP.

I can retrieve a user's entry from AD using LDAP and access the last login date from the php array eg:

echo $adAccount['lastlogontimestamp'][0]; // returns something like 129802528752492619

If this was a Unix timestamp I would use the following PHP code to convert to a human readable date:

date("d-m-Y H:i:s", $lastlogontimestamp);

However, this does not work. Does anyone know how I can achieve this or indeed if it is possible to do so from a Linux box?

Terry Gardner
  • 10,957
  • 2
  • 28
  • 38
amburnside
  • 1,943
  • 5
  • 24
  • 43

2 Answers2

18

According to this, the windows timestamp you have there is the number of 100-ns since Jan 1st 1601. Therefore, you could just convert it to a unix timestamp using the following formula:

tUnix = tWindow/(10*1000*1000)-11644473600;

You divide by 10*1000*1000 to convert to seconds since Jan 1st 1601 and then you discount 11644473600 which is the number of seconds between Jan 1601 and Jan 1970 (unix time).

So in PHP:

date("d-m-Y H:i:s", $lastlogontimestamp/10000000-11644473600);

EDIT: Interestingly, I got a different offset than Baba. I got mine with Java:

Calendar date1 = Calendar.getInstance(); date1.set(1601, 1, 1);
Calendar date2 = Calendar.getInstance(); date2.set(1970, 1, 1);
long dt = date2.getTimeInMillis() - date1.getTimeInMillis();
System.out.println(String.format("%f", dt / 1000.0)); // prints "11644473600.000000"

According to this SO: Ways to Convert Unix/Linux time to Windows time my offset is correct.

Community
  • 1
  • 1
brimborium
  • 9,362
  • 9
  • 48
  • 76
  • 4
    I got a different offset with PHP: strtotime("1601-01-01") - strtotime("1970-01-01") = 11644470000. This is an hour (3600 seconds) different to yours, but as MSDN says to use your Java derived value I will use your answer. Thank you for your assistance and thank you to Baba. – amburnside May 02 '12 at 11:31
  • 2
    I’ve also seen 11644477200 (as Baba used). That’s at least three different values. Granted, the difference isn’t huge and may not matter in some contexts, but it’s good to know what the correct value to subtract should be regardless of time-zone. I’m going to go with the `…7360…` value as [seen in the MSDN](http://msdn.microsoft.com/en-us/library/ms724228). – Synetech Sep 08 '13 at 00:53
  • 1
    @Synetech Yeah, the whole date thing is a bloody mess. It always depends on which system you are using. – brimborium Sep 10 '13 at 09:12
7

Since windows is not in seconds but in nano seconds you need to round it up by dividing it by 10000000 you also need to remove seconds between 1601-01-01 and 1970-01-01since windows timestamp start from 1601-01-01

function convertWindowsTimestamp($wintime) {
   return $wintime / 10000000 - 11644477200;
}

$lastlogontimestamp = convertWindowsTimestamp("129802528752492619");
$date = date("d-m-Y H:i:s", $lastlogontimestamp);
var_dump($date);

Output

string '30-04-2012 10:47:55' (length=19)
Baba
  • 94,024
  • 28
  • 166
  • 217