-
-
Save Mostafa-Hamdy-Elgiar/9714475f1b3bc224ea063af81566d873 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python | |
# Copyright (c) 2009, David Buxton <[email protected]> | |
# All rights reserved. | |
# | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions are | |
# met: | |
# | |
# * Redistributions of source code must retain the above copyright | |
# notice, this list of conditions and the following disclaimer. | |
# * Redistributions in binary form must reproduce the above copyright | |
# notice, this list of conditions and the following disclaimer in the | |
# documentation and/or other materials provided with the distribution. | |
# | |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
"""Tools to convert between Python datetime instances and Microsoft times. | |
""" | |
from datetime import datetime, timedelta, tzinfo | |
from calendar import timegm | |
# http://support.microsoft.com/kb/167296 | |
# How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME | |
EPOCH_AS_FILETIME = 116444736000000000 # January 1, 1970 as MS file time | |
HUNDREDS_OF_NANOSECONDS = 10000000 | |
ZERO = timedelta(0) | |
HOUR = timedelta(hours=1) | |
class UTC(tzinfo): | |
"""UTC""" | |
def utcoffset(self, dt): | |
return ZERO | |
def tzname(self, dt): | |
return "UTC" | |
def dst(self, dt): | |
return ZERO | |
utc = UTC() | |
def dt_to_filetime(dt): | |
"""Converts a datetime to Microsoft filetime format. If the object is | |
time zone-naive, it is forced to UTC before conversion. | |
>>> "%.0f" % dt_to_filetime(datetime(2009, 7, 25, 23, 0)) | |
'128930364000000000' | |
>>> dt_to_filetime(datetime(1970, 1, 1, 0, 0, tzinfo=utc)) | |
116444736000000000L | |
>>> dt_to_filetime(datetime(1970, 1, 1, 0, 0)) | |
116444736000000000L | |
""" | |
if (dt.tzinfo is None) or (dt.tzinfo.utcoffset(dt) is None): | |
dt = dt.replace(tzinfo=utc) | |
return EPOCH_AS_FILETIME + (timegm(dt.timetuple()) * HUNDREDS_OF_NANOSECONDS) | |
def filetime_to_dt(ft): | |
"""Converts a Microsoft filetime number to a Python datetime. The new | |
datetime object is time zone-naive but is equivalent to tzinfo=utc. | |
>>> filetime_to_dt(116444736000000000) | |
datetime.datetime(1970, 1, 1, 0, 0) | |
>>> filetime_to_dt(128930364000000000) | |
datetime.datetime(2009, 7, 25, 23, 0) | |
""" | |
return datetime.utcfromtimestamp((ft - EPOCH_AS_FILETIME) / HUNDREDS_OF_NANOSECONDS) | |
if __name__ == "__main__": | |
import doctest | |
doctest.testmod() | |
Very Helpful Script ... Thank you very much 👍
I wanted to say thank you for posting this code. Very handy. I did create a version inspired by this post and I wanted to share it.
It adds more flexibility in it's use.. read the comments it will explain what it's all about
I did not add the UTC conversions and I am sure that they can be very easily added.
# -*- coding: utf-8 -*-
#
# This file is part of EventGhost.
# Copyright © 2005-2018 EventGhost Project <http://www.eventghost.org/>
#
# EventGhost is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# EventGhost is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with EventGhost. If not, see <http://www.gnu.org/licenses/>.
# inspired by @Mostafa-Hamdy-Elgiar on GithubGist with the Filetimes.py file
from __future__ import print_function
import ctypes
from ctypes.wintypes import DWORD
from datetime import datetime
import time
# Win32 Epoch time is not the same as Unix Epoch time.
# Win32 Epoch time starts at 1/1/1601 00:00:00 where as
# Unix Epoch time starts January 1, 1970 00:00:00.
# Win32 Epoch time representation is also in hundreds of nanoseconds.
# So we need to have a couple of offsets to make the conversions
# this is the Win32 Epoch time for when Unix Epoch time started. It is in
# hundreds of nanoseconds.
EPOCH_AS_FILETIME = 116444736000000000
# This is the divider/multiplier for converting nanoseconds to
# seconds and vice versa
HUNDREDS_OF_NANOSECONDS = 10000000
# I coded this in a way that is going to make doing these time conversions
# really easy. The FILETIME class is a python version of the
# C Windows datatype structure. this can be used for this purpose for setting
# and getting filetimes. This class can be constructed with no values passed.
# then using ctypes.byref() the instance can be passed to the
# Kernel32.GetFileTime function. then by using one of the properties the
# conversions are made.
# You can also supply values on construction so the class can be passed to
# set the filetime as well.
# the constructor accepts 2 parameters. Most of the time you will only pass a
# single value. The values passed can be
# low byte 32 bit integer, high byte 32bit integer
# this is what Windows uses and stores in this structure. I did this so if
# needed the values can be set
# 64 bit integer (long)
# this can be either a float/int of the Unix Epoch time,
# or the Windows Epoch Time. an easy way of getting the time and passing it
# FILETIME(time.time())
# time.time_struct instance
# This example you would not do but for the sake of example the time.time()
# returns the current time since the Unix Epoch in float(seconds). the
# time.localtime() accepts the float and returns a time.time_struct instance
# so if you were storing times for some reason. you could store them as
# int/float(seconds) and using localtime create the time.time_struct instance.
# FILETIME(time.localtime(time.time()))
# datetime.datetime instance,
# same kind of a thing as the above 2 examples.
# FILETIME(datetime.datetime.now())
# passing anything to the constructor is almost only going to be done if you
# are going to set the file time
# properties.
# unix_epoch_seconds
# number of seconds since the Unix Epoch
# windows_epoch_seconds
# number of seconds since the Windows Epoch
# unix_epoch_datetime
# datetime.datetime instance
# seconds
# same as unix_epoch_seconds
# minutes
# number of minutes since Unix Epoch
# hours
# number of hours since Unix Epoch
# days
# number of days since Unix Epoch
# int(instance)
# same as unix_epoch_seconds
# float(instance)
# unix_epoch_seconds with fractions of a second
# str(instance)
# formatted string representation of the time for your locale.
class _FILETIME(ctypes.Structure):
_fields_ = [
('dwLowDateTime', DWORD),
('dwHighDateTime', DWORD)
]
def __init__(self, dwLowDateTime=None, dwHighDateTime=None):
if dwLowDateTime is None and dwHighDateTime is None:
super(_FILETIME, self).__init__()
else:
if dwHighDateTime is None:
if isinstance(dwLowDateTime, datetime):
dwLowDateTime = time.mktime(datetime.now().timetuple())
elif isinstance(dwLowDateTime, time.struct_time):
dwLowDateTime = time.mktime(dwLowDateTime)
else:
try:
dwLowDateTime = dwLowDateTime.seconds
except AttributeError:
pass
dwLowDateTime = int(dwLowDateTime)
if (
(dwLowDateTime - EPOCH_AS_FILETIME) /
HUNDREDS_OF_NANOSECONDS < 0
):
dwLowDateTime = (
(dwLowDateTime * HUNDREDS_OF_NANOSECONDS) +
EPOCH_AS_FILETIME
)
dwHighDateTime = (dwLowDateTime >> 32)
dwLowDateTime = dwLowDateTime - ((dwLowDateTime >> 32) << 32)
self.dwLowDateTime = DWORD(dwLowDateTime)
self.dwHighDateTime = DWORD(dwHighDateTime)
super(_FILETIME, self).__init__(dwLowDateTime, dwHighDateTime)
@property
def unix_epoch_seconds(self):
val = (self.dwHighDateTime << 32) + self.dwLowDateTime
return (val - EPOCH_AS_FILETIME) / HUNDREDS_OF_NANOSECONDS
@property
def windows_epoch_seconds(self):
val = (self.dwHighDateTime << 32) + self.dwLowDateTime
return val / HUNDREDS_OF_NANOSECONDS
@property
def unix_epoch_datetime(self):
return datetime.utcfromtimestamp(self.unix_epoch_seconds)
@property
def seconds(self):
return self.unix_epoch_seconds
@property
def minutes(self):
return int(self.seconds / 60)
@property
def hours(self):
return int(self.minutes / 60)
@property
def days(self):
return int(self.hours / 24)
def __int__(self):
return self.unix_epoch_seconds
def __float__(self):
val = (self.dwHighDateTime << 32) + self.dwLowDateTime
return (val - EPOCH_AS_FILETIME) / float(HUNDREDS_OF_NANOSECONDS)
def __str__(self):
dt = datetime.utcfromtimestamp(self.unix_epoch_seconds)
return dt.strftime('%c')
FILETIME = _FILETIME
PFILETIME = ctypes.POINTER(_FILETIME)
if __name__ == '__main__':
i = time.time()
j = (int(i) * HUNDREDS_OF_NANOSECONDS) + EPOCH_AS_FILETIME
k_high = (j >> 32)
k_low = j - ((j >> 32) << 32)
l = datetime.now()
m = time.localtime(i)
objs = (
('Unix Epoch', (i,)),
('Win32 Epoch (64bit)', (j,)),
('Win32 Epock (2 * 32bit)', (k_low, k_high)),
('datetime.datetime', (l,)),
('time.struct_time', (m,))
)
for time_type, values in objs:
print(time_type, '-', values)
ft = FILETIME(*values)
print(' windows_epoch_seconds:', ft.windows_epoch_seconds)
print(' unix_epoch_seconds:', ft.unix_epoch_seconds)
print(' seconds:', ft.seconds)
print(' minutes:', ft.minutes)
print(' hours:', ft.hours)
print(' days:', ft.days)
print(' __int__:', int(ft))
print(' __float__:', float(ft))
print(' __str__:', str(ft))
print(' dwHighDateTime:', ft.dwHighDateTime)
print(' dwLowDateTime:', ft.dwLowDateTime)
print('\n\n')
I wanted to say thank you for posting this code. Very handy. I did create a version inspired by this post and I wanted to share it.
It adds more flexibility in it's use.. read the comments it will explain what it's all aboutI did not add the UTC conversions and I am sure that they can be very easily added.
# -*- coding: utf-8 -*- # # This file is part of EventGhost. # Copyright © 2005-2018 EventGhost Project <http://www.eventghost.org/> # # EventGhost is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 2 of the License, or (at your option) # any later version. # # EventGhost is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along # with EventGhost. If not, see <http://www.gnu.org/licenses/>. # inspired by @Mostafa-Hamdy-Elgiar on GithubGist with the Filetimes.py file from __future__ import print_function import ctypes from ctypes.wintypes import DWORD from datetime import datetime import time # Win32 Epoch time is not the same as Unix Epoch time. # Win32 Epoch time starts at 1/1/1601 00:00:00 where as # Unix Epoch time starts January 1, 1970 00:00:00. # Win32 Epoch time representation is also in hundreds of nanoseconds. # So we need to have a couple of offsets to make the conversions # this is the Win32 Epoch time for when Unix Epoch time started. It is in # hundreds of nanoseconds. EPOCH_AS_FILETIME = 116444736000000000 # This is the divider/multiplier for converting nanoseconds to # seconds and vice versa HUNDREDS_OF_NANOSECONDS = 10000000 # I coded this in a way that is going to make doing these time conversions # really easy. The FILETIME class is a python version of the # C Windows datatype structure. this can be used for this purpose for setting # and getting filetimes. This class can be constructed with no values passed. # then using ctypes.byref() the instance can be passed to the # Kernel32.GetFileTime function. then by using one of the properties the # conversions are made. # You can also supply values on construction so the class can be passed to # set the filetime as well. # the constructor accepts 2 parameters. Most of the time you will only pass a # single value. The values passed can be # low byte 32 bit integer, high byte 32bit integer # this is what Windows uses and stores in this structure. I did this so if # needed the values can be set # 64 bit integer (long) # this can be either a float/int of the Unix Epoch time, # or the Windows Epoch Time. an easy way of getting the time and passing it # FILETIME(time.time()) # time.time_struct instance # This example you would not do but for the sake of example the time.time() # returns the current time since the Unix Epoch in float(seconds). the # time.localtime() accepts the float and returns a time.time_struct instance # so if you were storing times for some reason. you could store them as # int/float(seconds) and using localtime create the time.time_struct instance. # FILETIME(time.localtime(time.time())) # datetime.datetime instance, # same kind of a thing as the above 2 examples. # FILETIME(datetime.datetime.now()) # passing anything to the constructor is almost only going to be done if you # are going to set the file time # properties. # unix_epoch_seconds # number of seconds since the Unix Epoch # windows_epoch_seconds # number of seconds since the Windows Epoch # unix_epoch_datetime # datetime.datetime instance # seconds # same as unix_epoch_seconds # minutes # number of minutes since Unix Epoch # hours # number of hours since Unix Epoch # days # number of days since Unix Epoch # int(instance) # same as unix_epoch_seconds # float(instance) # unix_epoch_seconds with fractions of a second # str(instance) # formatted string representation of the time for your locale. class _FILETIME(ctypes.Structure): _fields_ = [ ('dwLowDateTime', DWORD), ('dwHighDateTime', DWORD) ] def __init__(self, dwLowDateTime=None, dwHighDateTime=None): if dwLowDateTime is None and dwHighDateTime is None: super(_FILETIME, self).__init__() else: if dwHighDateTime is None: if isinstance(dwLowDateTime, datetime): dwLowDateTime = time.mktime(datetime.now().timetuple()) elif isinstance(dwLowDateTime, time.struct_time): dwLowDateTime = time.mktime(dwLowDateTime) else: try: dwLowDateTime = dwLowDateTime.seconds except AttributeError: pass dwLowDateTime = int(dwLowDateTime) if ( (dwLowDateTime - EPOCH_AS_FILETIME) / HUNDREDS_OF_NANOSECONDS < 0 ): dwLowDateTime = ( (dwLowDateTime * HUNDREDS_OF_NANOSECONDS) + EPOCH_AS_FILETIME ) dwHighDateTime = (dwLowDateTime >> 32) dwLowDateTime = dwLowDateTime - ((dwLowDateTime >> 32) << 32) self.dwLowDateTime = DWORD(dwLowDateTime) self.dwHighDateTime = DWORD(dwHighDateTime) super(_FILETIME, self).__init__(dwLowDateTime, dwHighDateTime) @property def unix_epoch_seconds(self): val = (self.dwHighDateTime << 32) + self.dwLowDateTime return (val - EPOCH_AS_FILETIME) / HUNDREDS_OF_NANOSECONDS @property def windows_epoch_seconds(self): val = (self.dwHighDateTime << 32) + self.dwLowDateTime return val / HUNDREDS_OF_NANOSECONDS @property def unix_epoch_datetime(self): return datetime.utcfromtimestamp(self.unix_epoch_seconds) @property def seconds(self): return self.unix_epoch_seconds @property def minutes(self): return int(self.seconds / 60) @property def hours(self): return int(self.minutes / 60) @property def days(self): return int(self.hours / 24) def __int__(self): return self.unix_epoch_seconds def __float__(self): val = (self.dwHighDateTime << 32) + self.dwLowDateTime return (val - EPOCH_AS_FILETIME) / float(HUNDREDS_OF_NANOSECONDS) def __str__(self): dt = datetime.utcfromtimestamp(self.unix_epoch_seconds) return dt.strftime('%c') FILETIME = _FILETIME PFILETIME = ctypes.POINTER(_FILETIME) if __name__ == '__main__': i = time.time() j = (int(i) * HUNDREDS_OF_NANOSECONDS) + EPOCH_AS_FILETIME k_high = (j >> 32) k_low = j - ((j >> 32) << 32) l = datetime.now() m = time.localtime(i) objs = ( ('Unix Epoch', (i,)), ('Win32 Epoch (64bit)', (j,)), ('Win32 Epock (2 * 32bit)', (k_low, k_high)), ('datetime.datetime', (l,)), ('time.struct_time', (m,)) ) for time_type, values in objs: print(time_type, '-', values) ft = FILETIME(*values) print(' windows_epoch_seconds:', ft.windows_epoch_seconds) print(' unix_epoch_seconds:', ft.unix_epoch_seconds) print(' seconds:', ft.seconds) print(' minutes:', ft.minutes) print(' hours:', ft.hours) print(' days:', ft.days) print(' __int__:', int(ft)) print(' __float__:', float(ft)) print(' __str__:', str(ft)) print(' dwHighDateTime:', ft.dwHighDateTime) print(' dwLowDateTime:', ft.dwLowDateTime) print('\n\n')
Hi, sorry i dont know python but i just really need to convert my dwLowDateTime and dwHighDateTime to something readable. How do i use this script of yours?
That was so helpful! I've been all morning looking for this. Thanks so much!
That was so helpful!
Hello if you're arriving from Google. Note that I published a (public domain / CC0) python package for the same functionality as winfiletime
.
https://github.com/jleclanche/winfiletime
https://pypi.org/project/winfiletime/
Thank you, great clean code. Not only does it work but it's readable and I feel like I know what it's actually needing to do now to convert the time.
Usage :
#python