1

我想以 NT 格式创建网络时间戳。

我已经能够使用此功能将它们转换为可读时间:

NetworkStamp = "\xc0\x65\x31\x50\xde\x09\xd2\x01"

def GetTime(NetworkStamp):
    Ftime = int(struct.unpack('<Q',NetworkStamp)[0])
    Epoch = divmod(Ftime - 116444736000000000, 10000000)
    Actualtime = datetime.datetime.fromtimestamp(Epoch[0])
    return Actualtime, Actualtime.strftime('%Y-%m-%d %H:%M:%S')

print GetTime(NetworkStamp)

输出:

(datetime.datetime(2016, 9, 8, 11, 35, 57), '2016-09-08 11:35:57')

现在我想做相反的事情,将'2016/09/08 11:35:57'sec 转换为这种格式:

 "\xc0\x65\x31\x50\xde\x09\xd2\x01"
4

3 回答 3

2

如果您了解如何在一个方向上执行转换,那么反向执行基本上就是以相反的顺序使用每种方法的倒数。只需查看您正在使用的模块/类的文档:

  1. strftime对应strptime
  2. fromtimestamp 匹配timestamp(如果您使用的是 3.3 之前的 Python,timestamp则不存在,但您可以FILETIME_epoch = datetime.datetime(1601, 1, 1) - datetime.timedelta(seconds=time.altzone if time.daylight else time.timezone)在函数外部定义以预先计算datetime表示FILETIME您的时区的纪元的 a,然后用于直接int((mydatetime - FILETIME_epoch).total_seconds())获取int自纪元以来的秒数FILETIME,无需手动调整FILETIME和 Unix 纪元之间的区别)
  3. divmod(你并不真正需要,因为你只使用商,而不是余数,你可以这样做Epoch = (Ftime - 116444736000000000) // 10000000并避免稍后索引)是微不足道的可逆(只需乘法和加法,如果你使用我的技巧来转换,则加法是不必要的直接从 #2到FILETIME纪元秒)
  4. struct.unpack 被匹配struct.pack

我没有提供确切的代码,因为您确实应该自己学习使用这些东西(并在必要时阅读文档);我猜你的正向代码是在不理解它在做什么的情况下编写的,因为如果你理解它,反过来应该很明显;每一步都有一个逆记录在同一页面上。

于 2016-09-14T14:14:40.903 回答
1

    您将 Window 的FILETIME值转换为 adatetime.datetime的代码并不准确——它会截断可能存在的任何小数秒(因为它忽略了divmod()结果的其余部分)。这在您的代码创建的可读字符串中并不明显,因为它只显示整秒。
    即使包括小数秒,您也不能完全按照您的意愿行事,因为 WindowsFILETIME结构的值间隔为 100 纳秒(0.1 微秒),但 Pythondatetime仅支持精确到整微秒。因此,最好的办法是近似原始值,因为即使进行最准确的转换也会涉及到这种信息丢失。

这是 Python 2 和 3 的代码,使用NetworkStamp问题中的测试值演示了这一点:

import datetime
import struct
import time

WINDOWS_TICKS = int(1/10**-7)  # 10,000,000 (100 nanoseconds or .1 microseconds)
WINDOWS_EPOCH = datetime.datetime.strptime('1601-01-01 00:00:00',
                                           '%Y-%m-%d %H:%M:%S')
POSIX_EPOCH = datetime.datetime.strptime('1970-01-01 00:00:00',
                                         '%Y-%m-%d %H:%M:%S')
EPOCH_DIFF = (POSIX_EPOCH - WINDOWS_EPOCH).total_seconds()  # 11644473600.0
WINDOWS_TICKS_TO_POSIX_EPOCH = EPOCH_DIFF * WINDOWS_TICKS  # 116444736000000000.0

def get_time(filetime):
    """Convert windows filetime winticks to python datetime.datetime."""
    winticks = struct.unpack('<Q', filetime)[0]
    microsecs = (winticks - WINDOWS_TICKS_TO_POSIX_EPOCH) / WINDOWS_TICKS
    return datetime.datetime.fromtimestamp(microsecs)

def convert_back(timestamp_string):
    """Convert a timestamp in Y=M=D H:M:S.f format into a windows filetime."""
    dt = datetime.datetime.strptime(timestamp_string, '%Y-%m-%d %H:%M:%S.%f')
    posix_secs = int(time.mktime(dt.timetuple()))
    winticks = (posix_secs + int(EPOCH_DIFF)) * WINDOWS_TICKS
    return winticks

def int_to_bytes(n, minlen=0):  # helper function
    """ int/long to bytes (little-endian byte order).
        Note: built-in int.to_bytes() method could be used in Python 3.
    """
    nbits = n.bit_length() + (1 if n < 0 else 0)  # plus one for any sign bit
    nbytes = (nbits+7) // 8  # number of whole bytes
    ba = bytearray()
    for _ in range(nbytes):
        ba.append(n & 0xff)
        n >>= 8
    if minlen > 0 and len(ba) < minlen:  # zero pad?
        ba.extend([0] * (minlen-len(ba)))
    return ba  # with low bytes first

def hexbytes(s):  # formatting helper function
    """Convert string to string of hex character values."""
    ba = bytearray(s)
    return ''.join('\\x{:02x}'.format(b) for b in ba)

win_timestamp = b'\xc0\x65\x31\x50\xde\x09\xd2\x01'
print('win timestamp: b"{}"'.format(hexbytes(win_timestamp)))
dtime = get_time(win_timestamp)
readable = dtime.strftime('%Y-%m-%d %H:%M:%S.%f')  # includes fractional secs
print('datetime repr: "{}"'.format(readable))

winticks = convert_back(readable)  # includes fractional secs
new_timestamp = int_to_bytes(winticks)
print('new timestamp: b"{}"'.format(hexbytes(new_timestamp)))

输出:

win timestamp: b"\xc0\x65\x31\x50\xde\x09\xd2\x01"
datetime repr: "2016-09-08 07:35:57.996998"
new timestamp: b"\x80\x44\x99\x4f\xde\x09\xd2\x01"
于 2016-09-14T14:41:47.810 回答
-1

基本转换:

from datetime import datetime
from calendar import timegm

EPOCH_AS_FILETIME = 116444736000000000  # January 1, 1970 as MS file time
HUNDREDS_OF_NANOSECONDS = 10000000

def dt_to_filetime(dt):
    return EPOCH_AS_FILETIME + (timegm(dt.timetuple()) * HUNDREDS_OF_NANOSECONDS)

答案基于我发现的这个要点:https ://gist.github.com/Mostafa-Hamdy-Elgiar/9714475f1b3bc224ea063af81566d873

Gist 添加了对时区和另一个方向的转换的支持。

于 2020-07-18T20:10:33.067 回答