我正在通过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位时间戳的人。
答案 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位数字。