18

I want to convert 18 digit string from LDAP AccountExpires to Normal Date Time Format.

129508380000000000 >> May 26 2011

I got the above conversion from using the following link.

http://www.chrisnowell.com/information_security_tools/date_converter/Windows_active_directory_date_converter.asp?pwdLastSet,%20accountExpires,%20lastLogonTimestamp,%20lastLogon,%20and%20badPasswordTime

I tried to convert by using DateTime.Parse or Convert.ToDateTime. But no success.

Anyone know how to convert it? Thanks very much.

TTCG
  • 8,805
  • 31
  • 93
  • 141

8 Answers8

26

Edited answer

It's the number of ticks since Jan-01-1601 in UTC, according to Reference, which describes the significance of the year 1601. Good background reading.

var accountExpires = 129508380000000000;
var dt = new DateTime(1601, 01, 01, 0, 0, 0, DateTimeKind.Utc).AddTicks(accountExpires);

Original Accepted Answer

It's the number of ticks since Jan-02-1601.

DateTime dt = new DateTime(1601, 01, 02).AddTicks(129508380000000000);
agent-j
  • 27,335
  • 5
  • 52
  • 79
  • 2
    By the way, it seems to be in UTC time, but you'll want to make sure. – agent-j Jun 15 '11 at 15:39
  • Thanks very much. I'm wondering why Microsoft made it that difficult for the expire date. Puzzle... – TTCG Jun 15 '11 at 15:48
  • 2
    It is actually the number of ticks since 1601-01-01, not 1601-01-02. – Andy Hames Feb 16 '17 at 11:03
  • When I look at Active Directory Users & Computers at the "Account Expires" date, and compare it with this, I need to use 1600-12-30 to make it match. (then again, per the referenced article "It is common for the values to differ by a day, sometimes even two days.") – CJBS Oct 19 '18 at 18:32
23

You can use the FromFileTime method on the DateTime class, but watch out, when this field is set to not expire, it comes back as the Int64.MaxValue and doesn't work with either of these methods.

Int64 accountExpires = 129508380000000000;

DateTime expireDate = DateTime.MaxValue;

if (!accountExpires.Equals(Int64.MaxValue))
    expireDate = DateTime.FromFileTime(accountExpires);
Walk
  • 1,136
  • 8
  • 8
9

Some info for anyone who came here looking to set the AccountExpires value.

To clear the expiry is nice and easy:

entry.Properties["accountExpires"].Value = 0;

However if you try to directly write back an int64 / long:

entry.Properties["accountExpires"].Value = dt.ToFileTime();

You can get a 'COMException was unhandled - Unspecified error'

Instead write back the value as a string data type:

entry.Properties["accountExpires"].Value = dt.ToFileTime().ToString();

Be aware of the time of day you are setting, for consistancy with ADUC the time should be 00:00.

Instead of .Now or .UtcNow you can use .Today:

var dt1 = DateTime.Today.AddDays(90);
entry.Properties["accountExpires"].Value = dt1.ToFileTime().ToString();

Other input like dateTimePicker you can replace the time, Kind as Local for the Domain Controller:

var dt1 = dateTimePicker1.Value;
var dt2 = new DateTime(dt1.Year, dt1.Month, dt1.Day, 0, 0, 0, DateTimeKind.Local);
entry.Properties["accountExpires"].Value = dt2.ToFileTime().ToString();
WhoIsRich
  • 4,053
  • 1
  • 33
  • 19
2

For Ruby

def ldapTimeConverter(ldap_time)
  Time.at((ldap_time/10000000)-11644473600)
end
Rishabh Sairawat
  • 440
  • 6
  • 17
2

If you View Source on the link you posted you should see a Javascript conversion algorithm that should translate quite nicely to c#

DaveRead
  • 3,371
  • 1
  • 21
  • 24
  • Yeah, I noticed that. But I am wondering is there any better or direct way to convert it. Thanks for the advice. – TTCG Jun 15 '11 at 15:38
0

I stumbled across this working on a PowerShell script. I found I can query the accountexpirationdate property and no conversion is required.

northben
  • 5,448
  • 4
  • 35
  • 47
0

Someone had the "best" way above but when it's set to never expired, the value is zero.

public static DateTime GetAccountExpiresDate(DirectoryEntry de)
{
    long expires = de.properties["accountExpires"].Value;
    if (expires == 0)   // doesn't expire
        return DateTime.MaxValue;

    return DateTime.FromFileTime(expires);
}
BillJam
  • 221
  • 3
  • 13
0

I'll provide a perfect answer to this question using which you will be able to convert and DateTime to active directory long int format and will be also able to do the vice versa of it.

Here is a solution to it:-

To get DateTime from AD

string tickstring = de.Properties["accountExpires"][0].ToString();
long Ticks = (long) tickstring;

DateTime ReferenceDate = new DateTime(1601, 1, 1, 0, 0, 0, DateTimeKind.Utc);
long ExpireDateTicks = Ticks + ReferenceDate.Ticks;
DateTime ExpireDate = new DateTime(ExpireDateTicks);

To convert DateTime to AD long integer format

DateTime ReferenceDate = new DateTime(1601, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime ExpireDate = new DateTime(Request.EndDate.Year, Request.EndDate.Month, Request.EndDate.Day, 0, 0, 0);

long Ticks = ExpireDate.Ticks - ReferenceDate.Ticks;
NewUser.accountExpires = Ticks.ToString();