script.ps1
[spoiler]Код: [/spoiler]
Код: Выделить всё
# Пример работы со временем. Учет времени только в рабочее время (9:00 - 19:00),
# исключая выходные (суб., вск.).
# .\script.ps1 -stime $(get-date("21.12.2022 19:50")) -etime $(get-date("22.12.2022 17:00"))
param (
[datetime]$stime = $(get-date("21.12.2022 8:00")),
[datetime]$etime = $(get-date("22.12.2022 8:00")),
[timespan]$startwork = $(new-timespan -h 9 -min 0),
[timespan]$endwork = $(new-timespan -h 19 -min 0)
)
function get-timework {
param (
[datetime]$stt, # старт
[datetime]$ett, # стоп
[timespan]$start, # начало рабочего периода
[timespan]$end # конец рабочего периода
)
function get-weekend {
param (
[datetime]$sd,
[datetime]$ed,
[int[]]$weekend = @(6,0)
)
$sub = ($ed.date - $sd.date).days
$arr = @()
for ($i = 0; $i -le $sub;$i++){
#формируем массив выходных за период, для дальнейшего подсчета пар
if ($sd.adddays($i).dayofweek.value__ -in $weekend){
$arr += $sd.adddays($i).dayofweek.value__
}
}
if ($arr){
$out = ($arr.where({$_ -eq $weekend[0]},5)|%{$_.count}|sort -d)[0]
} else {$out = 0}
return $out
}
if ($ett -le $stt) {
write-host Ошибка! Проверьте данные '$stt - старт/ $ett - стоп' -for red
break
}
$m = new-timespan -h ($end - $start).totalhours
$x = ($ett.date - $stt.date).days # количество дней между стартом и стопом
$w, $h = @(1,2,3,4,5), @(6,0) # будни, выходные (суббота и воскресенье)
# укорачиваем код до названия переменных:
$sdw,$edw = $stt.dayofweek.value__,$ett.dayofweek.value__ # номер дня недели для старт и стоп
$rs,$re = $stt.timeofday.totalminutes,$ett.timeofday.totalminutes
$s,$e = $start.totalminutes,$end.totalminutes
$minutes = $m.totalminutes
# Для выходных:
if ($edw -in $h){
# Если стоп в выходной день (перенос стопа на пон. 0:00)
if (!$edw){$ds = 1} else {$ds = 2}
$ett = $ett.addminutes(-$ett.timeofday.totalminutes)
$ett = $ett.adddays($ds)
$edw,$re = $ett.dayofweek.value__,$ett.timeofday.totalminutes
$x = ($ett.date - $stt.date).days
}
if ($sdw -in $h){
# Если старт в выходной день (перенос старта на пон. 0:00)
if (!$sdw){$ds = 1} else {$ds = 2}
$stt = $stt.addminutes(-$stt.timeofday.totalminutes)
$stt = $stt.adddays($ds)
$sdw,$rs = $stt.dayofweek.value__,$stt.timeofday.totalminutes
$x = ($ett.date - $stt.date).days
}
$kw = get-weekend $stt $ett # количество пар выходных между стартом и стопом
if ($stt.dayofweek.value__ -in $h -and $kw){$kw--}
if ($x -and $sdw -in $w -and $edw -in $w){
# Если есть полный переход через выходные,
# старт/стоп в рабочие дни, вычитаем выходные полностью:
$x = $x - 2*$kw
}
# Реализация логики подсчета для будней:
if (!$x -and $sdw -in $w -and $edw -in $w -and $re -ge $rs){
# Если и старт, и стоп в один день
if($rs -lt $s -and $re -gt $e){
$time = new-timespan -min ($minutes)
} elseif (($rs -ge $s -and $rs -le $e) -and $re -gt $e){
$time = new-timespan -min ($e - $rs)
} elseif (($rs -gt $e -and $re -gt $e) -or ($rs -lt $s -and $re -lt $s)){
$time = new-timespan
} elseif ($rs -lt $s -and ($re -ge $s -and $re -le $e)) {
$time = new-timespan -min ($re - $s)
} elseif (($rs -ge $s -and $rs -le $e) -and ($re -ge $s -and $re -le $e)){
$time = new-timespan -min ($re - $rs)
}
} elseif ($x -and $sdw -in $w -and $edw -in $w) {
# Если старт и стоп в разные дни,
if ($rs -lt $s -and $re -gt $e){
$time = new-timespan -min ($minutes * ($x+1))
} elseif (($rs -ge $s -and $rs -le $e) -and $re -gt $e){
$time = new-timespan -min ($e - $rs + $minutes*$x)
} elseif (($rs -gt $e -and $re -gt $e) -or ($rs -lt $s -and $re -lt $s)){
$time = new-timespan -min ($minutes * $x)
} elseif ($rs -lt $s -and ($re -ge $s -and $re -le $e)){
$time = new-timespan -min ($re - $s + $minutes*$x)
} elseif (($rs -ge $s -and $rs -le $e) -and ($re -ge $s -and $re -le $e)){
$time = new-timespan -min ($re - $s + $e - $rs + $minutes*($x-1))
} elseif ($rs -gt $e -and ($re -ge $s -and $re -le $e)) {
$time = new-timespan -min ($re - $s + $minutes*($x-1))
} elseif (($rs -ge $s -and $rs -le $e) -and $re -lt $s){
$time = new-timespan -min ($e - $rs + $minutes*($x-1))
} elseif ($rs -gt $e -and $re -lt $s) {
$time = new-timespan -min ($minutes*($x-1))
}
} else {
write-host Условия не сработали... для будущей разработки. -for cyan
}
return $time
}
get-timework -stt $stime -ett $etime -start $startwork -end $endwork