-1

I have power shell code which extracts a date from a different source and converts it:

$dtStart = [DateTime]::ParseExact($StartDate.toString().Substring(0, 10).Trim(), 'M/d/yyyy', $null).ToString('dd/MM/yyyy')

The result for $StartDate.toString().Substring(0, 10).Trim() is 1/7/2025 and the error I see is this:

##[error]Exception calling "ParseExact" with "3" argument(s): "String '1/7/2025 4' was not recognized as a valid DateTime."

This line of code was working fine for many date use cases until this one. Any idea why please ?

8
  • 5
    If .Substring(0, 10).Trim() is 1/7/2025 then why the error says 1/7/2025 4 ? Should be your first self-question Commented Dec 2 at 17:52
  • @SantiagoSquarzon I have misread the error indeed. Going to check why the substring isn't what I expected it to be. Well spotted. Commented Dec 2 at 18:11
  • I see why. I assumed Substring(0, 10) will always catch the date. But with day and month with only one digit it doesn't. I need to find out how to code for that specific use case. Unfortunately I don't control the source I'm extracting from, so I can't use your suggestion above :( Commented Dec 2 at 18:13
  • 3
    @Joly Why cut the string by length? Split the string on first occurrence of a space character instead: $StartDate.Remove($StartDate.IndexOf(' ')) or -split($StartDate)[0]. If $StartDate is already an instance of [Datetime] you can also get a new instance with the time components truncated with: $StartDate.Date Commented Dec 2 at 18:23
  • 2
    Looks like Mathias is spot on, you're already dealing with a DateTime in $StartDate, you can confirm by doing $StartDate.GetType() and see if that's the case. If so you could simply do $StartDate.ToString('dd/MM/yyyy') Commented Dec 2 at 18:47

1 Answer 1

2

If the format of the input date-time string is the same as in your previous question on that topic, e.g. '12/16/2024 11:30:23 AM', then you can simplify your code to the following, taking advantage of the fact that this format is directly recognized by a [datetime] (System.DateTime) cast, irrespective of what culture is currently in effect (as explained in this answer to the linked question):

([datetime] $StartDate.ToString()).ToString('dd/MM/yyyy')

That said, $StartDate already appears to be a [datetime] instance in your code - given that you're calling .ToString() on it (and as since implicitly confirmed by an error message in one of your comments on the question) - so you can simply call (see the next section for details on the culture-related considerations):

# Assumes that $StartDate is a [datetime] instance.
$StartDate.ToString('dd/MM/yyyy')

# More robust alternative, assuming that the target culture is en-GB (UK English)
$StartDate.ToString('dd/MM/yyyy', [cultureinfo] 'en-GB')

# Even simpler (same assumption)
$StartDate.ToString('d', [cultureinfo] 'en-GB')

# Alternative that hard-codes the separators by \-escaping them.
# Note that this is only culture-invariant with *numeric* components.
$StartDate.ToString('dd\/MM\/yyyy')

If $StartDate is a string, after all:

  • No need to call .ToString() on it.

  • To deal with varying lengths of the date part due to single- vs. double-digit components (e.g. '1/7/2025' vs. '01/07/2025'), split the string at the first embedded space character instead of trying to extract a substring of fixed length:

    [DateTime]::ParseExact(
      (-split $StartDate)[0], 
      'M/d/yyyy', 
      $null
    ).ToString('dd/MM/yyyy') # See culture-sensitive considerations below.
    

Note:

  • The unary form of PowerShell's -split operator splits the input string(s) into an array of substrings by any nonempty run of whitespace, and using [0] on the result returns the first substring.

  • Custom date format M/d/yyyy is capable of also parsing double-digit month and day components (including 0-padded ones).

  • You're relying on the current culture both for input parsing (due to using $null as the third argument) and for output formatting (due to passing only a format string, not also a culture, to .ToString(), even though you're clearly transforming from one culture-specific string representation to another.

    • The previously linked answer explains why specifying the culture context explicitly if it differs from the current one makes for a more robust solution; e.g., to transform to a UK English representation, replace .ToString('dd/MM/yyyy') above with
      .ToString('dd/MM/yyyy', [cultureinfo] 'en-GB')
      or, more simply - given that in said culture that format is the default short date pattern, expressed as standard date-time format string d,
      .ToString('d', [cultureinfo] 'en-GB')
      Alternatively - as long as the date-component placeholders solely refer to numeric (rather than symbolic) date components - you can hard-code the separators to ensure their verbatim use, by \-escaping them:
      .ToString('dd\/MM\/yyyy')
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.