Как найти n-й экземпляр дня недели в данном месяце (аналитическое решение в Powershell) - PullRequest
0 голосов
/ 06 июля 2019

Мне недавно пришлось решать эту проблему в Powershell, и я был поражен количеством итеративных или просто сложных решений, которые существуют там.В основе этой проблемы лежит простая формула:

Желаемый календарный день = 7 (номер недели) + DOW - DOW (первое число в желаемом месяце)

Как показано ниже, вы затем используетеэто число с указанием года и месяца, чтобы получить дату.

Простые, аналитические решения выполняются намного быстрее, чем итеративные решения, и, как правило, не такие «причудливые», потому что вы полностью понимаете процесс (т. Е. Формула должна быть правильной до того, как вы начнете писать код).

Итак, вот решение, которое я предлагаю.Я надеюсь, что это помогает.

<# Find nth instance of a weekday in a given month
 * PROJECT ID: WeekdayInstance 
 * PURPOSE: 
    This function calculates the dateTime of the nth instance of a given weekday [i.e. in {Sun .. Sat}] in a given month
 * FILE:  Created: 04 Jun 2019 @ 14:57
 *
 * author John S. Abraham
 * copyright SysBuild Inc. 2019
#>
<#
    Parameters:
        dow0  "Desired WeekDay": Value in {0..6}
        wk0   "Desired Week in Month"   : Value in {0..4}
        date0 "A date in the desired month": datetime

        rValue "Date of desired day": String

    Process:
        Calculate dow1 "Weekday of the first of the month of date0": Value in {0..6}
        Calulate rValue = wk0 * 7 +(dow0 + 1) - dow1
        return rValue
#>
<# WORK LOG
[20190704, jsa]: RQ, Design, and Initiate Construction  
#>

Function Get-InstanceofDOW{            
    [CmdletBinding()]            
    param(            
        [parameter(Mandatory=$True, ValueFromPipelineByPropertyName, HelpMessage="Enter the desired Day of Week as a number (Sun=0 .. Sat=6)")]            
        [ValidateRange(0, 6)]            
        [int] $dow0,            

        [parameter(Mandatory=$True, ValueFromPipelineByPropertyName, HelpMessage="Enter the ordinal number of the desired week within the month")]            
        [ValidateRange(0, 4)]            
        [int]$wk0,

        [parameter(Mandatory=$True, ValueFromPipelineByPropertyName, HelpMessage="Enter a date within the desired month")]            
        [System.DateTime]$date0                        
    )
    Process{
        $dateFirstofMonth = Get-Date -Year $date0.Year -Month $date0.Month -Day 01
        $dow1 = $dateFirstofMonth.DayOfWeek
        $dayInstance  = 7 * $wk0 + ($dow0+1) -$dow1 
        $rValue = Get-Date -Year $date0.Year -Month $date0.Month -Day $dayInstance
    }         
    End {
    <# Output as a string with no time component, since time is not relavant #>
        $culture = Get-Culture
        return $rValue.ToString($culture.DateTimeFormat.ShortDatePattern)
    }            
}

<# TEST: Determine the second Saturday in DEC 2019 #>
Get-InstanceofDOW -dow0 6 -wk0 1 -date0 2019-12-30T13:23:56 

...