Inconsistent Timezones with GMT set in parsing LDAP date and Timestamps

I'm parsing the times from AD. There are two formats, i.e., YMD LDAP timestamps for whenCreated, whenChanged, 18-digit LDAP/FILETIME timestamps for lastLogonTimestamp, pwdLastSet, etc. Because I need to analyze the data upon the time. It makes sense to get local time. Here are the two functions that I wrote to parse the two different formats. The calculation in the second function I referenced from Convert 18-digit LDAP Timestamps To Human Teadable Date Using Java

public static String parseLdapDate(String ldapDate) {
    String[] parts = ldapDate.split("[.]");
    String dateTimePart = parts[0];  //take the date string before .0Z
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
    sdf.setTimeZone(TimeZone.getTimeZone("GMT"));  //Z means UTC time, to the local timezone
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 

    try {
        Date tempDate = sdf.parse(dateTimePart); //parse the string to a date
        return formatter.format(tempDate);  //format it as what we want
    } catch (ParseException ex) {
        System.out.println("Parsing LDAP Date exception \n");
        ex.printStackTrace();
    }
    return null;
}

public static String parseLdapTimestamp(String ldapTimestamp) {
    long nanoseconds = Long.parseLong(ldapTimestamp);  // 100 nanoseconds 
    long mills = (nanoseconds/10000000);  // To seconds
    long unix = (((1970-1601)*365)-3+Math.round((1970-1601)/4))*86400L;
    long timeStamp = mills - unix;

    Date date = new Date(timeStamp*1000L); // To milliseconds
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("GMT")); 

    return sdf.format(date);
}

I have an example 20150520143936.0Z, which is converted to "2015-05-20 16:39:36". For the example 131097986571852097, it is converted to "2016-06-07 18:44:17", while http://www.epochconverter.com/ldap tells me that it's the GMT time and the local time is "2016-06-07 20:44:17". I will get the local time if I comment the code of setting timezone.

So now I'm confused, sdf.setTimeZone(TimeZone.getTimeZone("GMT")); gives me local timezone or the universal time. I was thinking if AD stores whenCreated in the universal time, lastLogonTimestamp in local time. But in the functions I parse them as strings. There is no symbol about the timezone. If I comment this sentence in the second function, will I get local time for both attributes when I access an LDAP Directory in another place.

Jon Skeet
people
quotationmark

In the second case, you're constructing a Date and then telling it to format that date in UTC - whereas in the first case, you're parsing it in UTC, but formatting it in local time. You're already assuming that the timestamp is stored as a number of ticks since the Unix epoch, which is a time zone neutral format.

If the aim is to produce a string representation in local time, then you should remove the sdf.setTimeZone call. I would argue that a parse method should be returning a Date anyway though, rather than a String. Or better yet, return a java.time.Instant...

people

See more on this question at Stackoverflow