Home > OS >  How to get a list of the 5th of a Given Weekday (Monday, Tuesday, Wednesday, Thursday, Friday, Satur
How to get a list of the 5th of a Given Weekday (Monday, Tuesday, Wednesday, Thursday, Friday, Satur

Time:09-20

I need to be able to create an appointment / meeting in Outlook for the 5th Friday of any given month; but Outlook doesn't offer a way to do this since there are only 3 to 4 months a year which have a 5th of any given day of the week.

Its not a problem to manually create the meeting requests, but short of flipping through a calendar every year, is there a programmatic way to at least find the dates that this applies? Preferably, having a solution in PowerShell would help, since PowerShell is on just about every Windows computer.

CodePudding user response:

Yes, the following function will find all occurrences when their are 5 weeks with a particular day of the week in a given month.

   Function getAllFifthWeekDay(){
    [CmdletBinding()]
    param (
        [Parameter(Position=0)][DayOfWeek]$DayOfWeek='Friday',
        [Parameter(Position=1)][int]$Year=(Get-Date).Year
    )
    [DateTime[]]$output=@()
    $date = Get-Date "01/01/$($Year)"
    #Get First Day of Year on day
    $date = $date.AddDays($(if([int]$DayOfWeek -gt [int]$date.DayOfWeek){
                        $DayOfWeek-[int]$date.DayOfWeek    
                    }else{
                        $DayOfWeek-[int]$date.DayOfWeek 7
                    })) 

    $count = 0;
    $lastMonth = $date.Month;
    do{
        $lastMonth = $date.Month;
        $date = $date.AddDays(7)
        if($lastMonth -ne $date.Month){
            $count = 0
        }
        if($count -gt 3){
            $output  = $date
        }
        $count  = 1;

    } while ($date.Year -eq $Year)
    return $output
}

To run this:

  1. Within Windows Open "Windows Powershell" from your Start Menu.
  2. Paste the code above into the command prompt and press "Enter" to register the function.
  3. Execute the function as follows, substituting the Weekday and Year you're looking for:

getAllFifthWeekDay 'Friday' '2022'

You should see output like the following:

    Friday, April 29, 2022 12:00:00 AM
    Friday, July 29, 2022 12:00:00 AM
    Friday, September 30, 2022 12:00:00 AM
    Friday, December 30, 2022 12:00:00 AM

----------------------- EDIT LATER THAT DAY -----------------------

I actually created a fully working example that will not only find the 5th of a given day in a month, but will actually create a meeting invite for that day so its fully an automated process. Hopefully this helps someone else out.

You execute the code with something like the following:

Create-AppointmentFifthWeek -Subject 'Lunch - Strategic Planning' -StartTime "12:30:00" -DurationInMinutes 120 -Categories "Strategy"

Here is the full code which makes that possible:

Function Create-AppointmentFifthWeek(){
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)][String]$Subject,
        [Parameter(Mandatory=$true)][String]$StartTime,
        [Parameter()][String]$Recipients,
        [Parameter()][String]$Categories,
        [Parameter()][String]$Location,
        [Parameter()][String]$Body=$Subject,
        [Parameter()][int]$ReminderMinutesBeforeStart=15,
        [Parameter()][int]$DurationInMinutes=30,
        [Parameter()][DayOfWeek]$DayOfWeek='Friday',
        [Parameter()][int]$Year=(Get-Date).Year
    )

    foreach($date in $(getAllFifthWeekDay -DayOfWeek $DayOfWeek -Year $Year)){
        $StartDateTime = $date.Add([System.Timespan]::Parse($StartTime)) 
        Create-Appointment -Subject $Subject -Recipients $Recipients -Categories $Categories -Location $Location -Body $Body -ReminderMinutesBeforeStart $ReminderMinutesBeforeStart -DurationInMinutes $DurationInMinutes -MeetingStart $StartDateTime
    }
}


Function getAllFifthWeekDay(){
    [CmdletBinding()]
    param (
        [Parameter(Position=0)][DayOfWeek]$DayOfWeek='Friday',
        [Parameter(Position=1)][int]$Year=(Get-Date).Year
    )
    [DateTime[]]$output=@()
    $date = Get-Date "01/01/$($Year)"
    #Get First Day of Year on day
    $date = $date.AddDays($(if([int]$DayOfWeek -gt [int]$date.DayOfWeek){
                            $DayOfWeek-[int]$date.DayOfWeek    
                        }else{
                            $DayOfWeek-[int]$date.DayOfWeek 7
                        })) 

    $count = 0;
    $lastMonth = $date.Month;
    do{
        $lastMonth = $date.Month;
        $date = $date.AddDays(7)
        if($lastMonth -ne $date.Month){
            $count = 0
        }
        if($count -gt 3){
            $output  = $date
        }
        $count  = 1;

    } while ($date.Year -eq $Year)
    return $output
}


Function Create-Appointment(){
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)][String]$Subject,
        [Parameter(Mandatory=$true)][DateTime]$MeetingStart,
        [Parameter()][String]$Recipients,
        [Parameter()][String]$Categories,
        [Parameter()][String]$Location,
        [Parameter()][String]$Body=$Subject,
        [Parameter()][int]$ReminderMinutesBeforeStart=15,
        [Parameter()][int]$DurationInMinutes=30
    )

    $ol = New-Object -ComObject Outlook.Application
    $meeting = $ol.CreateItem('olAppointmentItem')

    if($ReminderMinutesBeforeStart -gt 0){
        $meeting.ReminderSet = $true
        $meeting.ReminderMinutesBeforeStart = $ReminderMinutesBeforeStart
    }

    if($PSBoundParameters.ContainsKey('Recipients')){
        foreach($email in $Recipients -split ";"){
            if($email -ne ''){
                $meeting.Recipients.Add($email)
            }
        }
        $meeting.MeetingStatus = [Microsoft.Office.Interop.Outlook.OlMeetingStatus]::olMeeting
    } else {
        $meeting.MeetingStatus = [Microsoft.Office.Interop.Outlook.OlMeetingStatus]::olNonMeeting
    }

    if($PSBoundParameters.ContainsKey('Location')){
        $meeting.Location = $Location
    }

    if($PSBoundParameters.ContainsKey('Categories')){
        $meeting.Categories = $Categories
    } 

    $meeting.Subject = $Subject
    $meeting.Body = $Body
    $meeting.Start = $MeetingStart
    $meeting.Duration = $DurationInMinutes
    $meeting.Save()    
    $meeting.Send()    
}

CodePudding user response:

A few loops with a few checks and you got yourself a list of Fridays that are in the 5th week of any month

foreach ($year in 2022..2024) {
    foreach ($month in 1..12) {
        if (($maxDays = [datetime]::DaysInMonth($year, $month)) -gt 28) {
            foreach ($day in 29..$maxDays) {
                if (($date = [datetime]"$year-$month-$day").DayOfWeek -eq [System.DayOfWeek]::Friday) {
                    $date.ToString("D")
                }
            }
        }
    }
}
Friday, April 29, 2022
Friday, July 29, 2022
Friday, September 30, 2022
Friday, December 30, 2022
Friday, March 31, 2023
Friday, June 30, 2023
Friday, September 29, 2023
Friday, December 29, 2023
Friday, March 29, 2024
Friday, May 31, 2024
Friday, August 30, 2024
Friday, November 29, 2024
  • Related