在解析 LDAP 日期和时间戳时设置与 GMT 不一致的时区
Inconsistent Timezones with GMT set in parsing LDAP date and Timestamps
我正在解析 AD 中的时间。有两种格式,即YMD LDAP timestamps for whenCreated, whenChanged, 18-digit LDAP/FILETIME timestamps for lastLogonTimestamp, pwdLastSet等。因为我需要按时间分析数据。获取当地时间是有意义的。这是我为解析两种不同格式而编写的两个函数。我从 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);
}
我有一个例子20150520143936.0Z,转换为“2015-05-20 16:39:36”。
对于示例 131097986571852097,它被转换为“2016-06-07 18:44:17”,而 http://www.epochconverter.com/ldap 告诉我这是 GMT 时间,当地时间是“2016-06-07 20:44:17”。如果我注释设置时区的代码,我将获得当地时间。
所以现在我很困惑,sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
给我本地时区或世界时。我在想,如果 AD 在世界时存储 whenCreated,在本地时间存储 lastLogonTimestamp。但是在函数中我将它们解析为字符串。没有关于时区的符号。如果我在第二个函数中注释这句话,当我在另一个地方访问 LDAP Directory 时,我会得到两个属性的本地时间吗?
在第二种情况下,您正在构造一个 Date
,然后告诉它 format 那个 UTC 日期 - 而在第一种情况下,您是解析 为 UTC,但格式化为本地时间。您已经假设时间戳存储为自 Unix 纪元以来的刻度数,这是一种时区中性格式。
如果目标是在本地时间生成字符串表示,那么您应该删除 sdf.setTimeZone
调用。我认为无论如何 parse
方法应该是 returning Date
,而不是 String
。或者更好的是,return一个java.time.Instant
...
我正在解析 AD 中的时间。有两种格式,即YMD LDAP timestamps for whenCreated, whenChanged, 18-digit LDAP/FILETIME timestamps for lastLogonTimestamp, pwdLastSet等。因为我需要按时间分析数据。获取当地时间是有意义的。这是我为解析两种不同格式而编写的两个函数。我从 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);
}
我有一个例子20150520143936.0Z,转换为“2015-05-20 16:39:36”。 对于示例 131097986571852097,它被转换为“2016-06-07 18:44:17”,而 http://www.epochconverter.com/ldap 告诉我这是 GMT 时间,当地时间是“2016-06-07 20:44:17”。如果我注释设置时区的代码,我将获得当地时间。
所以现在我很困惑,sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
给我本地时区或世界时。我在想,如果 AD 在世界时存储 whenCreated,在本地时间存储 lastLogonTimestamp。但是在函数中我将它们解析为字符串。没有关于时区的符号。如果我在第二个函数中注释这句话,当我在另一个地方访问 LDAP Directory 时,我会得到两个属性的本地时间吗?
在第二种情况下,您正在构造一个 Date
,然后告诉它 format 那个 UTC 日期 - 而在第一种情况下,您是解析 为 UTC,但格式化为本地时间。您已经假设时间戳存储为自 Unix 纪元以来的刻度数,这是一种时区中性格式。
如果目标是在本地时间生成字符串表示,那么您应该删除 sdf.setTimeZone
调用。我认为无论如何 parse
方法应该是 returning Date
,而不是 String
。或者更好的是,return一个java.time.Instant
...