在Java中使用MS的Integer8 / LargeInteger?

时间:2011-03-03 17:47:01

标签: java active-directory ldap

我正在通过LDAP(使用Spring LDAP)处理AD,并且在使用Integer8 / LargeInteger作为outlined here的时间戳时遇到了一个奇怪的问题。也就是说,我尝试写入该类型的字段导致......

  

格式错误的'字段名称'属性值

我已经尝试过将Longs和Strings放在希望底层实现可以进行任何所需的转换但没有运气的情况下。这就是我在做数学的方法......

/* AD Keeps track of time in 100 NS intervals (UTC) since Jan 1st 1601 */
long   winEpocMS    = new GregorianCalendar(1601, Calendar.JANUARY, 1).getTimeInMillis();        
long   nowMS        = System.currentTimeMillis();
long   winTime100NS = (nowMS - winEpocMS) * 10000;

是否有一种简单/优雅的方式来正确打包这些数据?是否有任何预编译的Java库来处理读/写这些相当奇怪的时间值?

奖励指向任何可以解释为什么我们需要在100NS分辨率下获得64位时间戳的人。

2 个答案:

答案 0 :(得分:3)

好的,这是故障......

/* time since Jan 1st 1601 00:00:00 UTC */
final long WIN_EPOC_MS = 11644473600000L;
final long now_ms      = System.currentTimeMillis();
final long now_win_ns  = (now_ms + WIN_EPOC_MS) * 10000L;

从上面的代码可以看出反过来。如果要仔细检查转换,请使用w32tm。例如,以下显示我们有正确的转换时间到Unix epoc(注意我在CST)

  

w32tm / ntte 116444736000000000
  134774 00:00:00.0000000 - 12/31/1969   06:00:00 PM(当地时间)

最后,在使用AD时,请确保该字段接受任何值。有些字段用“-1”表示“现在”,“0”表示特殊含义。此外,在某些情况下,时间属性修改是否与其他属性修改(例如pwdLastSet和unicodePwd)捆绑在一起似乎很重要。

最后一点,我会避免使用GregorianCalendar,除非你知道你的时区是正确的(很容易搞砸)。

答案 1 :(得分:1)

我不知道任何使用Microsoft特定格式处理时间的Java库(自1601年以来的100纳秒间隔)。我认为这种方式是正确的 您可以将winEpocMS定义为常量并使用:

long winTime100NS = (System.currentTimeMillis() - winEpocMS) * 10000L;

为什么我们需要64位时间戳很简单。 32位你有2 ^ 32个值(大约4,000,000,000),足以处理从1970年到2038年的秒数(知道对Unix的2000年影响)。如果您需要微秒或100纳秒的精度,则使用必须作为64位数管理的较大值。 Java自1970年以来使用毫秒来表示日期,并且需要long类型,这是一个带符号的64位数字。