Skip to content

Commit 5680236

Browse files
committed
Closes #89
Retain Kind value for DateTime resource type.
1 parent 703c9c3 commit 5680236

File tree

3 files changed

+35
-24
lines changed

3 files changed

+35
-24
lines changed

src/dnfile/base.py

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -985,28 +985,49 @@ def parse(self):
985985

986986
class DateTimeStruct(Structure):
987987
Ticks: int
988-
Kind: enums.DateTimeKind
988+
Kind: int
989989

990990

991991
class DateTime(object):
992-
def __init__(self, rva: int, raw_bytes: bytes):
992+
struct: Optional[DateTimeStruct]
993+
kind: Optional[enums.DateTimeKind]
994+
value: Optional[datetime.datetime]
995+
seconds: Optional[int]
996+
__data__: bytes
997+
998+
def __init__(self, raw_bytes: bytes, rva: Optional[int] = None):
993999
self.struct: Optional[DateTimeStruct] = None
994-
self.raw: bytes = raw_bytes
1000+
self.kind: Optional[enums.DateTimeKind] = None
9951001
self.value: Optional[datetime.datetime] = None
1002+
self.seconds: Optional[int] = None
1003+
self.__data__: bytes = raw_bytes
1004+
self.rva: Optional[int] = rva
9961005

9971006
def parse(self):
998-
if not self.raw:
1007+
if not self.__data__:
9991008
# TODO: warn/error
10001009
return
1001-
# Should be 64 bites
1002-
if len(self.raw) != 8:
1010+
# Should be 64 bits
1011+
if len(self.__data__) != 8:
10031012
# TODO: warn/error
10041013
return
1005-
x = _struct.unpack("<q", self.raw)[0]
1014+
x = _struct.unpack("<q", self.__data__)[0]
10061015
self.struct = DateTimeStruct()
10071016
self.struct.Ticks = x & 0x3FFFFFFFFFFFFFFF
1017+
# Value is stored in lower 62-bits
1018+
# https://github.com/dotnet/runtime/blob/17c55f1/src/libraries/System.Private.CoreLib/src/System/DateTime.cs#L130-L138
10081019
self.struct.Kind = x >> 62
10091020
# https://stackoverflow.com/questions/3169517/python-c-sharp-binary-datetime-encoding
1010-
secs = self.struct.Ticks / 10.0 ** 7
1011-
delta = datetime.timedelta(seconds=secs)
1012-
self.value = datetime.datetime(1, 1, 1) + delta
1021+
self.Seconds = self.struct.Ticks / 10.0 ** 7
1022+
self.Kind = enums.DateTimeKind(self.struct.Kind)
1023+
delta = datetime.timedelta(seconds=self.Seconds)
1024+
if self.Kind == enums.DateTimeKind.Utc:
1025+
self.value = datetime.datetime(1, 1, 1, 0, 0, 0, 0, datetime.timezone.utc) + delta
1026+
else:
1027+
self.value = datetime.datetime(1, 1, 1, 0, 0, 0, 0) + delta
1028+
1029+
def __str__(self) -> str:
1030+
return str(self.value)
1031+
1032+
def to_datetime(self) -> Optional[datetime.datetime]:
1033+
return self.value

src/dnfile/enums.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -874,4 +874,4 @@ class DateTimeKind(_enum.IntEnum):
874874
Unspecified = 0
875875
Utc = 1
876876
Local = 2
877-
LocalAmbiguousDst = 3
877+
LocalAmbiguousDst = 3

src/dnfile/resource.py

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -224,19 +224,9 @@ def type_str_to_type(self, type_name: str, data: bytes, offset: int) -> Tuple[Op
224224
elif type_name == "System.DateTime":
225225
tsize = 8
226226
final_bytes = data[offset:offset + tsize]
227-
x = struct.unpack("<q", final_bytes)[0]
228-
# Value is stored in lower 62-bits
229-
# https://github.com/dotnet/runtime/blob/17c55f1/src/libraries/System.Private.CoreLib/src/System/DateTime.cs#L130-L138
230-
x = x & ((1 << 62) - 1)
231-
# https://stackoverflow.com/questions/3169517/python-c-sharp-binary-datetime-encoding
232-
secs = x / 10.0 ** 7
233-
delta = datetime.timedelta(seconds=secs)
234-
try:
235-
dt = datetime.datetime(1, 1, 1) + delta
236-
final_value = dt
237-
except OverflowError:
238-
# TODO warn/error
239-
pass
227+
dt = base.DateTime(final_bytes)
228+
dt.parse()
229+
final_value = dt
240230
elif type_name == "System.TimeSpan":
241231
# TODO return resourceDataFactory.Create(new TimeSpan(reader.ReadInt64()));
242232
tsize = 8

0 commit comments

Comments
 (0)