Powershell validate textbox for dates - powershell

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})$

Related

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.

While loop user input

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

Date Time day of the week comparison logic in PowerShell

Date Time objects allow us to perform actions like this:
$CurrentDate = Get-Date
$TextDate = get-date -date "02/10/2016"
if ($TextDate -lt $CurrentDate){
Write-Host "True"
}
else {
Write-Host "False"
}
This outputs "True" because $TextDate is less than $CurrentDate.
Following the same logic, why does the following code output false?
$CurrentDate = Get-Date -UFormat %V
$TextDate = Get-Date -date "02/10/2016"
$TextDate = Get-Date -date $TextDate -UFormat %V
if ($TextDate -lt $CurrentDate){
Write-Host "True"
}
else {
Write-Host "False"
}
The only difference is that we are comparing the week of the year. If you change the comparison to -gt, the code returns True.
Formatted dates are strings, not integers. The string "6" is after the string "11".
This would be the most correct way to do this:
First, decide what the "first week of the year" actually means:
$CalendarWeekRule = [System.Globalization.CalendarWeekRule]::FirstDay;
#$CalendarWeekRule = [System.Globalization.CalendarWeekRule]::FirstFourDayWeek;
#$CalendarWeekRule = [System.Globalization.CalendarWeekRule]::FirstFullWeek;
Then, decide which day of the week is the first day of the week:
$FirstDayOfWeek = [System.DayOfWeek]::Sunday;
#$FirstDayOfWeek = [System.DayOfWeek]::Monday;
#Any day is available
Then you can get your correct week number:
$Today = (Get-Date).Date;
$TodayWeek = [cultureinfo]::InvariantCulture.Calendar.GetWeekOfYear($Today, $CalendarWeekRule, $FirstDayOfWeek);
$TargetDate = Get-Date -Date "2016-02-10";
$TargetWeek = [cultureinfo]::InvariantCulture.Calendar.GetWeekOfYear($TargetDate, $CalendarWeekRule, $FirstDayOfWeek);
if ($TargetWeek -lt $TodayWeek) { $true } else { $false }
Note that if you want a full ISO 8601 week, it's somewhat more complicated.
Because you are comparing string-objects.
(Get-Date -UFormat %V).GetType().FullName
System.String
When comparing strings using -gt and -lt it sorts the strings and because 6 comes after 1, your 6 -lt 11-test returns false.
Both $TextDate and $CurrentDate are of type [string] so what you are evaluating is '6' -lt '11' which will return false. Operators are based on the left side type in PowerShell. So in order to force an integer comparison modify your expression as under
if ([int]$TextDate -lt $CurrentDate)
{
Write-Host "True"
}
else
{
Write-Host "False"
}

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)

Compare Dates in loop

I have a requirement where I need to read a date from a CSV file and compare it to a date variable within the script. However, my code doesn't work when some of the date entries in the CSV file are blank. Any idea how I can store a blank date in [datetime] variable?
Here's the part of my code:
#This is my date variable in script
$InactivityDate = (Get-Date).AddDays(-62).Date
Import-Csv $MyCSV | ForEach {
#This is the date variable i'm reading from csv file
$whenCreated = $_.whenCreated
#This converts value in string variable $whenCreated to [DateTime] format
$ConvertWhenCreated = ([datetime]::ParseExact($whenCreated,"dd/MM/yyyy",$null))
#Comparing dates
if($ConvertWhenCreated -le $InactivityDate)
{
"Account is dormant"
}
Above code works fine when $whenCreated contains some value, but when it's blank PowerShell obviously cannot compare a date variable with blank value :(
The only solution I can see now is to check if $whenCreated is blank and save a very old date like it happens in Excel, e.g.:
if($whenCreated -eq "")
{
$whenCreated = "01/01/1900 00:00:00"
}
Should this be OK or is there another logical solution?
Your problem most likely isn't with the comparison, but with the conversion of the blank value to a date via ParseExact(). If you want accounts with no date treated as dormant you could simply do something like this:
$whenCreated = $_.whenCreated
if ($whenCreated) {
$whenCreated = [DateTime]::ParseExact($whenCreated, 'dd/MM/yyyy', $null)
}
if ($whenCreated -le $InactivityDate) {
'Account is dormant'
}
Checking if an empty string (or $null) is lesser or equal to $InactivityDate will return $true as long as $InactivityDate contains a date.
You already test if the string is empty, which is good. But there is no need to assign a fake old date, you can simply assign $null:
$InactivityDate = (Get-Date).AddDays(-62)
$dateString = "2014-11-01"
if ($dateString) {
$date = Get-Date $dateString
} else {
$date = $null
}
if ($date -le $InactivityDate) {
"Account is dormant"
}