@@ -558,32 +558,53 @@ def get_s5time(bytearray_: bytearray, byte_index: int) -> str:
558558
559559
560560def 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
589610def get_time (bytearray_ : bytearray , byte_index : int ) -> str :
0 commit comments