in_time_between.py (Source)

#!/usr/bin/python -u
# vim: fileencoding=utf-8:nomodified:nowrap:textwidth=0:foldmethod=marker:foldcolumn=4:ruler:showcmd:lcs=tab\:|- list:noexpandtab:nosmarttab:softtabstop=0:shiftwidth=0


verze  = '0.0.1-r1' # @@verze@@
datum  = '09.05.2021 04:36:29' # @@datum@@
branch = 'master' # @@branch@@

import sys
import re
import datetime
import logging

verb=logging.DEBUG
#	verb=logging.ERROR
#	if verbose: verb=logging.INFO
#	if debug: verb=logging.DEBUG
#	if quiet: verb=logging.CRITICAL
logging.basicConfig(stream=sys.stderr, level=verb)
logger = logging.getLogger("ITB")

# * is greedy, *? is not
# | X || 1.Kansaska || 2054.04.27 08:00 || 40 || 7.5 || 2054.04.27 8:30  || Po (Ramon 7:30)
TIME_LINE = re.compile(r"^\|[^\|]*\|\| *([^\|]*?) *\|\| *([^\|]*?) *\|\|[^\|]*\|\|[^\|]*\|\| *([^\|]*?) *\|\| *(.*)")
# 2054.04.27 8:30
TIME_STR = ( '%Y.%m.%d %H:%M')
def convert_timedelta(duration):	 # {{{
	days, seconds = duration.days, duration.seconds
	hours = days * 24 + seconds // 3600
	minutes = (seconds % 3600) // 60
	seconds = (seconds % 60)
	return hours, minutes, seconds
# }}}
def process_text(lines):	 # {{{
	def getKey(item):
		return item[0]
	retval=()
	for line in lines:
		line=line.strip()
		matcher = TIME_LINE.match(line)
		if matcher is not None:
			try:
				(t_what,t_from,t_to,t_comm) = matcher.groups()
				t_from = datetime.datetime.strptime(matcher.group(2), TIME_STR)
				t_to = datetime.datetime.strptime(matcher.group(3), TIME_STR)
				if t_to <= t_from:
					logger.error("#! Bad order datetime %s .. %s in %s",matcher.group(2),matcher.group(3),line)
					continue
			except ValueError:
				logger.error("#! Not datetime %s .. %s in %s",matcher.group(2),matcher.group(3),line)
				continue
			retval+=((t_from,t_to,t_what,t_comm),)
	return sorted(retval, key=getKey)
# }}}
def find_duplicities(lines):	 # {{{
	(o_from,o_to,o_what,o_comm) = (None,None,None,None)
	retval=()
	for (t_from,t_to,t_what,t_comm) in lines:
		if (o_from,o_to) == (t_from,t_to):
			if o_what in ("Charisma","Pistole") and  t_what in ("Charisma","Pistole"):
				pass # should be OK
			else:
				logger.warning("#d is same %s .. %s (%s || %s) x (%s || %s)",o_from.strftime(TIME_STR),o_to.strftime(TIME_STR),o_what,o_comm,t_what,t_comm)
		else:
			retval+= ((t_from,t_to,t_what,t_comm),)
		(o_from,o_to,o_what,o_comm) = (t_from,t_to,t_what,t_comm)
	return retval
# }}}
def find_crossed(lines):	 # {{{
	(t_from,t_to,t_what,t_comm) = lines[0]
	(o_from,o_to,o_what,o_comm) = (t_from,t_to,t_what,t_comm)
	retval=()
	retval+= ((t_from,t_to,t_what,t_comm),)
	for (t_from,t_to,t_what,t_comm) in lines[1:]:
		if o_from == t_from:
			logger.error("#! crossed %s .. %s x %s .. %s  (%s || %s) x (%s || %s)",o_from.strftime(TIME_STR),o_to.strftime(TIME_STR),t_from.strftime(TIME_STR),t_to.strftime(TIME_STR),o_what,o_comm,t_what,t_comm)
			continue
		elif o_to > t_from:
			logger.error("#! crossed %s .. %s x %s .. %s  (%s || %s) x (%s || %s)",o_from.strftime(TIME_STR),o_to.strftime(TIME_STR),t_from.strftime(TIME_STR),t_to.strftime(TIME_STR),o_what,o_comm,t_what,t_comm)
			continue
		else:
			retval+= ((t_from,t_to,t_what,t_comm),)
		(o_from,o_to,o_what,o_comm) = (t_from,t_to,t_what,t_comm)
	return retval
# }}}
def create_holes(lines):	 # {{{
	(t_from,t_to,t_what,t_comm) = lines[0]
	(o_from,o_to,o_what,o_comm) = (t_from,t_to,t_what,t_comm)
	retval=()
	for (t_from,t_to,t_what,t_comm) in lines[1:]:
		if o_to < t_from:
			(h,m,s)=convert_timedelta(t_from-o_to)
			retval += ((t_from, o_to , h,m),)
			logger.info("#i hole %s .. %s = %s:%02d ",o_to.strftime(TIME_STR),t_from.strftime(TIME_STR),h,m)
		(o_from,o_to,o_what,o_comm) = (t_from,t_to,t_what,t_comm)
	return retval
# }}}

if __name__ == '__main__':
	lines=()
	for line in sys.stdin:
		lines+=(line.strip(),)
	retval=process_text(lines)
	if not retval: sys.exit(1)
	retval=find_duplicities(retval)
	if not retval: sys.exit(1)
	retval=find_crossed(retval)
	if not retval: sys.exit(1)
	holes=create_holes(retval)
	if not holes: sys.exit(1)
	for line in retval:
		(t_from,t_to,t_what,t_comm)=line
		print("#>> %s .. %s || %s || %s" % (t_from.strftime(TIME_STR),t_to.strftime(TIME_STR),t_what,t_comm))
	print("="*30)
	for line in holes:
		(t_from,t_to,h,m)=line
		print("|-")
		print("| ? || EMPTY || %s || ?? || %s:%02d || %s || EMPTY " % (t_to.strftime(TIME_STR),h,m,t_from.strftime(TIME_STR)))