1# -*- coding: utf-8 -*-
2
3"""Enhancement of datetime for DOS date/time format compatibility."""
4from datetime import datetime, time
5
6
7def _convert_to_dos_date(func):
8 """Convert datetime to DosDateTime."""
9 def _wrapper(*args, **kwargs) -> "DosDateTime":
10 date: datetime = func(*args, **kwargs)
11 return DosDateTime(*date.timetuple()[:6])
12 return _wrapper
13
14
15class DosDateTime(datetime):
16 """DOS-specific date/time format serialization."""
17
18 now = _convert_to_dos_date(datetime.now)
19 fromtimestamp = _convert_to_dos_date(datetime.fromtimestamp)
20
21 def serialize_date(self) -> int:
22 """Convert current datetime to FAT date."""
23 date = self.year - 1980 << 9 | self.month << 5 | self.day
24 return date
25
26 def serialize_time(self) -> int:
27 """Convert current datetime to FAT time."""
28 time = self.hour << 11 | self.minute << 5
29 time |= ((self.second - (self.second % 2)) // 2)
30 return time
31
32 @staticmethod
33 def deserialize_date(dt: int) -> "DosDateTime":
34 """Convert a DOS date format to a Python object."""
35 day = dt & (1 << 5) - 1
36 month = (dt >> 5) & ((1 << 4) - 1)
37 year = ((dt >> 9) & (1 << 7) - 1) + 1980
38
39 try:
40 return DosDateTime(year, month, day)
41 except ValueError:
42 return DosDateTime(1980, 1, 1)
43
44 @staticmethod
45 def deserialize_time(tm: int) -> time:
46 """Convert a DOS time format to a Python object."""
47 second = (tm & (1 << 5) - 1) * 2
48 minute = (tm >> 5) & ((1 << 6) - 1)
49 hour = (tm >> 11) & ((1 << 5) - 1)
50
51 try:
52 return time(hour, minute, second)
53 except ValueError:
54 return time(0, 0, 0)