Adding onto Martin's answer, since the third Saturday MUST be between the 15th and 21st of the month (inclusive) we can write a simple one-liner as such:
15..21 | % {get-date -Day $_} | ? {$_.DayOfWeek -eq "Saturday"}
or for a particular year/month (we'll use January), just insert that as such:
15..21 | % {get-date "01/01/2023" -Day $_} | ? {$_.DayOfWeek -eq "Saturday"}
The output is still a DateTime object that can be used however you would like.
I couldn't leave this alone...
Function Get-NthDayofMonth {
[cmdletbinding()]
# This function came about from someone wanting the 3rd Saturday of the month (we'll use January).
# I came up with the following one-liner:
# 15..21 | % {get-date "01/01/2023" -Day $_} | ? {$_.DayOfWeek -eq "Saturday"}
# After that I couldn't leave well enough alone and so created this function.
param(
# Validate the occurrence range
[Parameter(Mandatory = $True, Position = 0)]
[ValidateRange(1,5)]
[Int]$NthOccurrence,
# Validate the day of the week
[Parameter(Mandatory = $True, Position = 1)]
[ValidateSet("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday")]
[String]$DayOfWeek,
# Validate and set month (default current month)
[ValidateRange(1,12)]
[Int]$Month = (Get-Date).Month,
# Validate and set year (default current year)
[ValidateRange(1900,2100)]
[Int]$Year = (Get-Date).Year
)
Begin {
# Each occurrence can ONLY fall within specific dates. We set those ranges here.
Write-Verbose "Getting `$NthOccurrence ($NthOccurrence) range"
# COULD just do $(($NthOccurrence*7)-6)..$($NthOccurrence*7) but I like seeing the ranges in the code
$Nth = switch ($NthOccurrence) {
1 {1..7}
2 {8..14}
3 {15..21}
4 {22..28}
5 {29..31}
}
Write-Verbose "`$NthOccurrence range is: $($Nth[0])..$($Nth[6])"
Write-Verbose "Getting `$Month and `$Year date"
# Get a DateTime object for the selected Month/Year
$MonthYear = [DateTime]::new($Year, $Month, 1)
Write-Verbose $MonthYear
}
Process {
Write-Verbose "Getting occurrence $NthOccurrence of weekday $DayOfWeek in $($MonthYear.ToLongDateString().Split(',')[1].Trim().Split(' ')[0]) of $Year"
# Get the day of the week for each date in range and select the desired one
foreach ($Day in $Nth) {
Get-Date $MonthYear -Day $Day | Where-Object {$_.DayOfWeek -eq $DayOfWeek}
}
}
End {
}
}
Provides this output when used:
PS H:\> Get-NthDayofMonth 4 Saturday -Month 2 -Verbose
VERBOSE: Getting $NthOccurrence (4) range
VERBOSE: $NthOccurrence range is: 22..28
VERBOSE: Getting $Month and $Year date
VERBOSE: 02/01/2023 00:00:00
VERBOSE: Getting occurrence 4 of weekday Saturday in February of 2023
Saturday, February 25, 2023 12:00:00 AM