PowerShellでカンタンに勤務時間を割り出す方法

#勤務表作成#
みなさん楽しく勤務表付けてますか？
メンドクサイですね。ぼくは楽しんではいないです。

ってことで自社と違う会社名でのネーム下げて働いているSE/PGにはおなじみの勤務表作成で、勤怠時間をイベントビューアーから簡単に割り出す小技を紹介したいと思います。
　※正確にはPCの起動時間～終了時間

#最初に実行結果とか#
今月の生勤怠
![image](https://qiita-image-store.s3.amazonaws.com/0/78880/01a9a40a-6b43-d992-8fbe-5ce4a3cf690a.png)
先月の均し勤怠
![image](https://qiita-image-store.s3.amazonaws.com/0/78880/060671aa-18bc-162e-63c8-eff9be806d07.png)

#手順#

1. PowerShellコードをコピペ
2. cmdから実行
3. コピペして整形

##1.PowerShellコードをコピペ##
以下のコードをマルっとコピーし、適当な場所に「.ps1」で保存してください。

```ps1:gwt.ps1
$target_ym = Read-Host "対象年月は？　yyyyMM";
$make_even = Read-Host "時間を均す？　y/n";

$start_time = New-Object System.DateTime (Get-Date).Year,(Get-Date).Month,1,4,0,0,0;
$ym = 0;
if([int]::TryParse($target_ym,[ref]$ym)){
    try
    {
        $t = [string]::Join("-", ($target_ym.Substring(0, 4), $target_ym.Substring($target_ym.Length - 2, 2), 1));
        $r = [Datetime]::Parse($t);
        $start_time = New-Object System.DateTime $r.Year,$r.Month,1,4,0,0,0;
    }catch{}
}

$write_time = Get-EventLog System -After $start_time -Before $start_time.AddMonths(1) | Select-Object TimeWritten;
#$write_time += Get-EventLog Security -After $start_time -Before $start_time.AddMonths(1) | Select-Object TimeWritten;
$write_time += Get-EventLog Application -After $start_time -Before $start_time.AddMonths(1) | Select-Object TimeWritten;
$write_time = $write_time | Sort-Object TimeWritten;

[string]::Join("`t", ("起動日時", "終了日時", "経過時間", "経過時間-休憩(1H)"));
$ji=$write_time[0].TimeWritten;
for ($i = 1; $i -lt $write_time.Count; $i++) {
    if ($write_time[$i-1].TimeWritten.AddHours(-4).ToShortDateString() -ne ($write_time[$i]).TimeWritten.AddHours(-4).ToShortDateString()) {
        $shi=$write_time[$i-1].TimeWritten;
        if ($make_even -eq "y"){
            $h1 = $ji.AddSeconds(449).Hour;
            $m1 = [math]::Truncate($ji.AddSeconds(449).Minute/15)*15;
            $ji = New-Object System.DateTime $ji.Year,$ji.Month,$ji.Day,$h1,$m1,0,0;
            $h2 = $shi.AddSeconds(449).Hour;
            $m2 = [math]::Truncate($shi.AddSeconds(449).Minute/15)*15;
            $shi = New-Object System.DateTime $shi.Year,$shi.Month,$shi.Day,$h2,$m2,0,0;
        }
        $lap=$shi-$ji;
        $lap2=$shi-$ji.AddHours(1);
        [string]::Join("`t", ($ji.ToString("yyyy/MM/dd HH:mm:ss"), $shi.ToString("yyyy/MM/dd HH:mm:ss"), $lap, $lap2));
        $ji=$write_time[$i].TimeWritten;
    }
}
$shi=$write_time[$i-1].TimeWritten;
if ($make_even -eq "y"){
    $h1 = $ji.AddSeconds(449).Hour;
    $m1 = [math]::Truncate($ji.AddSeconds(449).Minute/15)*15;
    $ji = New-Object System.DateTime $ji.Year,$ji.Month,$ji.Day,$h1,$m1,0,0;
    $h2 = $shi.AddSeconds(449).Hour;
    $m2 = [math]::Truncate($shi.AddSeconds(449).Minute/15)*15;
    $shi = New-Object System.DateTime $shi.Year,$shi.Month,$shi.Day,$h2,$m2,0,0;
}
$lap=$shi-$ji;
$lap2=$shi-$ji.AddHours(1);
[string]::Join("`t", ($ji.ToString("yyyy/MM/dd HH:mm:ss"), $shi.ToString("yyyy/MM/dd HH:mm:ss"), $lap, $lap2));
```

##2.cmdから実行##
cmdを起動
上記１で保存した場所に移動
　`cd c:\work`
以下のコマンドを実行
　`powershell -NoProfile -ExecutionPolicy Unrestricted .\gwt.ps1`

##3.コピペして整形##
  出力された内容を焼くなり煮るなり。。

#残念なこと#
PowerShell上のタブ文字「`t」がcmdの出力ではスペースになっちゃってます。
ちょっと調べましたがよくわかんなかったので諦めました。
　**※この記事を見た有識者からのアドバイスを期待して…**

#入力について#
`対象年月`は`yyyyMM`形式で適切に入力してください。
入力がないか間違えている場合は勝手に当月になります。
`時間を均す`オプションは、~~なぜか当然のように違法に~~切り捨てされる15分未満の時間を生かす機能です。
7分29秒までの切り捨て、切り上げを自動で行ないます。

また職場のPCで起動することを想定しているためSecurityLogは取得していません。
管理者として起動可能な方は16行目のコメントアウト「#」を外して実行すれば対象になります。

#文字化けとかしちゃったら#
コピペして保存した「.ps1」ファイルの文字コードを確認してください。
コマンドプロンプトの標準はSJISのため、ps1ファイルをUTF8辺りで保存しているとエラーになります。
　※サクラエディタ辺りで、ファイル＞名前を付けて保存＞文字コードセット のあたりを見ればわかるかと
　※cmdの文字コードを変えている酔狂な方なら、言わずもがな自力で何とかしてください

#さいごに#
以下の記事を参考にさせてもらいました。ありがとうございます。

[イベントログからその日の最初と最後のタイムスタンプを抽出するpowershellスクリプト（勤怠管理） [Windows]](http://blog.livedoor.jp/aotaka/archives/51898247.html)
[Powershellを楽に実行してもらうには](http://qiita.com/tomoko523/items/df8e384d32a377381ef9)

PowerShellは正直初めて触ったけど、C#erとしてはちょっと~~キモイ~~ワクワク。

*全てのシステム従事者の助けとなるように。。*