LoginSignup
24
25

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-06-30

勤務表作成

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

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

最初に実行結果とか

今月の生勤怠
image
先月の均し勤怠
image

手順

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

1.PowerShellコードをコピペ

以下のコードをマルっとコピーし、適当な場所に「.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を起動
上記1で保存した場所に移動
 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]
Powershellを楽に実行してもらうには

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

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

24
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
25