Search code examples
powershelldatetimedate-range

How to split a date range into monthly subranges in PowerShell?


In Powershell, assuming:

$rangeFrom = "2020-03-01" 
$rangeTo  =  "2020-05-13" 

How could I obtain:

$monthRange[0] = "2020-03-01","2020-03-31"
$monthRange[1] = "2020-04-01","2020-04-30"
$monthRange[2] = "2020-05-01","2020-05-13"

Dates will be used in a loop as strings (from/to) on commands that do not support more than one month in range, such as:

myCommand -From $rangeFrom -To $rangeTo # keep this in one month range

Solution

  • By using DateTime objects you can solve the most trouble, like calculating the last day of a month or iterating over dates. You can use the following code to solve your problem:

    $rangeFrom = "2019-12-15" 
    $rangeTo   = "2020-05-13"
    
    $monthRange = @()
    
    $dateFrom = Get-Date $rangeFrom
    $dateTo = Get-Date $rangeTo
    $dateCur = Get-Date $dateFrom -Day 1
    while ($dateCur -lt $dateTo) {
        if (($dateCur.Year -eq $dateFrom.Year) -and ($dateCur.Month -eq $dateFrom.Month)) {
            $dateBegin = $dateFrom # First month exception
        } else {
            $dateBegin = $dateCur
        }
        if (($dateCur.Year -eq $dateTo.Year) -and ($dateCur.Month -eq $dateTo.Month)) {
            $dateEnd = $dateTo # Last month exception
        } else {
            $dateEnd = $dateCur.AddMonths(1).AddDays(-1)
        }
        $monthRange += [Tuple]::Create($dateBegin.toString('yyyy-MM-dd'), $dateEnd.toString('yyyy-MM-dd'))
        $dateCur = $dateCur.AddMonths(1)
    }
    $monthRange
    

    Output:

    Item1      Item2      Length
    -----      -----      ------
    2019-12-15 2019-12-31      2
    2020-01-01 2020-01-31      2
    2020-02-01 2020-02-29      2
    2020-03-01 2020-03-31      2
    2020-04-01 2020-04-30      2
    2020-05-01 2020-05-13      2
    

    You can access individual elements like this:

    $monthRange[2].Item2
    

    Output:

    2020-02-29