3

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.

Gordon
  • 6,257
  • 6
  • 36
  • 89
  • Is your intent truly to ask for a _different_ culture's format string and then apply it in the context of the _current_ culture? For instance, if you ask for a German format string that involves month and/or weekday names and you apply that pattern with US-English in effect, for instance, you'll get _English_ names: `(Get-Date).ToString(([cultureinfo] 'de-DE').DateTimeFormat.LongDatePattern)` -> `Tuesday, 9. July 2019`. – mklement0 Jul 09 '19 at 22:24

2 Answers2

2

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
mklement0
  • 382,024
  • 64
  • 607
  • 775
-1

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 :)

I.T Delinquent
  • 2,305
  • 2
  • 16
  • 33
  • There is no `-Format` operator in PowerShell, only `-f`, and that's what the error message complains about (albeit with `'-format'`, not `'$format'`). – mklement0 Jul 09 '19 at 12:02
  • While the workarounds are helpful (assuming the OP truly wants to interpret a different culture's format strings in the context of the current culture), the explanation of the original problem is incorrect and misleading. – mklement0 Jul 09 '19 at 22:26