-1

I'm trying to calculate LDAP accountExpires. The given value is LDAP date - nanoseconds since 01/01/1601 00:00.

What is the best way to test if it is indeed after new Date()?

Nati
  • 1,034
  • 5
  • 19
  • 46
  • What did your search and research bring up? What have you tried? – Ole V.V. Jun 25 '17 at 12:09
  • Accorinding to [this page](https://www.epochconverter.com/ldap) the LDAP time is really in 100-nanoseconds intervals. Do you know whether this is correct for the number you have got? Could you give an example input and desired output? – Ole V.V. Jun 25 '17 at 12:12
  • @OleV.V. - a very unfriendly way... convert the attribute value to milliseconds, then create a `Date` with Jan-01-1601, then add the ms to that date, and then check if `after()` now... – Nati Jun 25 '17 at 12:13

1 Answers1

2

The best way probably depends on your precision requirements. I suggest

private static final Instant ldapEpoch = LocalDateTime.of(1601, Month.JANUARY, 1, 0, 0)
                                .atOffset(ZoneOffset.UTC)
                                .toInstant();

and then

long ldapTime = 131_428_662_140_000_000L;
Instant convertedTime = ldapEpoch.plusMillis( ldapTime / 10_000L );
System.out.println(convertedTime.isAfter(Instant.now()));

With my example LDAP time value this produces an Instant of 2017-06-25T12:10:14Z and prints false because the time is not after the current time.

Since you mentioned new Date() in the question, I assumed that the precision of Date would suffice for you, that is, milliseconds. I would really have loved to do ldapEpoch.plusNanos(ldapTime * 100) to keep the full precision, but this overflows the Java long data type and therefore gives an incorrect result. If you need the full precision, … Edit: as suggested by Basil Bourque in a comment, slice off the fractional second, work in whole seconds, then add back your fractional second:

    Instant convertedTime = ldapEpoch.plusSeconds( ldapTime / 10_000_000L )
                                    .plusNanos( ldapTime % 10_000_000L * 100L );

(The way I had first presented works too, gives the same result; but the edited version may be more natural to readers who know the Java date & time API (and may also perform a slight bit better, but that’s hardly critical).)

Why I wanted to multiply by 100? The LDAP, Active Directory & Filetime Timestamp Converter I found says “The timestamp is the number of 100-nanoseconds intervals (1 nanosecond = one billionth of a second) since Jan 1, 1601 UTC.”

Beware that in 1601 not everyone agreed about calendars, so January 1 that year is ambiguous. Most computer software assumes the Gregorian calendar, so I guess the definition of LDAP time does too, it’s not something I know.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 1
    To keep the full precision, slice off the fractional second, then work in whole seconds. To that result, add back your fractional second. This is how java.time classes work internally : whole seconds *plus* a fraction of a second as nanoseconds. – Basil Bourque Jun 25 '17 at 15:59