To add to Santiago's helpful answer:
In essence, your goal is to convert between date-time string representations of different cultures, which requires:
(a) first converting the input string to a [datetime] (System.DateTime) instance
(b) then calling the resulting instance's .ToString() method to create a string representation in a given (different) culture's format.
(By contrast, your solution attempt mistakenly tried to conflate these two steps through the use of the static ::ParseExact() method, which, however, only implements step (a) above and, importantly, requires a custom date-time format (pattern) string that matches the input string, along the lines of 'MM/dd/yyyy hh:mm:ss tt'; also note that passing $null as the 2nd argument or omitting that argument means that parsing happens in the context of the current culture, whereas it is advisable to specify the origin culture explicitly, e.g. by passing [cultureinfo] 'en-GB')[1]
In your case, the simplest implementation of (a) is to use a [datetime] cast, given that such casts are invariably based on the invariant culture ([cultureinfo]::InvariantCulture), which is based on, but distinct from, the US-English culture with its month-first format (e.g., 12/16/2024 representing 16 December 2024).
- Thus,
[datetime] '12/16/2024 11:30:23 AM' is sufficient to create a [datetime] instance representing 16 December 2024 with the specified time of day.
In order to robustly implement (b), you must (also) pass a [cultureinfo] (System.Globalization.CultureInfo) instance with the desired target culture to .ToString(),[1] which in your case (the UK-English culture) is [cultureinfo] 'en-GB'; the [cultureinfo] instance (needed only if the current culture is different from the target culture) can be used either alone, so as to get the default date and time format, or in combination with a standard (e.g., 'G') or a custom format string (e.g., 'dd/MM/yyy HH:mm:ss'.
Therefore (a PM time was chosen to illustrate the 24-hour use in the UK culture; all 3 statements produce the same output):
# Use the default date-time representation of the 'en-GB' culture.
([datetime] '12/16/2024 11:30:23 PM').ToString([cultureinfo] 'en-GB')
# -> '16/12/2024 23:30:23' - note the day-first format and the 24-hour format
# The default is equivalent to the 'G' standard date-time format:
([datetime] '12/16/2024 11:30:23 PM').ToString('G', [cultureinfo] 'en-GB')
# -> (same as above)
# In the 'en-GB' culture, the default / 'G' standard format is equivalent to
# the following custom format:
([datetime] '12/16/2024 11:30:23 PM').ToString('dd/MM/yyy HH:mm:ss', [cultureinfo] 'en-GB')
# -> (same as above)
[1] If you neglect to do so - in ::ParseExact() / ::Parse() or .ToString() calls - format-string separators such as / and : may be replaced / interpreted interchangeably with different, culture-appropriate separators based on the current culture (as reflected in [cultureinfo]::CurrentCulture; you may \-escape separators in order to force their literal use).
Similarly, format specifiers for symbolic pieces of information, such as MMM for the month name and tt for the AM/PM indicator, are subject to current-culture interpretation in the absence of an explicit [cultureinfo] instance.
For instance, with culture de-DE (German) in effect,
([datetime] '1970-01-02').ToString('dd/MM/yyy') yields '02.01.1970', i.e. / becomes .
With culture es-MX (Mexican Spanish) in effect,
([datetime] '1970-01-02 13:00').ToString('MMMM tt') yields 'enero p.m.', i.e. the month name is expressed in Spanish, and the PM designator is formatted in all-lowercase, with punctuation.
What am I doing wrong?- you are asking it to parse a date that does not conform to the template you are also passing?convert to UK formatthere's no such thing,DateTimeis a binary value. What you get is a .NET DateTime object that doesn't care about locales. Locales and formats only apply when formatting that binary value to a string, or parsing a string to DateTimeDateTimeobject. You can then easily convert this object to a string for the desired locale anytime (hint: then it's no longer a DateTime), but the best strategy is keeping it a DateTime for as long as possible.