timelog

GTimeLog compatible command line tools
git clone https://git.ce9e.org/timelog.git

commit
de1fdc0d30ddd783b6214aec20999ef29aab9574
parent
beaf161ee5baca7ba274b4acb5d5b23d83c51bee
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2022-02-23 21:36
Gardening

Diffstat

M vtimelog 78 +++++++++++++++++++++----------------------------------------

1 files changed, 27 insertions, 51 deletions


diff --git a/vtimelog b/vtimelog

@@ -1,30 +1,29 @@
    1     1 #!/usr/bin/env python3
    2     2 
    3    -1 #	Parse timelog files, filter the lines and output interesting data
    4    -1 #	Copyright (C) 2014 Tobias Bengfort <tobias.bengfort@posteo.de>
   -1     3 # Parse timelog files, filter the lines and output interesting data
   -1     4 # Copyright (C) 2014 Tobias Bengfort <tobias.bengfort@posteo.de>
    5     5 #
    6    -1 #	This program is free software: you can redistribute it and/or modify
    7    -1 #	it under the terms of the GNU General Public License as published by
    8    -1 #	the Free Software Foundation, either version 3 of the License, or
    9    -1 #	(at your option) any later version.
   -1     6 # This program is free software: you can redistribute it and/or modify
   -1     7 # it under the terms of the GNU General Public License as published by
   -1     8 # the Free Software Foundation, either version 3 of the License, or
   -1     9 # (at your option) any later version.
   10    10 #
   11    -1 #	This program is distributed in the hope that it will be useful,
   12    -1 #	but WITHOUT ANY WARRANTY; without even the implied warranty of
   13    -1 #	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14    -1 #	GNU General Public License for more details.
   -1    11 # This program is distributed in the hope that it will be useful,
   -1    12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
   -1    13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   -1    14 # GNU General Public License for more details.
   15    15 #
   16    -1 #	You should have received a copy of the GNU General Public License
   17    -1 #	along with this program.  If not, see <http://www.gnu.org/licenses/>.
   -1    16 # You should have received a copy of the GNU General Public License
   -1    17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
   18    18 
   19    19 import argparse
   20    -1 from os.path import expanduser
   -1    20 import os
   21    21 from datetime import datetime, timedelta
   22    22 
   23    23 EMPTY_LINE = object()
   24    24 DT_FORMAT = '%Y-%m-%d %H:%M'
   25    25 
   26    26 
   27    -1 """parse"""
   28    27 class ParseError(Exception):
   29    28 	def __init__(self, line, msg=''):
   30    29 		self.line = line
@@ -72,7 +71,6 @@ class LazyTimelog(LazyTuple):
   72    71 			raise ParseError(i, str(e))
   73    72 
   74    73 
   75    -1 """filter"""
   76    74 def datetime_add(dt, years=0, months=0, weeks=0, days=0, hours=0, minutes=0,
   77    75 		seconds=0, microseconds=0):
   78    76 	dt += timedelta(
@@ -81,22 +79,24 @@ def datetime_add(dt, years=0, months=0, weeks=0, days=0, hours=0, minutes=0,
   81    79 		hours=hours,
   82    80 		minutes=minutes,
   83    81 		seconds=seconds,
   84    -1 		microseconds=microseconds)
   -1    82 		microseconds=microseconds,
   -1    83 	)
   85    84 
   86    85 	month = dt.month + months
   87    86 	div, month = divmod(month - 1, 12)
   88    87 	month += 1
   89    88 	year = dt.year + years + div
   90    89 
   91    -1 	return datetime(year, month, dt.day, dt.hour, dt.minute, dt.second,
   92    -1 		dt.microsecond)
   -1    90 	return datetime(
   -1    91 		year, month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond
   -1    92 	)
   93    93 
   94    94 
   95    95 def timedelta2str(delta):
   96    96 	seconds = delta.total_seconds()
   97    97 	minutes, seconds = divmod(seconds, 60)
   98    98 	hours, minutes = divmod(minutes, 60)
   99    -1 	return "{: =3}:{:0=2}".format(int(hours), int(minutes))
   -1    99 	return '{: =3}:{:0=2}'.format(int(hours), int(minutes))
  100   100 
  101   101 
  102   102 class Query:
@@ -160,7 +160,6 @@ class Query:
  160   160 		return tuple(self.timelog[i] for i in self.data)
  161   161 
  162   162 
  163    -1 """extract information"""
  164   163 class Extractor:
  165   164 	def __init__(self, data):
  166   165 		self.data = tuple(data)
@@ -190,7 +189,6 @@ class Extractor:
  190   189 		return d
  191   190 
  192   191 
  193    -1 """Holidays"""
  194   192 class ExpectedHoursPer:
  195   193 	WORKDAYS_PER_WEEK = 5
  196   194 	WORKHOURS_PER_WEEK = 35
@@ -230,42 +228,19 @@ class ExpectedHoursPer:
  230   228 			- cls.VACATION_DAYS_PER_YEAR)
  231   229 
  232   230 
  233    -1 """cli"""
  234    -1 #def timelog2csv():
  235    -1 #	f = open('timelog.txt')
  236    -1 #	l = [line.strip() for line in f.readlines() if line.strip()]
  237    -1 #	data = LazyTimelog(l)
  238    -1 #	f.close()
  239    -1 #
  240    -1 #	def day(entry):
  241    -1 #		return entry['dt'].strftime('%Y-%m-%d')
  242    -1 #
  243    -1 #	x = timedelta()
  244    -1 #	last = None
  245    -1 #	for entry in data:
  246    -1 #		if last is not None:
  247    -1 #			if day(last) != day(entry):
  248    -1 #				print('"%s","%s"' % (day(last), int(x.total_seconds() / 3600)))
  249    -1 #				x = timedelta()
  250    -1 #
  251    -1 #			if '**' not in entry['comment']:
  252    -1 #				x += entry['dt'] - last['dt']
  253    -1 #		last = entry
  254    -1 
  255    -1 
  256   231 if __name__ == '__main__':
  257   232 	parser = argparse.ArgumentParser(
  258   233 		description='extract interesting data from timelogs')
  259   234 	parser.add_argument('--file',
  260    -1 		default=expanduser("~/.gtimelog/timelog.txt"))
   -1   235 		default=os.path.expanduser('~/.gtimelog/timelog.txt'))
  261   236 	parser.add_argument('-d', '--day', nargs='?', const=0, type=int,
  262    -1 		help="show entries from today or DAY days ago")
   -1   237 		help='show entries from today or DAY days ago')
  263   238 	parser.add_argument('-w', '--week', nargs='?', const=0, type=int,
  264    -1 		help="show entries from this week or WEEK weeks ago")
   -1   239 		help='show entries from this week or WEEK weeks ago')
  265   240 	parser.add_argument('-m', '--month', nargs='?', const=0, type=int,
  266    -1 		help="show entries from this month or MONTH months ago")
   -1   241 		help='show entries from this month or MONTH months ago')
  267   242 	parser.add_argument('-y', '--year', nargs='?', const=0, type=int,
  268    -1 		help="show entries from this year or YEAR years ago")
   -1   243 		help='show entries from this year or YEAR years ago')
  269   244 	args = parser.parse_args()
  270   245 
  271   246 	# load data from file
@@ -290,7 +265,8 @@ if __name__ == '__main__':
  290   265 		expected = ExpectedHoursPer.year()
  291   266 	else:
  292   267 		expected = ExpectedHoursPer.days(
  293    -1 			(data[-1]['dt'] - data[0]['dt']).total_seconds() / 3600 / 24)
   -1   268 			(data[-1]['dt'] - data[0]['dt']).total_seconds() / 3600 / 24
   -1   269 		)
  294   270 	data = q.all()
  295   271 
  296   272 	ex = Extractor(data)
@@ -305,4 +281,4 @@ if __name__ == '__main__':
  305   281 
  306   282 	# output total workhours
  307   283 	done = int(ex.sum().total_seconds() / 3600)
  308    -1 	print("Total workhours done: %i (%i extra)" % (done, done - expected))
   -1   284 	print('Total workhours done: %i (%i extra)' % (done, done - expected))