最近時間を切り売りする仕事の仕方にシフトしているため、数年ぶりに勤怠管理をすることになったので、それ用のスクリプトを書いてみたのでメモ程度に残します。
要件
- 勤怠管理があまり徹底されてないゆるふわな感じ
- でも勤怠管理は付けてね、チェックもするから。みたいな矛盾した世界
- 普段、始業と共にMacを起動する
- そして終業と共にMacをシャットダウンする
- つまりMacの、その日の最初の起動・最後の終了取れれば勤怠管理できる
- 直近の月のログ取れればとりあえず良いよね
- 標準インストールのPythonで動かしたい
- python 2.7
コード
やってることはlast rebootとlast shutdownを叩いてソートしてるだけ
$ python attendance_output.py 7 <- 取りたい月を引数にする
attendance_output.py
import sys
import re
import subprocess
import dateutil.parser
def attendanceDate(month):
output = {}
checkMonth = [0]
def assignDate(matchDate, func):
parseDate = dateutil.parser.parse(matchDate)
if checkMonth[0]:
if checkMonth[0] is not parseDate.month: return
if parseDate.month is month:
dateStr = parseDate.day
if dateStr in output:
if job in output[dateStr]:
output[dateStr][job] = parseDate if func(output[dateStr][job], parseDate) else output[dateStr][job]
else:
output[dateStr].update({job: parseDate})
else:
output[dateStr] = {job: parseDate}
checkMonth[0] = parseDate.month
for job, func in {'reboot': lambda x,z:x>z, 'shutdown': lambda x,z:x<z}.items():
for checkDate in subprocess.check_output("last %s" % job, shell=True).splitlines():
matchObj = re.findall(r'%s\s+\~\s+([a-zA-Z]{3}\s[a-zA-Z]{3}\s+\d{1,2}\s+\d{1,2}\:\d{1,2})\s' % job, checkDate.decode('utf-8'))
if len(matchObj): assignDate(matchObj[0], func)
return output
for key, value in sorted(attendanceDate(int(sys.argv[1])).items(), key=lambda x: x[0]):
print('%s/%s %s, %s' % (int(sys.argv[1]), key,
'start %s' % value['reboot'].strftime('%H:%M') if 'reboot' in value else '',
'end %s' % value['shutdown'].strftime('%H:%M') if 'shutdown' in value else ''))
結果
以下の感じでデータ出力されればOK。あとで出力をCSVかスプレッドシートとかにすれば尚良い
6/1 start 14:14, end 14:42
6/2 start 11:44,
6/5 start 11:56, end 22:30
6/6 start 12:00, end 19:07
6/7 start 11:51, end 19:03
6/8 start 12:15, end 12:22
6/9 start 10:17,
6/13 start 12:04, end 19:19
6/14 start 12:10,
6/16 start 12:26, end 18:59
6/18 start 17:50, end 18:18
6/19 start 12:29, end 19:04
6/23 start 12:03,
6/27 start 12:26,
6/28 start 15:48, end 18:16
6/29 start 12:40, end 19:11
6/30 start 18:30, end 21:57