<# .SYNOPSIS Plays a ding/timer sound at regular intervals aligned to round period marks (e.g. every 15 min), with an optional offset so the sound plays a few seconds before each mark. .DESCRIPTION Default: period 15 minutes, offset 15 seconds. Notification plays at :14:45, :29:45, :44:45, :59:45. .PARAMETER PeriodMinutes Interval in minutes between notifications (default 15). Defines the "round" marks (0, 15, 30, 45 past the hour). .PARAMETER OffsetSeconds Seconds before each round mark to play the sound (default 15). E.g. 15 means play at XX:14:45, XX:29:45, etc. .EXAMPLE .\interval-timer-ding.ps1 .\interval-timer-ding.ps1 -PeriodMinutes 30 -OffsetSeconds 10 #> param( [int] $PeriodMinutes = 15, [int] $OffsetSeconds = 15 ) $ErrorActionPreference = 'Stop' if ($PeriodMinutes -lt 1) { throw "PeriodMinutes must be >= 1" } if ($OffsetSeconds -lt 0) { throw "OffsetSeconds must be >= 0" } $periodSec = $PeriodMinutes * 60 function Get-SecondsSinceMidnight { $now = Get-Date return $now.Hour * 3600 + $now.Minute * 60 + $now.Second } function Get-NextRingSeconds { $nowSec = Get-SecondsSinceMidnight $nextBoundarySec = [Math]::Ceiling($nowSec / $periodSec) * $periodSec $ringSec = $nextBoundarySec - $OffsetSeconds if ($ringSec -le $nowSec) { $ringSec += $periodSec } return $ringSec } function Get-WaitSeconds { $nowSec = Get-SecondsSinceMidnight $ringSec = Get-NextRingSeconds $wait = $ringSec - $nowSec if ($wait -le 0) { $wait = 1 } return [int]$wait } function Play-Ding { try { [System.Media.SystemSounds]::Asterisk.Play() } catch { [Console]::Beep(800, 200) } } $nextRing = Get-NextRingSeconds $nextH = [Math]::Floor($nextRing / 3600) $nextM = [Math]::Floor(($nextRing % 3600) / 60) $nextS = $nextRing % 60 Write-Host "Period: $PeriodMinutes min, offset: $OffsetSeconds s. Next ding at $($nextH.ToString('00')):$($nextM.ToString('00')):$($nextS.ToString('00')) (then every $PeriodMinutes min). Press Ctrl+C to stop." while ($true) { $waitSec = Get-WaitSeconds if ($waitSec -gt 0) { Start-Sleep -Seconds $waitSec } Play-Ding $ts = Get-Date -Format "HH:mm:ss" Write-Host "[$ts] ding" }