While loop user input - powershell

Started a new question since new approach.
old thread here: Catching error in validatescript to custom error message
So I have a param is used for defining a date, it's need to be in format yyyy-mm-dd.
If it's not in the right format, can't verify as datetime or null i want it to keep asking, so was thinking a while loop would work but can't figure out how to finish.
Param (
[parameter(mandatory=$false)][alias('d')][string]$date #date in format yyyy-mm-dd
)
if ($date){
try {get-date($date)}
catch{
While($date -ne $null){
Write-host "The Date is invalid and need to be in this format, yyyy-mm-dd" -ForeGroundColor Yellow
$date = read-host
clear
}
}
}
this kind of works but when right format it ends up as an infinite loop.
Param (
[parameter(mandatory=$false)][alias('d')][string]$date #date in format yyyy-mm-dd
)
if ($date){
do{
try {get-date($date)}
catch{
clear
Write-host "The Date is invalid and need to be in this format, yyyy-mm-dd" -ForeGroundColor Yellow
$date=read-host
}
}
until($date -eq $('^\d{4}-\d{2}-\d{2}$'))
}

You can use function:
param (
[parameter(mandatory=$false)][alias('d')][string]$date #date in format yyyy-mm-dd
)
function IsParsable() { try { get-date($date) } catch { return $false }; return $true }
while (-not (IsParsable))
{
clear
Write-host "The Date is invalid and need to be in this format, yyyy-mm-dd" -ForeGroundColor Yellow
$date = read-host
}
# do whatever you want with $date here

Related

Powershell validate textbox for dates

I'm trying to validate a textbox in Powershell. It should only allow the format dd.MM.yyyy (f.e 22.11.2022). Yet if I type some random characters (f.e 20.2), I get erros instead of a MessageBox.
I've tried something like this:
if($Starttextbox.Text -as [DateTime] -or $Endtextbox.Text -as [DateTime]){
"do something"
}else{
[System.Windows.MessageBox]::Show('Type in correct format','format','Ok','Error')
}
You could create a small function and use a combination of RegEx and Get-Date commandlet, like below.
$StartDate = '22.12.2022' #Good
$EndDate = '22.19.2022' #Bad
function Get-ValidDate { param($DateToCheck)
$DateToCheck -match '(\d{2})\.(\d{2})\.(\d{4})' | Out-Null
if($matches.count -eq 4) {
$ValidDate = $(Get-Date -Date "$($matches[2])-$($matches[1])-$($matches[3])" -Format 'dd.MM.yyyy') 2>> $NULL
}
if($DateToCheck -eq $ValidDate) {
return "GoodDate"
}
}
if((Get-ValidDate $StartDate) -and (Get-ValidDate $EndDate)) {
Write-Host "These are Good Dates!" # DO STUFF
} else {
Write-Host "These are Bad Dates!" # MESSAGEBOX
}
2>>$NULL will remove your Get-Date error messages as all you're looking for is a valid datetime from Get-Date. Function will only return on RegEx match and a valid date.
Here is the regex for dates in the format of dd.mm.yyyy:
^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$

How do I use "DO... Until" for a script date prompt

I am trying to use "DO...Until" in a script to require a user to enter a date. I want to ensure that the date is valid and that the script is able to use that date. I'm fairly new to PS and I'm not certain what I'm doing wrong. It keeps looping even if I put in a valid date.
Do #Start Get Effective Date#
{
$StartDate = Read-Host ' What is the effective date? Format: MM/DD/YYYY '
if ($StartDate -ge 1)
{ Write-Host " You Entered an Effective date of: $StartDate "
}
else
{ Write-Host " Please enter the effective date " -ForegroundColor:Green }
} Until ($StartDate -ge 1)
#End Get Effective Date#
I'm not certain if I am using the wrong '-ge' or not. Once I am able to get a valid date from the user I want the script to move to the next step.
you were close to ;-)
Do{
[string]$StartDate = Read-Host 'What is the effective date? Format: MM/DD/YYYY'
try {
[datetime]$StartDate = [datetime]::ParseExact($startdate, 'MM/dd/yyyy', [cultureinfo]::InvariantCulture)
}
Catch {
}
}
Until ($StartDate -is [DateTime])
The TryParseExact method seems a good fit for what you're looking to achieve, no need for error handling:
[ref] $date = [datetime]::new(0)
do {
$startdate = Read-Host 'What is the effective date? Format: MM/DD/YYYY'
$parsed = [datetime]::TryParseExact($startdate, 'MM/dd/yyyy', [cultureinfo]::InvariantCulture, [Globalization.DateTimeStyles]::None, $date)
} until($parsed)
$date.Value
To offer a concise alternative that relies on the fact that casting a string to [datetime] in PowerShell by default recognizes date strings such as '12/24/2022' (representing 24 December 2022), irrespective of the current culture, because PowerShell's casts, among other contexts, use the invariant culture:
$prompt = 'What is the effective date? Format: MM/DD/YYYY'
# Keep prompting until a valid date is entered.
while (-not ($startDate = try { [datetime] (Read-Host $prompt) } catch {})) {}
"Date entered: "; $startDate
Note: A [datetime] cast also recognizes other string formats, such as '2022-12-24'
Another option would be to create a PowerShell function and accept the date as a parameter. Functions can use a variety of approaches for parameter validation, including script.
https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters?view=powershell-7.2

Compare dates from a string in PowerShell [duplicate]

This question already has answers here:
Compare Get-Date to Date as String
(1 answer)
How to parse (French) full month into datetime object in PowerShell?
(1 answer)
Closed 4 years ago.
$Deldate = "19-06-2018"
$Newdate = "04-06-2018"
I need to check which date is bigger.
if ($Deldate -ge $NewDate) {
write-host "NewDate is bigger"
}
else {
write-host "Deldate is bigger"
}
This is not working for me, and it looks like the format is not "System.DateTime". I'm getting the date values are from an external CSV file. How do I find a solution for this?
You should be able to cast the strings that you have created to the "datetime" type like so:
$Deldate = "19-06-2018"
$Newdate = "04-06-2018"
$Deldate = [datetime]::ParseExact("$Deldate", 'dd-MM-yyyy', $null)
$Newdate = [datetime]::ParseExact("$Newdate", 'dd-MM-yyyy', $null)
if ($Deldate -ge $NewDate) {
write-output "NewDate is bigger than or equal to"
}
else {
write-output "Deldate is bigger"
}
This returns the correct result. You can't simply use the Get-Date cmdlet, since the -Date required parameter also requires that the parameter be of type "DateTime", so you first have to cast the strings to the DateTime type.
Originally Proposed...
I am going to change the format of your date just a hair from DD-MM-YYYY to MM-DD-YYYY:
$Deldate = Get-Date "06-19-2018"
$Newdate = Get-Date "06-04-2018"
if ($Deldate -gt $Newdate) {
'Deldate is larger'
}
else {
'Newdate is larger or equal'
}
I'm creating two date objects based on the respective dates you gave. I'm comparing the two objects; PowerShell knows how to do the date math.
It works fine for U.S. style dates.
After much discussion...
However, for non-US style dates, consider calling datetime's constructor:
$Deldate = New-object 'datetime' -ArgumentList 2018, 6, 19, $null, $null, $null
$Newdate = New-object 'datetime' -ArgumentList 2018, 6, 4, $null, $null, $null
if ($Deldate -gt $Newdate) { 'Deldate is larger' } else { 'Newdate is larger or equal' }
Or, as proposed the [datetime]::ParseExact() method; documented here.
PowerShell is good with dates; it just has to know it's a date...
$Deldate = get-date "19-06-2018"
$Newdate = get-date "04-06-2018"
if ($Deldate -ge $NewDate) {
write-host "NewDate is bigger"
}
else {
write-host "Deldate is bigger"
}
Note: You could cast [datetime]$Deldate ="19-06-2018", but as explained in comments to PowerTip: Convert String into DateTime Object, it's valid only for US date format.

Output the date/time in PowerShell

I want to output the date time in various places in my script for logging so I am doing this:
$b = Get-Date
Write-Output "Backups complete at $b"
# more code here
$c = Get-Date
Write-Output "Backups complete at $c"
I am having to use multiple letters of the alphabet to get the most current date/time.
Is there an easier way of doing this or do I have to reestablish the date each time I want to use it again?
Once you assign the current datetime to a variable, you are capturing the date and time at the moment you ran Get-Date.
Every time you want a new date and time, you need to run it again. You could avoid using a variable:
Write-Output "Backups complete at $(Get-Date)"
Another way to do this is using a format string and since you are using this for logging purpose I would recommend you to write a function because this will allow you to change the format of all log messages in a single place:
function Log-Message
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true, Position=0)]
[string]$LogMessage
)
Write-Output ("{0} - {1}" -f (Get-Date), $LogMessage)
}
Now you can simple log using:
Log-Message "Starting Backups"
Log-Message "Backups Completed"
Output:
22.07.2016 08:31:15 - Starting Backups
22.07.2016 08:31:15 - Backups Completed
Here is simple 1 which allow you format date time in your desire format
$currentTime = Get-Date -format "dd-MMM-yyyy HH:mm:ss"
Write-Host $currentTime " Other log string message "
OUTPUT
17-Aug-2020 10:06:19 other log string message

Formatting Dates in PowerShell

I am currently trying to convert a date from the one displayed in regedit to a readable datetime format. But I do not know how to do this, I'm working with the following:
.GetValue('InstallDate')
And in the .csv file, it display it as this: 20150914
How would I go about converting that into a readable date?
try
[datetime]::Parseexact("20150914","yyyyMMdd", $null )
I'm not sure why you down voted the other answer because he is right on the money with [Datetime]::ParseExact you will have to deal with the null values though
$Regbase = Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\
foreach ($entry in $regBase)
{
$date = (Get-ItemProperty HKLM:\$entry | select installdate).installdate
try
{
[DateTime]::ParseExact($date, "yyyyMMdd", [CultureInfo]::InvariantCulture)
}
catch [exception]
{
"Date Value: $date"
}
}
PowerShell Date is just .NET DateTime. Check DateTime.ParseExact.
[DateTime]::ParseExact("20151010", "yyyyMMdd", [CultureInfo]::InvariantCulture)