如何在powershell中计算X个工作日?

时间:2015-01-29 19:46:01

标签: powershell counting

有人能帮助我使用PowerShell脚本,从当前日期算起X个工作日吗?该脚本应该询问返回计算的工作日数,输出将是某种日期。

示例:我想知道我需要回溯多少个日历日才能获得20个工作日。所以我输入数字20,输出将是12/31/2014。因此,为了获得20个工作日,我需要从2014年12月31日开始计算(从今天到12月31日之间有一天假期(2015年1月1日)。) 工作日是星期一至星期五,美国法定假日除外。

我发现很多类似的代码可以计算两天之间的天数,例如http://powershell.com/cs/blogs/tips/archive/2014/07/07/finding-dates-between-two-dates.aspx

或者这个 http://www.integrationtrench.com/2014/05/counting-days-with-powershell.html

但是没有代码可以完全满足我的需要。

感谢您的帮助。

威乐

这是我试图修改的代码......

$startdate = (Get-Date).date
$enddate = Get-Date -Date '2014-12-20'

$New_Years_Day2014 = Get-Date -Date '2014-01-01'
$Martin_Luther_King2014 = Get-Date -Date '2014-01-20'
$Washingtons_Birthday2014 = Get-Date -Date '2014-02-17'
$Good_Friday2014 = Get-Date -Date '2014-04-18'
$Memorial_Day2014 = Get-Date -Date '2014-05-26'
$Independence_Day2014 = Get-Date -Date '2014-07-04'
$Labor_Day2014 = Get-Date -Date '2014-09-01'
$Thanksgiving_Day2014 = Get-Date -Date '2014-11-27'
$Christmas2014 = Get-Date -Date '2014-12-25'
$New_Years_Day2015 = Get-Date -Date '2015-01-01'
$Martin_Luther_King2015 = Get-Date -Date '2015-01-19'
$Washingtons_Birthday2015 = Get-Date -Date '2015-02-16'
$Good_Friday2015 = Get-Date -Date '2015-04-03'
$Memorial_Day2015 = Get-Date -Date '2015-05-25'
$Independence_Day2015 = Get-Date -Date '2015-07-03'
$Labor_Day2015 = Get-Date -Date '2015-09-07'
$Thanksgiving_Day2015 = Get-Date -Date '2015-11-26'
$Christmas2015 = Get-Date -Date '2015-12-25'

 $difference = New-TimeSpan -Start $startdate -End $enddate
 "Days in all: " + $difference.Days

 $days = [Math]::Ceiling($difference.TotalDays)+1

 $workdays = 0..$days | ForEach-Object {
 $startdate
 $startdate = $startdate.AddDays(1)
 } |
 Where-Object { $_.DayOfWeek -gt 0 -and $_.DayOfWeek -lt 6 -and  $startdate -ne $New_Years_Day2014 -and $startdate -ne $Martin_Luther_King2014 -and $startdate -ne $Washingtons_Birthday2014 -and $startdate -ne $Good_Friday2014 -and $startdate -ne $Memorial_Day2014 -and $startdate -ne $Independence_Day2014 -and $startdate -ne $Labor_Day2014 -and $startdate -ne $Thanksgiving_Day2014 -and $startdate -ne $Christmas2014 -and  $startdate -ne $New_Years_Day2015 -and $startdate -ne $Martin_Luther_King2015 -and $startdate -ne $Washingtons_Birthday2015 -and $startdate -ne $Good_Friday2015 -and $startdate -ne $Memorial_Day2015 -and $startdate -ne $Independence_Day2015 -and $startdate -ne $Labor_Day2015 -and $startdate -ne $Thanksgiving_Day2015 -and $startdate -ne $Christmas2015} |
 Measure-Object |
 Select-Object -ExpandProperty Count

 "Workdays: $workdays"

1 个答案:

答案 0 :(得分:1)

此功能将采用两个值。第一个是你正在寻找日期匹配的工作天数。第二个是可选的,允许您指定开始日期。如果省略今天使用的日期。

Function Get-WorkingDay{
    param(
        [Parameter(Mandatory=$True,Position=1)]
        [int]$maxWorkingDays,
        [Parameter(Mandatory=$False,Position=2)]
        [datetime]$startDate = (Get-Date).Date
    )

    $holidays = @(
        (Get-Date -Date '2014-01-01'),            # New_Years_Day2014
        (Get-Date -Date '2014-01-20'),            # Martin_Luther_King2014
        (Get-Date -Date '2014-02-17'),            # Washingtons_Birthday2014
        (Get-Date -Date '2014-04-18'),            # Good_Friday2014 
        (Get-Date -Date '2014-05-26'),            # Memorial_Day2014 
        (Get-Date -Date '2014-07-04'),            # Independence_Day2014
        (Get-Date -Date '2014-09-01'),            # Labor_Day2014
        (Get-Date -Date '2014-11-27'),            # Thanksgiving_Day2014
        (Get-Date -Date '2014-12-25'),            # Christmas2014
        (Get-Date -Date '2015-01-01'),            # New_Years_Day2015
        (Get-Date -Date '2015-01-19'),            # Martin_Luther_King2015
        (Get-Date -Date '2015-02-16'),            # Washingtons_Birthday2015 
        (Get-Date -Date '2015-04-03'),            # Good_Friday2015 
        (Get-Date -Date '2015-05-25'),            # Memorial_Day2015 
        (Get-Date -Date '2015-07-03'),            # Independence_Day2015
        (Get-Date -Date '2015-09-07'),            # Labor_Day2015 
        (Get-Date -Date '2015-11-26'),            # Thanksgiving_Day2015
        (Get-Date -Date '2015-12-25')             # Christmas2015
    )

    # Count down the working days checking each date as we progress
    $dateIndex = $startDate

    For($workingDayIndex = $maxWorkingDays; $workingDayIndex -gt 0; $workingDayIndex--){
        # Assume the current day is not a working day
        $isWorkingDay = $False

        Do{
            If (("Sunday","Saturday" -contains $dateIndex.DayOfWeek) -or ($holidays -contains $dateIndex)){
                # This is not a working day. Check the next day.
                # Write-Host "$($dateIndex.Date) is a weekend or holiday" -ForegroundColor Red
                $dateIndex = $dateIndex.AddDays(-1)
            } Else {
                # Current $dateIndex is a working day.
                $isWorkingDay = $True
            }
        } While(!$isWorkingDay)

        # Write-Host "Current Date: $($dateIndex.Date). Number of working days left: $workingDayIndex."

        # Set the $dateIndex to the previous day.
        $dateIndex = $dateIndex.AddDays(-1)
    }

    # The last date was the correct one. Re-add the day. 
    $dateIndex.AddDays(1)
}

Get-WorkingDay 10

我们将您的假期日期转换为数组,以便以后更轻松地进行比较。这是一个手动练习,因此您需要确保定期更新日期。

使用变量$maxWorkingDays确定我们需要返回多少个工作日,并$workingDayIndex跟踪进度。我们使用For循环来计算工作日,直到我们到达1.在循环中我们检查前一天是否是工作日。如果没有较小的Do..While循环,则会将日期设置为我们到达工作日。我已经放置了一些注释掉的Write-Host行,可以帮助解释你处于循环位置的位置。

-contains为我们工作,因为我们在比较中使用数组,并且检查是上述数组中的元素之一。 @AnsgarWiechers我发誓我没有从你的链接帖子中窃取条件逻辑。我独立想到了它:)

示例输出今天在这种情况下是 2015年1月31日星期六12:00:00

PS C:\Users\Cameron> Get-WorkingDay 5

Monday, January 26, 2015 12:00:00 AM

PS C:\Users\Cameron> Get-WorkingDay 5 "02/01/2015"

Monday, January 26, 2015 12:00:00 AM

Jan-Feb 2015

PS C:\Users\Cameron> Get-WorkingDay 5 "2014-11-27"

Thursday, November 20, 2014 12:00:00 AM

November 2014 Calendar