Get-ClosestToMinute.ps1

function Get-ClosestToMinute {
    <#
    .synopsis
    Returns an object with a timespan that is rounded to the nearest x minute.
     
    .description
    Returns an object with a timespan that is rounded to the nearest x minute,
    specified by the -minute parameter, and rounding up or down depending on
    the value passed to the -boundary parameter.
     
    .example
    PS C:\> Get-ClosestToMinute -timespan '00:12'
 
    initialtimespan nearestminute boundary newtimespan
    --------------- ------------- -------- -----------
           00:12:00 15 5 00:15:00
 
    .EXAMPLE
    PS C:\> Get-ClosestToMinute -timespan 01:12 -minute 30 -boundary 20
     
    initialtimespan nearestminute boundary newtimespan
    --------------- ------------- -------- -----------
           01:12:00 30 20 01:00:00
 
    #>

    [cmdletbinding()]

    param (
        # starting timespan to be rounded to the nearest x minute
        [parameter(
            mandatory,
            valuefrompipeline,
            valuefrompipelinebypropertyname
        )]
        [alias('initialtimespan', 'ts')]
        [timespan] $timespan,

        # the minute to round the timespan to
        [parameter(valuefrompipeline)]
        [alias('nearestminute')]
        [int] $minute = 15,

        # if we're outside the boundary, we aim to go to the next/prev $minute
        [parameter(valuefrompipelinebypropertyname)]
        [validatenotnullorempty()]
        [validatescript({ $_ -ge 0 -and $_ -le $minute })]
        [alias('increaseboundary')]
        [int] $boundary = 5
    )

    process {
        $newts = $timespan
        $minutemod = $timespan.minutes % $minute
        $tsmod = new-timespan -minutes $minutemod
        $tsincrease = new-timespan -minutes ($minute - $minutemod)
        $halfnearestminute = $minute / 2

        write-psfmessage -level verbose -message "calculating new timespan for $newts"
        $newts = if ($minutemod -gt $boundary -and $newts.totalminutes -ge $boundary) {
            $newts.add($tsincrease)
        }
        elseif ($minutemod -le $halfnearestminute -and $newts.totalminutes -ge $halfnearestminute) {
            $newts.subtract($tsmod)
        }
        else {
            $newts.add($tsincrease)
        }

        [pscustomobject]@{
            initialtimespan = $timespan
            nearestminute   = $minute
            boundary        = $boundary
            newtimespan     = $newts
        }
    }
}