将18位LDAP/FILETIME时间戳转换为可读的日期

3
我已经从AD导出了一个用户列表,并需要验证他们的登录时间。
来自Powershell脚本的输出将最后一次登录给出为LDAP/FILE时间。
例如:130305048577611542
我遇到了将其转换为pandas中可读时间的问题。
我使用以下代码:
df['date of login'] = pd.to_datetime(df['FileTime'], unit='ns')
列 FileTime 包含上述 EXAMPLE 格式的时间。
在新列 date of login 中,我得到以下输出:
1974-02-17 03:50:48.577611542
当我在在线转换器上输入此日期时间时,我知道它被解析错误,因为我得到了以下输出:
Epoch/Unix时间:1386031258 GMT:2013年12月3日星期二上午12:40:58 您的时区:2013年12月2日星期一下午4:40:58 GMT-08:00
有人知道这里发生了什么事情吗?为什么我的所有日期都是在1970年代?

我认为这是 https://dev59.com/c1PTa4cB1Zd3GeqPnvCi 的重复。 - schlenk
可能是将64位Windows日期时间转换为Python的重复问题。 - schlenk
3个回答

9
18位活动目录时间戳(LDAP),也称为“Windows NT时间格式”,“Win32 FILETIME或SYSTEMTIME”或NTFS文件时间。这些用于Microsoft Active Directory的pwdLastSet、accountExpires、LastLogon、LastLogonTimestamp和LastPwdSet。该时间戳是自1601年1月1日UTC以来的100纳秒间隔数(1纳秒=十亿分之一秒)。因此,130305048577611542确实与2013年12月3日有关。当将此值通过Python中的日期时间函数时,它会将该值截断为九位数字。因此,时间戳变为130305048,并从1970年1月1日开始计算,这导致一个1974年的日期!为了获得正确的Unix时间戳,您需要执行:(130305048577611542 / 10000000) - 11644473600

2

这是我用Python编写的解决方案,对我来说效果很好:

import datetime

def ad_timestamp(timestamp):
    if timestamp != 0:
        return datetime.datetime(1601, 1, 1) + datetime.timedelta(seconds=timestamp/10000000)
    return np.nan

那么,如果您需要转换Pandas列:
df.lastLogonTimestamp = df.lastLogonTimestamp.fillna(0).apply(ad_timestamp)

注意:在使用apply之前,我需要使用fillna。另外,由于我填充了0,因此在转换函数中检查了它,即if timestamp != 0。希望这有意义。这是额外的内容,但您可能需要它来转换相关列。

1

我被卡在这个问题上已经几天了。但现在我准备分享一个真正可行的解决方案,以更易于使用的形式呈现:

import datetime
timestamp = 132375402928051110
value = datetime.datetime (1601, 1, 1) +   
datetime.timedelta(seconds=timestamp/10000000) ### combine str 3 and 4  
print(value.strftime('%Y-%m-%d %H:%M:%S'))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接