2016-09-14 19 views
1

ネットワークタイムスタンプをNT形式で作成したいと思います。datetimeをWindows 64ビットに変換するFILETIME

私はこの機能を読める時間に変換することができました:

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'秒に変換する、反対のことをやってみたいです形式:

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

答えて

1

変換を一方向に行う方法を理解している場合は、基本的に逆の順序で各メソッドの逆を使用しています。ちょうどあなたが使用しているモジュール/クラスのドキュメントを見て:

  1. strftimeすることは、事前に3.3のPythonを使っているのであれば、timestampは存在しませんが、あなたが定義することができ(a strptime counterpart
  2. fromtimestampis matched by timestampを持っています手動FILETIMEとUnixは別途epoches間の差を調整することなく、直接FILETIMEエポックからの秒intを取得するためにint((mydatetime - FILETIME_epoch).total_seconds())を使用し、その後、あなたのタイムゾーンのためのFILETIMEエポックを表しdatetimeを事前計算する機能外FILETIME_epoch = datetime.datetime(1601, 1, 1) - datetime.timedelta(seconds=time.altzone if time.daylight else time.timezone)
  3. divmod(実際には不要ですが、剰余ではなく剰余ではなく、Epoch = (Ftime - 116444736000000000) // 10000000を実行して後で索引付けを避けることができます)は簡単に可逆です(掛け算と加算だけです。私のトリックは、#2)から直接FILETIMEエポック秒に変換する
  4. struct.unpackis matched by struct.pack

あなたが本当にこれらの事を自分で使用(し、必要に応じてドキュメントを読むことを学ばなければならないので、私は正確なコードを提供していませんよ) ;私はあなたのフォワードコードが、それが何をしているのか理解せずに書かれたと推測しています。すべてのステップには同じページに逆の説明があります。 datetime.datetimeにウィンドウのFILETIME値を変換

1

       あなたのコードでは、それは、それは可能性として(それはdivmod()結果の残りの部分を無視するため)があったかもしれない端数秒を切り捨てていますように正確ではありません。これは、コードが作成する読み取り可能な文字列では目に見えません。秒の小数が含まれている場合でも
       は、Windows FILETIME構造は、100ナノ秒(0.1マイクロ秒)の間隔で値を持っているので、あなたが欲しいものを正確に行うことはできませんが、Pythonのdatetimeは全体の精度をサポートしていますマイクロ秒。だから最善のことは、可能な最も正確な変換を行っても、この情報の損失が原因で元の値に近似していることです。

ここでは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" 
+0

OPは秒に切り捨てられたことを考えると、 100 nsの細分性の欠如は本当に重要ではありません。あなたはあなたが始めたものを得ることはできませんが、datetimeの制限のためではありません。 – ShadowRanger

+0

また、なぜ 'divmod'の後に' divmod'を元に戻すのでしょうか? 'quotient'、' remainder'と 'microsecs'を定義する2行を' microsecs'を直接計算する1行に置き換えることができます: 'microsecs =(winticks - WINDOWS_TICKS_TO_POSIX_EPOCH)/ WINDOWS_TICKS' – ShadowRanger

+0

@ShadowRanger:必要がないことを指摘してくれてありがとう「divmod」 - それは、自分自身のコードと違って、残りの部分を捨てず、より正確な変換を行う方法をOPに見せようとする私の遺物に過ぎませんでした。 0.1マイクロ秒の細分性が欠落しているかどうかについては、何らかの理由で開始したものとまったく同じ値を取得する必要がある場合があります。 – martineau

関連する問題