How to Run PowerShell Code Only During Certain Times
When you have a PowerShell command running inside a loop, you may not want it to execute continuously. For example, you might want a script to run only during business hours, between scheduled maintenance windows, or during a specific overnight period.
PowerShell makes this straightforward by comparing the current time with a start and end time.
Checking Whether the Current Time Is Within a Range
The current time can be retrieved with:
(Get-Date).TimeOfDay
This returns the current time as a TimeSpan, which can be compared with other TimeSpan values.
The following example runs code between 9:00 AM and 5:00 PM:
while ($true) {
$currentTime = (Get-Date).TimeOfDay
$startTime = [TimeSpan]::Parse("09:00")
$endTime = [TimeSpan]::Parse("17:00")
if ($currentTime -ge $startTime -and $currentTime -lt $endTime) {
# Code to execute between 09:00 and 17:00
Write-Host "Running scheduled code"
}
Start-Sleep -Seconds 30
}
In this example:
-gemeans “greater than or equal to”-ltmeans “less than”- The code runs when the current time is at or after 9:00 AM and before 5:00 PM
- The loop pauses for 30 seconds before checking again
The code will execute during every loop iteration while the current time is within the specified range.
Including the End Time
The previous example excludes the end time. If the code should also run at exactly 5:00 PM, use -le instead:
if ($currentTime -ge $startTime -and $currentTime -le $endTime) {
# Code to execute through 17:00
}
Handling Time Ranges That Cross Midnight
A simple comparison works when the start time comes before the end time on the same day. However, a range such as 10:00 PM to 2:00 AM crosses midnight and requires slightly different logic.
while ($true) {
$currentTime = (Get-Date).TimeOfDay
$startTime = [TimeSpan]::Parse("22:00")
$endTime = [TimeSpan]::Parse("02:00")
$withinRange =
if ($startTime -le $endTime) {
$currentTime -ge $startTime -and $currentTime -lt $endTime
}
else {
$currentTime -ge $startTime -or $currentTime -lt $endTime
}
if ($withinRange) {
# Code to execute between 22:00 and 02:00
Write-Host "Running scheduled code"
}
Start-Sleep -Seconds 30
}
The important difference is the use of -or when the range crosses midnight. A time is within the range if it is:
- At or after 10:00 PM, or
- Before 2:00 AM
This allows the script to correctly handle both sides of midnight.
Running the Code Only Once Per Time Window
If the loop runs every few seconds or minutes, the code inside the if statement will also run repeatedly. To execute it only once during the time window, use a Boolean flag:
$hasRun = $false
while ($true) {
$currentTime = (Get-Date).TimeOfDay
$startTime = [TimeSpan]::Parse("09:00")
$endTime = [TimeSpan]::Parse("17:00")
$withinRange =
$currentTime -ge $startTime -and
$currentTime -lt $endTime
if ($withinRange -and -not $hasRun) {
# Code to execute once
Write-Host "Executing command"
$hasRun = $true
}
elseif (-not $withinRange) {
# Reset the flag for the next time window
$hasRun = $false
}
Start-Sleep -Seconds 30
}
When the script first enters the time window, $hasRun is $false, so the code executes. The flag is then set to $true, preventing the code from running again during that same window.
Once the current time moves outside the window, the flag is reset. This allows the code to execute again during the next scheduled window.
Complete Example
Here is a reusable version that checks the time and runs a command every 30 seconds between 9:00 AM and 5:00 PM:
$startTime = [TimeSpan]::Parse("09:00")
$endTime = [TimeSpan]::Parse("17:00")
while ($true) {
$currentTime = (Get-Date).TimeOfDay
if ($currentTime -ge $startTime -and $currentTime -lt $endTime) {
# Replace this with the command you want to run
Write-Host "The command is running at $(Get-Date)"
}
else {
Write-Host "Outside the allowed time range"
}
Start-Sleep -Seconds 30
}
This pattern is useful for polling scripts, scheduled monitoring tasks, automated maintenance jobs, and any PowerShell process that should operate only during specific hours.