I am trying to create a date/time picker through Windows Forms in Powershell and am having an issue getting the time to work properly.
My goal is to try to round the current time to the nearest 15 minute interval (example: 8:43am to 8:45am) and then add 15 minute intervals to a set time, say 4:30pm. Have those outputted into a picker that people can choose. I have looked at the rounding pieces and I have only seen people who round up and down where I want to round up only:
$FifteenMinutes = (New-TimeSpan -Minutes 15 ).Ticks
$Date = Get-Date
$Ticks = ([Math]::Round($Date.Ticks / $FifteenMinutes, 0) * $FifteenMinutes) -as [long]
[DateTime]$Ticks
Here is my code:
Add-Type -AssemblyName System.Windows.Forms
# Main Form
$mainForm = New-Object System.Windows.Forms.Form
$font = New-Object System.Drawing.Font("Consolas", 13)
$mainForm.Text = "Pick Time Frame"
$mainForm.Font = $font
#$mainForm.ForeColor = "White"
#$mainForm.BackColor = "DarkOliveGreen"
$mainForm.Width = 300
$mainForm.Height = 200
# DatePicker Label
$datePickerLabel = New-Object System.Windows.Forms.Label
$datePickerLabel.Text = "Date"
$datePickerLabel.Location = "15, 10"
$datePickerLabel.Height = 22
$datePickerLabel.Width = 90
$mainForm.Controls.Add($datePickerLabel)
# TimePicker Label
$TimePickerLabel = New-Object System.Windows.Forms.Label
$TimePickerLabel.Text = "Time"
$TimePickerLabel.Location = "15, 45"
$TimePickerLabel.Height = 22
$TimePickerLabel.Width = 90
$mainForm.Controls.Add($TimePickerLabel)
# DatePicker
$datePicker = New-Object System.Windows.Forms.DateTimePicker
$datePicker.Location = "110, 7"
$datePicker.Width = "150"
$datePicker.Format = [windows.forms.datetimepickerFormat]::custom
$datePicker.CustomFormat = "MM/dd/yyyy"
$datepicker.MinDate = Get-Date
$datepicker.MaxDate = (Get-Date).AddDays(2)
$mainForm.Controls.Add($datePicker)
# TimePicker
$TimePicker = New-Object System.Windows.Forms.DateTimePicker
$TimePicker.Location = "110, 42"
$TimePicker.Width = "150"
$TimePicker.Format = [windows.forms.datetimepickerFormat]::custom
$TimePicker.CustomFormat = "HH:mm:ss"
$TimePicker.ShowUpDown = $TRUE
$mainForm.Controls.Add($TimePicker)
# OD Button
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = "15, 130"
$okButton.ForeColor = "Black"
$okButton.BackColor = "White"
$okButton.Text = "OK"
$okButton.add_Click({$mainForm.close()})
$mainForm.Controls.Add($okButton)
[void] $mainForm.ShowDialog()
$datepicker.text
$TimePicker.text
Any help would be much appreciated!
CodePudding user response:
Use [Math]::Ceiling()
instead of [Math]::Round()
to always round up:
$FifteenMinutes = (New-TimeSpan -Minutes 15).Ticks
$Date = Get-Date
[long] $Ticks = ([Math]::Ceiling($Date.Ticks / $FifteenMinutes) * $FifteenMinutes)
# See caveat in bottom section.
[DateTime] $Ticks
To get a list of additional, future times spaced fifteen minutes apart up to and including a given end time, simply use
to iteratively add the interval time span; e.g.:
# Interval, as a [timespan] instance
$15Minutes = [timespan] '0:15' # Alternative to: New-TimeSpan -Minutes 15
# Start time, based on now (streamlined version of the above).
$rawStartTime = Get-Date
$startTime = [datetime]::new(
[long] [Math]::Ceiling($rawStartTime.Ticks / $15Minutes.Ticks) * $15Minutes.Ticks,
$rawStartTime.Kind
)
# Sample end time.
# To end on a fixed hour of the day, use something like (for 8 PM):
# Get-Date $startTime -Hour 20 -Minute 0 -Second 0
$endTime = $startTime.AddHours(2)
# Create an array of time-of-day strings in 15-minute intervals
# between the start and end time, inclusively:
[string[]] $timeStrings =
while ($startTime -le $endTime) {
$startTime.ToString('HH:mm:ss') # format and output
$startTime = $15Minutes
}
Note: using a [datetime]
cast ([DateTime] $Ticks
) yields an unspecified instance, i.e. one whose .Kind
property value is Unspecified
, which means that it is unspecified whether the instance represents a local or a UTC point in time.
To make sure that the input .Kind
is preserved, call the relevant [datetime]
constructor:
[datetime]::new($Ticks, $Date.Kind)