Gordon
Gordon

Reputation: 6863

Culture based formatting of time variable

In this example it seems to me that the first two outputs should match, giving me formatting based on my defined culture. The last should be different because French formatting is different. Instead, the last two are the same, and are both getting some kind of default formatting. So, how do I do Culture based formatting when the time is a variable rather than formatting directly with Get-Date? It seems like it should be the same, but it's not.

get-date -format ((Get-Culture).DateTimeFormat.FullDateTimePattern)

$time = Get-Date
$pattern = 'FullDateTimePattern'
$formattedTime = $time -f (Get-Culture).DateTimeFormat.$pattern
Write-Host "$formattedTime"

$culture = New-Object system.globalization.cultureinfo('fr-FR') 
$formattedTime = $time -f ($culture).DateTimeFormat.$pattern
Write-Host "$formattedTime"

The output I get is

July 9, 2019 11:22:01 AM
07/09/2019 11:22:01
07/09/2019 11:22:01

What I want to get is

July 9, 2019 11:26:46 AM
July 9, 2019 11:26:46 AM                 
Tuesday 9 July 2019 11:26:46 

EDIT: So, based on I.T Delinquent's response, I tried this

$pattern = 'longDateTimePattern'
$date = Get-Date

$format = (Get-Culture).DateTimeFormat.$pattern
$string = ($date).ToString($format)
Write-Host $string

$culture = New-Object system.globalization.cultureinfo('de-DE')
$format = $culture.DateTimeFormat.$pattern
$string = ($date).ToString($format)
Write-Host $string

And it gave me identical results. Because it's not 'longDateTimePattern', its 'longDatePattern'. Given that the pattern could become a user supplied string, I better validate them.

Upvotes: 3

Views: 997

Answers (2)

mklement0
mklement0

Reputation: 438093

Your attempt at using the -f operator is flawed (see bottom section).

To get the desired output, use the [datetime] type's appropriate .ToString() overload:

$time.ToString($culture.DateTimeFormat.$pattern, $culture)

Passing $culture as the 2nd argument ensures that the formatting is applied in the context of that culture.

If your intent is truly to use a format from another culture and apply it in the context of the current culture, simply omit the 2nd argument (as an alternative to the Get-Date -Format approach in your question):

$time.ToString($culture.DateTimeFormat.$pattern)

If there's no need to involve a different culture, the task becomes much simpler, by way of the standard date-time format strings, where single-character strings such as "D" refer to standard formats, such as LongDatePattern:

$time.ToString("D")

You can also pass these strings to Get-Date -Format

Get-Date -Format D

As for what you tried:

In order for the -f operator to work correctly, your LHS must be a string template with placeholders ({0} for the first one, {1} for the second, ...), to be replaced with the RHS operands.

Using a simple example:

Format the RHS, an [int], as a number with 2 decimal places.
PS> '{0:N2}' -f 1
1.00

Therefore, $time -f (Get-Culture).DateTimeFormat.$pattern doesn't perform (explicit) formatting at all, because the LHS - $time - contains no placeholders.

That is, the RHS is ignored, and the LHS is returned as a string: It is effectively the same as calling $time.ToString() in the context of the invariant culture (because the result of applying the -f operator is always a string and PowerShell uses the invariant culture in many string-related contexts).

While you can incorporate a specific date-time format string into a template-string placeholder - by following the placeholder index with : and a format string, as shown above ({0:N2}) - you cannot also provide a culture context for it.

You'd have to (temporarily) switch to the desired culture first:

# Save the currently effective culture and switch to the French culture
$prev = [cultureinfo]::CurrentCulture
[cultureinfo]::CurrentCulture = 'fr-FR'

# Format with the desired format string.
"{0:$($culture.DateTimeFormat.$pattern)}" -f $time

[cultureinfo]::CurrentCulture = $prev

Upvotes: 2

Mark Harwood
Mark Harwood

Reputation: 2415

I think this has something to do with how the Get-Date is passed using the variable, it seems to lose the format capability. In fact, if you try using Write-Host ($date -Format $format) gives an error:

Unexpected token '$format' in expression or statement

Here are my setup variables:

$pattern = 'FullDateTimePattern'
$format = (Get-Culture).DateTimeFormat.$pattern
$date = Get-Date

As stated above, using Write-Host ($date -f $format) and incorrectly outputs 07/09/2019 12:24:38. However, using any of the below options does work and correctly outputs 09 July 2019 12:24:38:

Write-Host (Get-Date -Format $format)
Write-Host (Get-Date).ToString($format)
Write-Host ($date).ToString($format)

Hope this helps :)

Upvotes: -1

Related Questions