0

I need to create a PowerShell script, able to collect some data at each minute. However, this script cannot run during the "technical windows", that are scheduled to occur at the same week days and time. (Ex. every tuesday from 19h00 to 23h00) This schedule information is declared in a file (Ex:.\Schedule.txt):

# SCHEDULE
#
# Periods when the script will not be executed: "Prohibited Period"
# Inform: <Begin_Week_Day>:<Begin_Hour>:<Begin_Minute>:<End_Week_Day>:<End_Hour>:<End_Minute>
#
# Example: Set the Prohibited Period of script execution, every Tuesday, from 8:00 pm to 10:00 pm:
# tue:20:00:tue:22:00
#
# ATTENTION: LIMITED SCHEDULE TO THE SAME DAY OF THE WEEK!
#
qua:10:30:qua:15:40
qui:13:30:qui:23:00

In this example, there are two technical windows scheduled.

I achieved this in the first version, as long as the technical window is on the same day:

$ScheduleFile=Get-Content -Path .\Schedule.txt
$NowDay=Get-Date -Format "ddd"
$NowHour=Get-Date -Format "HH"
$NowMinute=Get-Date -Format "mm"
$NowTime=[single]$NowHour+[single]$NowMinute/60
$PeriodoProibido = $false
Write-Host "========================================================================="
Write-Host "SCHEDULE ANALYSIS: Today is ${NowDay}, ${NowHour}:${NowMinute} (${NowTime})"
foreach ($line in $ScheduleFile){
    if($line.Substring(0,1) -ne "#") {
        Write-Host "-------------------------------------------------------------------------"
        $LineArray = $line.Split(':')
        <#  Schedule:  BEGIN of Prohibited Period: $LineArray[0] = Day   $LineArray[1] = Hour  $LineArray[2] = Minute
                       END   of Prohibited Period: $LineArray[3] = Day   $LineArray[4] = Hour  $LineArray[5] = Minute
        #>
        #   Convert HOUR to decimal format, include minutes.
        $LineArray[1]=[single]$LineArray[1]+[single]$LineArray[2]/60
        $LineArray[4]=[single]$LineArray[4]+[single]$LineArray[5]/60
        Write-Host "Prohibited Period: From "$LineArray[0] $LineArray[1]" to " $LineArray[3] $LineArray[4]
  
        <#  Check if NOW is DAY of Prohibited Period
        ($NowDay -eq $LineArray[0])   > Check if is DAY  do Período Proibido
        ($NowTime -gt $LineArray[1])  > Check if TIME is AFTER  the BEGIN of Prohibited Period
        ($NowTime -lt $LineArray[4])  > Check if TIME is BEFORE the BEGIN of Prohibited Period
        #>
        if($NowDay -eq $LineArray[0] -AND $NowTime -gt $LineArray[1] -AND $NowTime -lt $LineArray[4]){
            Write-Host "NOW IS A PROHIBITED PERIOD! DO NOT RUN THE SCRIPT."
            $PeriodoProibido = $true
        }
        else {
            Write-Host "The script can be executed."
        }
    }
}
Write-Host "-------------------------------------------------------------------------"
if ($PeriodoProibido) {
    Write-Host "CONCLUSION: WE ARE IN THE PROHIBITED PERIOD. DO NOT RUN SCRIPT"
}
else {
    Write-Host "CONCLUSION: You can run the script."
}
Write-Host "========================================================================="


The output is similar to:

=========================================================================
SCHEDULE ANALYSIS: Today is qua, 14:42 (14.7)
-------------------------------------------------------------------------
Prohibited Period: From  qua 10.5  to  qua 15.6666666666667
NOW IS A PROHIBITED PERIOD! DO NOT RUN THE SCRIPT.
-------------------------------------------------------------------------
Prohibited Period: From  qui 13.5  to  qui 23
The script can be executed.
-------------------------------------------------------------------------
CONCLUSION: WE ARE IN THE PROHIBITED PERIOD. DO NOT RUN SCRIPT
=========================================================================

But, if the technical window starts in a day and ends on the next day, this script will not work. I believe should I have to use date format like in Excel or something similar, but I am not sure.

Does some good ideas to get this script better? Thanks!

  • what does `qua` and `qui` mean? – Lee_Dailey Nov 12 '20 at 01:14
  • @Lee_Dailey abbreviated day names.in Portuguese: see `[cultureinfo]::GetCultureInfo('pt').DateTimeFormat.AbbreviatedDayNames` yields `dom seg ter qua qui sex sáb`. – JosefZ Nov 12 '20 at 14:06
  • i recommend you add that info to your Question to avoid confusion. [*grin*] you also likely ought to add a sample time span that overlaps midnite ... that is what you seem to say is the problem. – Lee_Dailey Nov 12 '20 at 14:10

1 Answers1

0

The following function allows "technical windows" defined as time interval in hours

  • at the same weekday, e.g. Fri:10:30:Fri:15:40, or
  • overlapping midnight, e.g. Fri:22:30:Sat:05:40, or
  • covering more days, e.g. Mon:22:30:Wed:05:40 (inside a calendar week), or even Fri:22:30:Mon:05:40 (crossover weekend).

The keynote (basic idea) lays in using and comparing weekday numbers instead of weekday name abbreviations (defined by datetime "ddd" custom format specifier).

The script works for a particular (given) [cultureinfo]::CurrentCulture however enables easy localization as .ToString method as well as AbbreviatedDayNames property allow changing culture-specific formatting information (via [cultureinfo] class)…

Function TestDayTimeInterval {
    [CmdletBinding()]param(
      [Parameter(ValueFromPipeline)]
      [string]$FromTo = 'ne:00:00:ne:00:00', # ddd:HH:mm:ddd:HH:mm
      [Parameter()]
      [datetime]$Date = (Get-Date)
    )
    Write-Verbose "is $($Date.ToString("ddd HH:mm")) in $FromTo`?"
    $fAbbrDayNames = ([System.Globalization.DateTimeFormatInfo]::
            CurrentInfo.AbbreviatedDayNames).ForEach({$_.ToLower()})
        # [System.Globalization.DateTimeFormatInfo]::InvariantInfo.AbbreviatedDayNames
        # [cultureinfo]::GetCultureInfo('pt').DateTimeFormat.AbbreviatedDayNames

    $fTestDay = $fAbbrDayNames.IndexOf( $Date.ToString('ddd').ToLower())
    $fTestTime= [single]$Date.ToString("HH") +
          [math]::Round($Date.ToString("mm")/60,2)

    $aux = $FromTo -split ':'
    $fFromDay = $fAbbrDayNames.IndexOf( $aux[0].ToLower())
    $fFromTime= [single]$aux[1]+[math]::Round($aux[2]/60,2)
    $fUptoDay = $fAbbrDayNames.IndexOf( $aux[3].ToLower())
    $fUptoTime= [single]$aux[4]+[math]::Round($aux[5]/60,2)

    if ( $fFromDay -lt 0 -or $fUptoDay -lt 0 ) {
        Write-Warning "incorrect FromTo [$FromTo]"
        return $false
    }

    if ( $fFromDay -eq $fUptoDay ) {
        return  $fTestDay  -eq $fFromDay  -and
                $fTestTime -ge $fFromTime -and
                $fTestTime -le $fUptoTime
    } elseif ( $fFromDay -lt $fUptoDay ) {
        return ($fTestDay  -gt $fFromDay -and
                $fTestDay  -lt $fUpToDay)  -or
               ($fTestDay  -eq $fFromDay -and
                $fTestTime -ge $fFromTime) -or
               ($fTestDay  -eq $fUpToDay -and
                $fTestTime -le $fUpToTime)
    } else {
        return ($fTestDay  -gt $fFromDay ) -or
               ($fTestDay  -lt $fUpToDay ) -or
               ($fTestDay  -eq $fUpToDay -and
                $fTestTime -le $fUpToTime) -or
               ($fTestDay  -eq $fFromDay -and
                $fTestTime -ge $fFromTime)
    }
}
JosefZ
  • 1,514
  • 1
  • 10
  • 18