Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Gets the next date
function Get-TaskStartDate {
<#
.SYNOPSIS
Get a start date from a string expression.
.DESCRIPTION
Finds the start date from a string expression.
.EXAMPLE
Get-TaskStartDate -Day '1st Monday'
Gets the next occurrence of the first monday of a month.
.EXAMPLE
Get-TaskStartDate -Day Tuesday
Gets the next tuesday in the month.
.EXAMPLE
Get-TaskStartDate -Day '2nd tuesday' -Offset 2
Gets a date two days after the 2nd tuesday of the month.
.EXAMPLE
Get-TaskStartDate -Day 'last fri'
Gets the last friday of the month.
#>
[CmdletBinding()]
param (
# The Day may be an expression, such as 3rd Wednesday, or a day of the week such as Tuesday.
[string]$Day,
# Apply an offset (in days) to the start date.
[int]$Offset
)
function Get-DayInMonth {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[DayOfWeek]$Day,
# The starting point.
[DateTime]$Date = (Get-Date -Day 1),
# Week number
[int]$Week = 1,
# Apply an offset (in days) to the start date.
[int]$Offset,
[switch]$Backwards
)
while ($Date.DayOfWeek -ne $Day) {
$Date = $Date.AddDays(1 * (1, -1)[$Backwards.IsPresent])
}
$Date.AddDays(7 * ($Week - 1) + $Offset)
}
$today = Get-Date
$offSetParam = @{
Offset = $Offset
}
switch -regex ($Day) {
{ $Day -as [DayOfWeek] } {
$start = $today
do {
$date = Get-DayInMonth -Day $Day -Date $start @offSetParam
$start = $start.AddDays(1)
} until ($date -gt $today)
break
}
'^\d+$' {
$date = Get-Date -Day $Day
if ($date -lt $today) {
$date = $date.AddMonths(1)
}
break
}
'^(?<week>\d+)\S* +(?<day>[a-z]+)$' {
if (-not ($matches['day'] -as [DayofWeek])) {
throw 'Unexpected day format'
}
$matches.Remove(0)
$date = Get-DayInMonth @matches -Offset $Offset
if ($date -lt $today) {
$date = Get-DayInMonth @matches -Date (Get-Date -Day 1).AddMonths(1) @offSetParam
}
break
}
'(?<modifier>\w+) +(?<day>[a-z]+)$' {
switch ($matches['modifier']) {
'first' { Get-TaskStartDate ("1st {0}" -f $matches['day']) }
'second' { Get-TaskStartDate ("2nd {0}" -f $matches['day']) }
'third' { Get-TaskStartDate ("3rd {0}" -f $matches['day']) }
'forth' { Get-TaskStartDate ("4th {0}" -f $matches['day']) }
'last' {
$startDate = (Get-Date -Day 1).AddMonths(1).AddDays(-1)
$date = Get-DayInMonth -Day $matches['day'] -Date $startDate -Backwards @offSetParam
if ($date -lt $today) {
$date = Get-DayInMonth -Day $matches['day'] -Date $startDate.AddMonths(1) @offSetParam
}
}
}
}
default {
throw 'Invalid date expression'
}
}
$date.Date
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment