|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » PowerShell - Посчитать время с учётом рабочих часов |
|
|
PowerShell - Посчитать время с учётом рабочих часов
|
Новый участник Сообщения: 22 |
Всем привет!
Стоит задача посчитать сколько было затрачено времени в текущей задаче. В целом всё просто, использовал командлет Timespan, взял время старта, время конца, сложил и получил ответ: Во вложении вывод. Однако, есть нюанс, который заключается в SLA. Время останавливается на нерабочих часах. То есть должно на 19:00 время остановиться и в 9:00 следующего дня утром снова возобновиться. По итогу вывод должен быть не на 2 часа 17 минут, а просто на 1 час 32 минуты. Следовательно, если время будет начинаться, скажем с 20:00 часов, то считать он должен с 9:00 и до времени, когда будет $END_TIME_TICKET (например конечная дата 12:00 и того 3 часа итог, а не 16 часов, как он посчитается всё время). И вот как посчитать время с учётом рабочих часов, вообще никаких идей нет, может у кого будут мысли как это сделать. Заранее спасибо!!! p.s. а и да, ещё нужно как-то учесть производственный календарь... в общем время должно считать строго в пороге от 9:00 до 19:00 буднего дня, а оставшееся выкидывать |
|
Отправлено: 12:22, 21-12-2022 |
Crazy Сообщения: 1218
|
Профиль | Отправить PM | Цитировать Для будних дней:
$k = new-timespan -h 14 if (($x = $END_TIME_TICKET.day - $START_TIME_TICKET.day)){ $END_TIME_TICKET - $START_TIME_TICKET - $x*$k } else { $END_TIME_TICKET - $START_TIME_TICKET } Цитата Njem:
![]() |
|
------- Отправлено: 13:12, 21-12-2022 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Новый участник Сообщения: 22
|
Профиль | Отправить PM | Цитировать Цитата YuS_2:
а если время будет начинаться с 7:00 утра, он ведь всё равно посчитает его с 7:00, а не с 9:00 как должен(( p.s. причём вот, есть живой пример сейчас: время начинается с 16:37, а заканчивается на следующий день в 19:37. Считает 13 часов, так как отнимает 14 часов, НО, 37 минут же идут вне рабочего временни, значит должно быть 12 часов 23 минуты. И вот как сделать, чтобы он когда достигал 19:00 понимал, что это уже стоп... ![]() |
|
Последний раз редактировалось Njem, 21-12-2022 в 15:57. Отправлено: 13:47, 21-12-2022 | #3 |
Crazy Сообщения: 1218
|
Профиль | Отправить PM | Цитировать Цитата Njem:
Пример для одного дня, без перехода на новую дату: $start = new-timespan -h 9 $end = new-timespan -h 19 $k = new-timespan -h 14 $time = new-timespan if (!($x = $END_TIME_TICKET.day - $START_TIME_TICKET.day)){ if($END_TIME_TICKET.timeofday.totalhours -ge $end.totalhours -and $START_TIME_TICKET.timeofday.totalhours -lt $start.totalhours){ $time = $end - $start } elseif ($END_TIME_TICKET.timeofday.totalhours -ge $end.totalhours -and $START_TIME_TICKET.timeofday.totalhours -ge $start.totalhours){ $time = $end - $START_TIME_TICKET.timeofday } elseif ($END_TIME_TICKET.timeofday.totalhours -le $end.totalhours -and $START_TIME_TICKET.timeofday.totalhours -lt $start.totalhours){ $time = $END_TIME_TICKET.timeofday - $start } elseif ($END_TIME_TICKET.timeofday.totalhours -le $end.totalhours -and $START_TIME_TICKET.timeofday.totalhours -ge $start.totalhours) { $time = $END_TIME_TICKET.timeofday - $START_TIME_TICKET.timeofday } } $time В общем, остальные возможные комбинации, предлагаю обдумывать самостоятельно... |
|
------- Последний раз редактировалось YuS_2, 21-12-2022 в 17:47. Отправлено: 17:12, 21-12-2022 | #4 |
Crazy Сообщения: 1218
|
Профиль | Отправить PM | Цитировать Njem,
В общем, накидал тут пример реализации логики для будней: script.ps1
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), [timespan]$endwork = $(new-timespan -h 19), [timespan]$fullwork = $(new-timespan -h 10) ) function get-timework { param ( [datetime]$stt, # старт [datetime]$ett, # стоп [timespan]$start, # начало рабочего периода [timespan]$end , # конец рабочего периода [timespan]$m # полный рабочий период ) $x = $ett.day - $stt.day # количество дней между стартом и стопом $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 (!$x -and $re -le $rs) { write-host Ошибка! Проверьте данные '$stt - старт/ $ett - стоп' -for red break } if (!$x -and $sdw -notin $h -and $edw -notin $h -and $re -gt $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 -notin $h -and $edw -notin $h) { 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 -m $fullwork Пример запуска: Для ориентирования, как реализуется логика, приведу табличку: 2022-12-22 16-1-39.png Выходные и праздники не учитываются... попробуйте их реализовать, отталкиваясь от логики будней... |
|
------- Последний раз редактировалось YuS_2, 22-12-2022 в 14:40. Причина: Исправил номера дней недели от 0 до 6 Отправлено: 13:03, 22-12-2022 | #5 |
Новый участник Сообщения: 22
|
Профиль | Отправить PM | Цитировать Цитата YuS_2:
а я тут сижу второй день пытаясь математически всё это рассчитать) пока что логика тяжело даётся) думаю с этим намного проще будет!) Цитата YuS_2:
сейчас всё посмотрю, спасибо ещё раз!!!) работа с числами всегда тяжело даётся для меня ![]() |
||
Отправлено: 13:19, 22-12-2022 | #6 |
Crazy Сообщения: 1218
|
Профиль | Отправить PM | Цитировать Цитата Njem:
- выполнение условия будет означать переход через выходные, кроме того и старт, и стоп были осуществлены в будний день... только при реализации, надо учесть все нюансы (один или два выходных, момент старта и стопа и т.д.), в общем поле для размышлений есть... А вот для праздников, возможно, придется использовать какой-либо список, тот же csv, либо прямо в скрипте его организовать... |
|
------- Отправлено: 13:36, 22-12-2022 | #7 |
Новый участник Сообщения: 22
|
Профиль | Отправить PM | Цитировать Цитата YuS_2:
Цитата YuS_2:
|
||
Отправлено: 13:40, 22-12-2022 | #8 |
Crazy Сообщения: 1218
|
Профиль | Отправить PM | Цитировать Njem, небольшая поправка
неправильно был указан номер воскресенья... должен был быть 0, т.е. 6 - суббота, 0 - воскресенье в скрипте исправил... |
------- Отправлено: 14:44, 22-12-2022 | #9 |
Crazy Сообщения: 1218
|
Профиль | Отправить PM | Цитировать Ещё вариант, в котором поправлены ошибки и добавлен учет выходных:
script.ps1
# Пример работы со временем. Учет времени только в рабочее время (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 |
------- Последний раз редактировалось YuS_2, 24-12-2022 в 11:39. Отправлено: 18:58, 23-12-2022 | #10 |
|
![]() |
Участник сейчас на форуме |
![]() |
Участник вне форума |
![]() |
Автор темы |
![]() |
Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
2019 - [решено] Excel. Неправильное суммирование рабочих часов | Tolea3 | Microsoft Office (Word, Excel, Outlook и т.д.) | 12 | 28-04-2020 17:20 | |
[решено] Как посчитать время работа программы | vk_k14m@vk | Хочу все знать | 6 | 04-06-2019 15:47 | |
Flash - Как посчитать время записи файлов на флешку | alleclf | Накопители (SSD, HDD, USB Flash) | 1 | 01-11-2016 18:39 | |
Слетает дата и время на рабочих станциях | Diman1989_19 | Microsoft Windows NT/2000/2003 | 7 | 09-07-2014 09:45 | |
сбрасывается время РОВНО на 9 часов назад! | whattaff | Непонятные проблемы с Железом | 4 | 15-10-2010 21:26 |
|