Mukai Systems

勤怠入力の自動化

私は日々の勤怠をS式でつけている。

$ cat attendance.p
((2022 04 20)
 ; Su Mo Tu We Th Fr Sa
 ;                 1  2
 ;  3  4  5  6  7  8  9
 ; 10 11 12 13 14 15 16
 ; 17 18 19 20 21 22 23
 ; 24 25 26 27 28 XX 30
 (01 "09:30" "18:15")
 (04 "09:45" "17:30")
 ...
 (28 "10:00" "16:00"))

...

((2022 12 20)
; Su Mo Tu We Th Fr Sa
;              1  2  3
;  4  5  6  7  8  9 10
; 11 12 13 14 15 16 17
; 18 19 20 21 22 23 24
; 25 26 27 28 XX XX XX
 (01 "09:30" "17:00"))

そして、そのためのプログラムams(1)を作ってある。

$ paren man ams(1)
ams(1)

# NAME
ams - attendance management system.

# SYNOPSIS

    ams [OPTION] ... [FILE] ...

# DESCRIPTION
Read attendance information from standard input or `FILE` and output summary to stand
ard output.

See `ams(5)` for attendance information format specifications.

# OPTIONS

    -a
        All subject to.
    -e
        Estimate the change in working hours if working at current levels.
    -E HOUR
        Estimate the change in working hours if working HOUR hours per day.
    -h HOUR
        Specify HOUR for the target monthly working hours instead of 140.
    -l
        Output in long format when -v option is enabled.
    -m MONTHS
        MONTHS are considered as the month to be counted.
        The default is this month.
    -s
        Suppress summary.
    -t
        Display a table of hours worked per day against the number of working days an
d exit.
    -y YEARS
        YEARS are considered as the year to be counted.
        The default is this year.
    -v
        Output working hours verbosely.

# EXAMPLES
Reads attendance information from the file `attendance.p` and display a summary of ti
me and attendance information.

    $ paren ams attendance.p

Reads attendance information from the file `attendance.p` and display only the hours
worked per day.

    $ paren ams -vs attendance.p

Reads attendance information from the file `attendance.p` and displays a summary of 1
60 hours per month of target working hours.

    $ paren ams -l160 attendance.p

Read attendance information from the file `attendance.p` and display data from `2020`
 to `2022` and `2024`.

    $ paren ams -y2020-2022,2024 attendance.p

# SEE ALSO
- `cal(1)`
- `ldate(1)`
- `ams(5)`

--
./man1/ams.md

ams(1)に勤怠データを与えると様々なことができる。オプションなしで実行した場合、今月の勤務日数、勤務時間、一日あたりの勤務時間、月140時間とした場合に残りの勤務時間、そして、月140時間とした場合の一日当たりに働かなければならない時間が出力されるようになっている。

$ paren ams attendance.p
(:year 2022 :month 12 :total (:day 1 :h 6.5 :h/day 6.5) :rest (:day 19 :h 133.5 :h/day 7.026316))

オプションによって、今のペースで働いた場合に残りの勤務時間がどのように遷移するのかといったことや、毎日の勤務時間はどうだったのか。といった確認も行える。

$ paren ams -e attendance.p
(:year 2022 :month 12 :total (:day 1 :h 6.5 :h/day 6.5) :rest (:day 19 :h 133.5 :h/day 7.026316))
(:days 19 :h 133.5 :h/day 7.026316)
(:days 18 :h 127 :h/day 7.055556)
(:days 17 :h 120.5 :h/day 7.088235)
(:days 16 :h 114 :h/day 7.125)
(:days 15 :h 107.5 :h/day 7.166667)
(:days 14 :h 101 :h/day 7.214286)
(:days 13 :h 94.5 :h/day 7.269231)
(:days 12 :h 88 :h/day 7.333333)
(:days 11 :h 81.5 :h/day 7.409091)
(:days 10 :h 75 :h/day 7.5)
(:days 9 :h 68.5 :h/day 7.611111)
(:days 8 :h 62 :h/day 7.75)
(:days 7 :h 55.5 :h/day 7.928571)
(:days 6 :h 49 :h/day 8.166667)
(:days 5 :h 42.5 :h/day 8.5)
(:days 4 :h 36 :h/day 9)
(:days 3 :h 29.5 :h/day 9.833333)
(:days 2 :h 23 :h/day 11.5)
(:days 1 :h 16.5 :h/day 16.5)

そうして、雇われの身である私は、月の下限労働時間である140時間を満たすように毎日amsを実行しながら勤務時間を調整し、月末にたくさんのセル結合と、難解で不完全な祝日判定処理をはじめとした、いくつかのバグのあるVBAが組み込まれた指定のExcelにこの内容を転写して提出することによって、事業収入を得ることになっているのである。

このプロセスには問題がある。そう、自動化されていないのである。私はある日、出勤時刻を記録するのを忘れていたため困ってしまった。何かあてにできる値はないかと探したものがWindowsのイベントログである。イベントビューアでシステムログを確認するとKernel-PowerKernel-BootWinlogon等のイベントを出勤・退勤時刻として利用できそうである。

PowerShellでGet-WinEventを使えばWindowsのシステムログを取得できることがわかった。マニュアルによるとProviderNameオプションで特定のログを抽出できそうだ。ListProviderオプションで目当てのProviderを列挙する。

$ Get-WinEvent -ListProvider *Kernel*
Name     : Microsoft-Windows-Kernel-Licensing-StartServiceTrigger
LogLinks : {}
Opcodes  : {}
Tasks    : {}

Name     : Microsoft-Windows-Kernel-XDV
LogLinks : {Microsoft-Windows-Kernel-XDV/Analytic, System}
Opcodes  : {win:Start, win:Stop}
Tasks    : {}
...

今回はイベントビューアで目星をつけた次のProviderのログを対象とする。

知りたいのはログが生成された時刻だけなのでSelect-Objectで当該列のみ抽出する。

$ Get-WinEvent -ProviderName `
    Microsoft-Windows-Kernel-Boot, `
    Microsoft-Windows-Kernel-General, `
    Microsoft-Windows-Kernel-Power | `
  Select-Object -Property TimeCreated

  TimeCreated
-----------
  2022/12/01 10:45:25
  2022/12/01 10:44:56
  ...

PowerShellに詳しい人なら各日付の最小値、最大値(即ち、出勤時刻、退勤時刻)のみ出力するように修正できそうであるが、PowerShellでの作業はここまででも十分だろう。ここからS式に変換すれば勤怠の自動生成まで実現できるのだが、飽きたのでここまでとする。