Skip to content

Instantly share code, notes, and snippets.

@andyzib
Last active March 20, 2024 20:31
Show Gist options
  • Save andyzib/22c4732627ae9a1d3f1776374980ec9c to your computer and use it in GitHub Desktop.
Save andyzib/22c4732627ae9a1d3f1776374980ec9c to your computer and use it in GitHub Desktop.
PowerShell function for finding the date of the Second Tuesday of July 2017, or whatever date you may need.
Function Get-XDayOfMonth {
<#
.SYNOPSIS
Returns the date of the requested day of the month.
.DESCRIPTION
This function will return the date for searches such as the third Tuesday of July 2018 or the Second Friday in August 2002.
.PARAMETER Find
What day to find: First, Second, Third, Fourth, Last. (Numbers 1-5 are also valid, 1 being First 5 being last.)
.PARAMETER Weekday
What day of the week to look for: Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday.
.PARAMETER Month
The month to search. 1-12.
.PARAMETER Year
The four digit year to search.
.INPUTS
None
.OUTPUTS
None, returns a date object.
.EXAMPLE
Find the second Tuesday of January 2020
Get-XDayOfMonth -Find Second -Weekday Tuesday -Month 1 -Year 2020
.EXAMPLE
Find the last Monday of July 2017
Get-XDayOfMonth -Find Last -Weekday Monday -Month 7 -Year 2017
.EXAMPLE
Find the first Friday of June 2020
Get-XDayOfMonth -Find First -Weekday Friday -Month 6 -Year 2020
#>
Param (
[Parameter(Mandatory=$true)][ValidateSet("First","Second","Third","Fourth","Last","1","2","3","4","5")][string]$Find,
[Parameter(Mandatory=$true)][ValidateSet("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday")][string]$Weekday,
[Parameter(Mandatory=$true)][ValidateRange(1,12)][int]$Month,
[Parameter(Mandatory=$true)][ValidatePattern('^\d{4}$')][int]$Year
)
# Cast $Find to an integer so it's easy to work with.
switch ($Find)
{
"First" { $intFind = 1 }
"Second" { $intFind = 2 }
"Third" { $intFind = 3 }
"Fourth" { $intFind = 4 }
"Last" { $intFind = 5 }
default { $intFind = [int]$Find }
}
# Find all days in the given month that match $Weekday
$allDays = @()
# There aren't 32 days in any month so we make sure we iterate through all days in a month
0..31 | ForEach-Object -Process {
$evaldate = (Get-Date -Year $Year -Month $Month -Day 1).AddDays($_)
if ($evaldate.Month -eq $Month)
{
if ($evaldate.DayOfWeek -eq $Weekday) {
$alldays += $evaldate
}
}
}
#$allDays | FT
# If we found fewer matching days than we are seeking, subtract 1 from $intFind.
# For example, if there are only four Mondays in a month, not Five.
# Or for a really odd ready there are only three Fridays... or some other calendar oddity.
if ($allDays.Count -lt $intFind) { $intFind = $intFind-1 }
#Write-Host "The day you are looking for is $($allDays[$($intFind-1)])."
# Put the result on the PowerShell pipeline.
$allDays[$($intFind-1)]
Return
}
@markdmac
Copy link

markdmac commented Nov 3, 2022

Thank you so much for sharing this function. I have some code that writes to a SharePoint site and we have noticed a time shift when writing dates. This Sunday will be the first DST change since implementing my code and I honestly have no idea if it will break, this function will allow me to create a date range that can determine if the offset I use needs to be changed. Living in Arizona we don't change time zones but where the servers are does, so this will be super helpful.

$StartDST = Get-XDayOfMonth -Find Second -Weekday Sunday -Month 3 -Year (get-Date).Year
$EndDST = Get-XDayOfMonth -Find First -Weekday Sunday -Month 11 -Year (get-Date).Year

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment