Skip to content

Commit 6f8bcb1

Browse files
authored
added DATE_AND_TIME Value as Datetime object (#312)
* added DATE_AND_TIME Value as Datetime object added function to get DATE_AND_TIME value as datetime Object and updated get_dt to use this function * Fix error * implemented pycodecsytle fixes replace lamba with internal function to implement pycodecsytle proposal
1 parent dc53f4a commit 6f8bcb1

File tree

1 file changed

+47
-26
lines changed

1 file changed

+47
-26
lines changed

snap7/util.py

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -558,32 +558,53 @@ def get_s5time(bytearray_: bytearray, byte_index: int) -> str:
558558

559559

560560
def get_dt(bytearray_: bytearray, byte_index: int) -> str:
561-
# 1990 - 1999, 2000 - 2089
562-
micro_to_milli = 1000
563-
data_bytearray = bytearray_[byte_index:byte_index + 8]
564-
dt_lst = list(data_bytearray.hex())
565-
date_time_list = []
566-
for i in range(0, len(dt_lst), 2):
567-
# last two bytearrays are the miliseconds and workday, they must be parsed together
568-
if i != len(dt_lst) - 4:
569-
if i == 0 and dt_lst[i] == '9':
570-
date_time_list.append(int('19' + dt_lst[i] + dt_lst[i + 1]))
571-
elif i == 0 and dt_lst[i] != '9':
572-
date_time_list.append(int('20' + dt_lst[i] + dt_lst[i + 1]))
573-
else:
574-
date_time_list.append(int(dt_lst[i] + dt_lst[i + 1]))
575-
else:
576-
date_time_list.append(int(dt_lst[i] + dt_lst[i + 1] + dt_lst[i + 2]))
577-
break
578-
date_and_time = datetime(
579-
date_time_list[0],
580-
date_time_list[1],
581-
date_time_list[2],
582-
date_time_list[3],
583-
date_time_list[4],
584-
date_time_list[5],
585-
date_time_list[6] * micro_to_milli).isoformat(timespec='microseconds')
586-
return date_and_time
561+
"""Get DATE_AND_TIME Value from bytearray as ISO 8601 formatted Date String
562+
Notes:
563+
Datatype `DATE_AND_TIME` consists in 8 bytes in the PLC.
564+
Args:
565+
bytearray_: buffer to read.
566+
byte_index: byte index from where to start writing.
567+
Examples:
568+
>>> data = bytearray(8)
569+
>>> data[:] = [32, 7, 18, 23, 50, 2, 133, 65] #'2020-07-12T17:32:02.854000'
570+
>>> get_dt(data,0)
571+
'2020-07-12T17:32:02.854000'
572+
"""
573+
return get_date_time_object(bytearray_, byte_index).isoformat(timespec='microseconds')
574+
575+
576+
def get_date_time_object(bytearray_: bytearray, byte_index: int) -> datetime:
577+
"""Get DATE_AND_TIME Value from bytearray as python datetime object
578+
Notes:
579+
Datatype `DATE_AND_TIME` consists in 8 bytes in the PLC.
580+
Args:
581+
bytearray_: buffer to read.
582+
byte_index: byte index from where to start writing.
583+
Examples:
584+
>>> data = bytearray(8)
585+
>>> data[:] = [32, 7, 18, 23, 50, 2, 133, 65] #date '2020-07-12 17:32:02.854'
586+
>>> get_date_time_object(data,0)
587+
datetime.datetime(2020, 7, 12, 17, 32, 2, 854000)
588+
"""
589+
590+
def bcd_to_byte(byte: int) -> int:
591+
return (byte >> 4) * 10 + (byte & 0xF)
592+
593+
year = bcd_to_byte(bytearray_[byte_index])
594+
# between 1990 and 2089, only last two digits are saved in DB 90 - 89
595+
year = 2000 + year if year < 90 else 1900 + year
596+
month = bcd_to_byte(bytearray_[byte_index + 1])
597+
day = bcd_to_byte(bytearray_[byte_index + 2])
598+
hour = bcd_to_byte(bytearray_[byte_index + 3])
599+
min = bcd_to_byte(bytearray_[byte_index + 4])
600+
sec = bcd_to_byte(bytearray_[byte_index + 5])
601+
# plc save miliseconds in two bytes with the most signifanct byte used only
602+
# in the last byte for microseconds the other for weekday
603+
# * 1000 because pythoin datetime needs microseconds not milli
604+
microsec = (bcd_to_byte(bytearray_[byte_index + 6]) * 10
605+
+ bcd_to_byte(bytearray_[byte_index + 7] >> 4)) * 1000
606+
607+
return datetime(year, month, day, hour, min, sec, microsec)
587608

588609

589610
def get_time(bytearray_: bytearray, byte_index: int) -> str:

0 commit comments

Comments
 (0)