1

In my script i have a date parameter that need to be in a certain format, that I've solved with validatescript and regex. This works nicely but I want a custom error if a. your date don't validate as DateTime b. your date doesn't validate the regex

Param (
[parameter(mandatory=$false)]
[ValidateScript({
      If ($_ -match "^([0-9]{4}[-]?((0[13-9]|1[012])[-]?(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])[-]?31|02[-]?(0[1-9]|1[0-9]|2[0-8]))|([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00)[-]?02[-]?29)") {
        $True
      }
      else {
        Write-host "The Date is invalid and need to be in this format, 2017-07-25" -ForeGroundColor Yellow
      }
    })]
    [datetime]$date
           )

was thinking using try and catch like

[ValidateScript({
      try {
$_ -notmatch "^([0-9]{4}[-]?((0[13-9]|1[012])[-]?(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])[-]?31|02[-]?(0[1-9]|1[0-9]|2[0-8]))|([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00)[-]?02[-]?29)"
        } catch [System.Management.Automation.ParameterBindingValidationException] {
    Write-host "The Date is invalid and need to be in this format, 2017-07-25" -ForeGroundColor Yellow
        }
)]

any suggestions?

Edit:

Changed it to:

        Param (
            [parameter(mandatory=$false)][alias('d')][string]$date #date in format yyyy-mm-dd
            )

if ($date){
try {get-date($date)}
catch{
 Write-host "The Date is invalid and need to be in this format, yyyy-mm-dd" -ForeGroundColor Yellow
 $date = getdate(read-host)
}
}

works, though if don't obey the format that is requested and go ahead and type for example 070725 again you will get an error. Is there some way to loop it until you get a correct format? maybe a Do Until loop?

4
  • You do not need to explicitly mention the catch type. put like this: catch{ Write-output $_.Exception.Message } It will capture the exception message. That would be enough in your case i believe. Commented Jul 25, 2017 at 9:35
  • 1
    Possible duplicate of PowerShell Custom error from parameters Commented Jul 25, 2017 at 9:42
  • @Anthon It's more like ValidateScript{ try{...}catch{...}} - check out dup flagged answer. Commented Jul 25, 2017 at 9:47
  • @gms0ulman yes a typo, edited. still not catching the error. Commented Jul 25, 2017 at 12:00

2 Answers 2

1

I think you may be going about this the wrong way?

Why not just let the user type whatever he wants? Check if whatever was entered validates as a System.DateTime. Then use $date.ToString("yyyy-MM-dd") to shape it the way you want, and do your regex check on that (if you have to).

Better yet, in my opinion would be to use the properties on the DateTime object for validation, rather than regexing a string.

(Sorry to post this as an answer, it is more of a comment, but I can't do those)

Sign up to request clarification or add additional context in comments.

3 Comments

well since a user could type 170725 and that's acceptable as DateTime but won't work since I need it to be 2017-07-25.
The DateTime object and the format of it are two separate things. Get-Date("170725") returns an error on my system which could be caught. But if the user inputs anything useful that can be translated into a DateTime all you'd have to do to get it in "your format" would be something like: $date = Get-Date(read-host) $date.toString("yyyy-MM-dd") I may just be misunderstanding your case completely ;-)
hmm yes get-date("170725") will fail, but not [datetime]$date=170507 it will accept it but give you a date of 1 jan year 0001 :) think it might be easier your way than my regex way :D
0

TL;DR - go with datetime or string that matches regex, not both.


I don't understand the requirement to both have a datetime and have this datetime in a particular format.

Either you have a datetime object which uses culture-dependant settings when displayed as a string. Or ToString() is used explicitly to get it in the format you want (e.g..ToString("yyyy-MM-dd")).

Or you have a String object which has a specific string form. But cannot be treated as a date, so .ToDateTime() or other methods can be used to convert it a datetime object.

This treatment is also causing an issue in the ValidateScript.

  • Either $date is a valid datetime

    • In which case it is successfully cast as datetime before the ValidateScript is called. And ToString()) will need to be used before you can run rrgex on it.
  • Or $date is an invalid datetime

    • In which case it is unsuccessfully cast as datetime, and a PowerShell error is thrown. Before the ValidateScipt can run and through your custom error.

String

Param (
    [parameter(mandatory=$false)]
    [ValidateScript({
            try{
                $culture = [cultureinfo]::InvariantCulture
                [datetime]::ParseExact($_,"yyyy-MM-dd",$culture)
            }catch{
                throw "The Date is invalid and need to be in this format, 2017-07-25"
            }       
        })
    ]
    [string]$date 
)

Write-Host $date
Write-Host $date.GetType()

# if you actually want a datetime object
$date = [datetime]::ParseExact($date,"yyyy-MM-dd",$culture)

Datetime

[CmdletBinding()]
Param (
    [parameter(mandatory=$false)]
    [datetime]$date 
)

3 Comments

Thanks, It's for a API request which needs to have it as date, so in the request you send 2017-07-25t00:00:00
@Anthon If you don't need to treat it as a datetime at any point - for example, to add days or figure out what month it is etc - you can keep it is as string, and validate using regex, or the built-in ParseExact. Or you can take it as datetime, and use ToString when needed to format it any way you want.
It's seems it must be in datetime format for the API to work correctly. your first suggestion works nicely (see my edit) the only thing that would be nice to have is to loop it until it's valid so you don't for example just press enter. so some kind of catch loop?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.