-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGet-NthWorkingDayOfMonth.ps1
138 lines (105 loc) · 4.81 KB
/
Get-NthWorkingDayOfMonth.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
################################################################################
# Copyright (C) 2020
# Adam Russell <adam[at]thecliguy[dot]co[dot]uk>
# https://www.thecliguy.co.uk
#
# Licensed under the MIT License.
#
################################################################################
# Development Log:
#
# 1.0.0 - 2020-09-12 - Adam Russell
# * Added '-DayOfMonthToExclude' parameter.
#
# 0.1.0 - 2020-01-25 - Adam Russell
# * First release.
#
################################################################################
Function Get-NthWorkingDayOfMonth {
<#
.SYNOPSIS
Gets the Nth working day of a specific month and year.
.DESCRIPTION
Returns the date of the Nth working day in a specified month and year
as a DateTime object.
In the event that there is no Nth working day then a terminating error
is thrown.
By default, the days of a working week are Monday to Friday. This can
customised with the -WorkingDaysOfWeek parameter.
.EXAMPLE
Get-NthWorkingDayOfMonth -Nth 10 -Month 1 -Year 2020
14 January 2020 00:00:00
# Gets the 10th working day of January 2020.
.EXAMPLE
Get-NthWorkingDayOfMonth -Nth 10 -Month 1 -Year 2020 -DayOfMonthToExclude 1
15 January 2020 00:00:00
# Gets the 10th working day of January 2020.
# Excludes the 1st January using the '-DayOfMonthToExclude' parameter.
.EXAMPLE
Get-NthWorkingDayOfMonth -Nth 10 -Month 1 -Year 2020 -WorkingDaysOfWeek (1..4)
14 January 2020 00:00:00
# Gets the 10th working day of January 2020.
# Specifies the days of a working week as Mon-Thu using a range of
# integers, which are cast as System.DayOfWeek.
.EXAMPLE
Get-NthWorkingDayOfMonth -Nth 10 -Month 1 -Year 2020 -WorkingDaysOfWeek Monday, Tuesday, Wednesday, Thursday
16 January 2020 00:00:00
# Gets the 10th working day of January 2020.
# Specifies the days of a working week as Mon-Thu using an array of
# strings, the values of which are cast as System.DayOfWeek.
.EXAMPLE
Get-NthWorkingDayOfMonth -Nth 10 -Month 1 -Year 2020 -WorkingDaysOfWeek ([System.DayOfWeek]::Monday), ([System.DayOfWeek]::Tuesday), ([System.DayOfWeek]::Wednesday), ([System.DayOfWeek]::Thursday)
16 January 2020 00:00:00
# Gets the 10th working day of January 2020.
# Specifies the days of a working week as Mon-Thu using an array of
# System.DayOfWeek enums.
.LINK
https://github.com/thecliguy/Get-NthWorkingDayOfMonth/
https://www.thecliguy.co.uk/2020/01/25/get-the-nth-working-day-of-the-month/
#>
[CmdletBinding()]
param (
[parameter(Mandatory=$True)]
[ValidateRange(1,31)]
[Int]$Nth,
[parameter(Mandatory=$True)]
[ValidateRange(1,12)]
[Int]$Month,
[parameter(Mandatory=$True)]
[ValidateRange(1,9999)]
[Int]$Year,
[parameter(Mandatory=$False)]
[System.DayOfWeek[]]$WorkingDaysOfWeek = 1..5,
[parameter(Mandatory=$False)]
[Int[]]$DayOfMonthToExclude
)
$OrdinalIndicator = Switch -Regex ($Nth) {
'1(1|2|3)$' { 'th'; break }
'.?1$' { 'st'; break }
'.?2$' { 'nd'; break }
'.?3$' { 'rd'; break }
default { 'th'; break }
}
$DaysInMonth = [DateTime]::DaysInMonth($Year, $Month)
$NthCounter = 0
Write-Verbose "Calculating the $($Nth)$($OrdinalIndicator) working day ($($WorkingDaysOfWeek -join ", ")) in $((Get-Culture).DateTimeFormat.GetMonthName($Month)) $($Year)..."
For ($i=1; $i -le $DaysInMonth; $i++) {
$Date = (Get-Date -Month $Month -Year $Year -Day $i).Date
If ($DayOfMonthToExclude -notcontains $Date.Day) {
If ($WorkingDaysOfWeek -contains $Date.DayOfWeek) {
$NthCounter++
Write-Verbose "NthCounter=$($NthCounter): $(Get-Date $Date -Format 'yyyy-MM-dd') $($Date.DayOfWeek)"
}
}
If ($NthCounter -eq $Nth) {
Return $Date
}
}
If ($PSBoundParameters.ContainsKey('DayOfMonthToExclude')) {
$Excluding = ", excluding day(s) of month: $($DayOfMonthToExclude -join ', ')."
}
Else {
$Excluding = "."
}
Throw "There isn't a $($Nth)$($OrdinalIndicator) working day ($($WorkingDaysOfWeek -join ", ")) in $((Get-Culture).DateTimeFormat.GetMonthName($Month)) $($Year)$($Excluding)"
}