PowerShell, formatting values in another culture












6















Is there an easy way in PowerShell to format numbers and the like in another locale? I'm currently writing a few functions to ease SVG generation for me and SVG uses . as a decimal separator, while PowerShell honors my locale settings (de-DE) when converting floating-point numbers to strings.



Is there an easy way to set another locale for a function or so without sticking



.ToString((New-Object Globalization.CultureInfo ""))


after every double variable?



Note: This is about the locale used for formatting, not the format string.



(Side question: Should I use the invariant culture in that case or rather en-US?)



ETA: Well, what I'm trying here is something like the following:



function New-SvgWave([int]$HalfWaves, [double]$Amplitude, [switch]$Upwards) {
"<path d='M0,0q0.5,{0} 1,0{1}v1q-0.5,{2} -1,0{3}z'/>" -f (
$(if ($Upwards) {-$Amplitude} else {$Amplitude}),
("t1,0" * ($HalfWaves - 1)),
$(if ($Upwards -xor ($HalfWaves % 2 -eq 0)) {-$Amplitude} else {$Amplitude}),
("t-1,0" * ($HalfWaves - 1))
)
}


Just a little automation for stuff I tend to write all the time and the double values need to use the decimal point instead of a comma (which they use in my locale).



ETA2: Interesting trivia to add:



PS Home:> $d=1.23
PS Home:> $d
1,23
PS Home:> "$d"
1.23


By putting the variable into a string the set locale doesn't seem to apply, somehow.










share|improve this question

























  • It's interesting that [Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]::InvariantCulture doesn't work..

    – stej
    Mar 4 '10 at 13:35











  • I've had problems only with 1.5 vs. 1,5, that's why inv. culture would work for me. It sounded to me like a batch task, so I thought you could run it in a separate powershell.exe session.

    – stej
    Mar 4 '10 at 14:03











  • @stej: [Threading.Thread]::CurrentThread.CurrentUICulture determines the display language of UI elements, not number formatting; by contrast, it is [Threading.Thread]::CurrentThread.CurrentCulture that determines number formatting; try (on a single line) [Threading.Thread]::CurrentThread.CurrentCulture = 'de-DE'; 1.2.

    – mklement0
    Jun 2 '16 at 22:11






  • 1





    @Joey: As an aside: I can guess that by "ETA" you meant something like "update (later edit)"; however, "ETA" is typically used to represent "Expected Time of Arrival"; what did you intend it to mean?

    – mklement0
    Jun 2 '16 at 23:49











  • @mklement0: “edited to add”

    – Joey
    Jun 3 '16 at 5:34
















6















Is there an easy way in PowerShell to format numbers and the like in another locale? I'm currently writing a few functions to ease SVG generation for me and SVG uses . as a decimal separator, while PowerShell honors my locale settings (de-DE) when converting floating-point numbers to strings.



Is there an easy way to set another locale for a function or so without sticking



.ToString((New-Object Globalization.CultureInfo ""))


after every double variable?



Note: This is about the locale used for formatting, not the format string.



(Side question: Should I use the invariant culture in that case or rather en-US?)



ETA: Well, what I'm trying here is something like the following:



function New-SvgWave([int]$HalfWaves, [double]$Amplitude, [switch]$Upwards) {
"<path d='M0,0q0.5,{0} 1,0{1}v1q-0.5,{2} -1,0{3}z'/>" -f (
$(if ($Upwards) {-$Amplitude} else {$Amplitude}),
("t1,0" * ($HalfWaves - 1)),
$(if ($Upwards -xor ($HalfWaves % 2 -eq 0)) {-$Amplitude} else {$Amplitude}),
("t-1,0" * ($HalfWaves - 1))
)
}


Just a little automation for stuff I tend to write all the time and the double values need to use the decimal point instead of a comma (which they use in my locale).



ETA2: Interesting trivia to add:



PS Home:> $d=1.23
PS Home:> $d
1,23
PS Home:> "$d"
1.23


By putting the variable into a string the set locale doesn't seem to apply, somehow.










share|improve this question

























  • It's interesting that [Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]::InvariantCulture doesn't work..

    – stej
    Mar 4 '10 at 13:35











  • I've had problems only with 1.5 vs. 1,5, that's why inv. culture would work for me. It sounded to me like a batch task, so I thought you could run it in a separate powershell.exe session.

    – stej
    Mar 4 '10 at 14:03











  • @stej: [Threading.Thread]::CurrentThread.CurrentUICulture determines the display language of UI elements, not number formatting; by contrast, it is [Threading.Thread]::CurrentThread.CurrentCulture that determines number formatting; try (on a single line) [Threading.Thread]::CurrentThread.CurrentCulture = 'de-DE'; 1.2.

    – mklement0
    Jun 2 '16 at 22:11






  • 1





    @Joey: As an aside: I can guess that by "ETA" you meant something like "update (later edit)"; however, "ETA" is typically used to represent "Expected Time of Arrival"; what did you intend it to mean?

    – mklement0
    Jun 2 '16 at 23:49











  • @mklement0: “edited to add”

    – Joey
    Jun 3 '16 at 5:34














6












6








6


2






Is there an easy way in PowerShell to format numbers and the like in another locale? I'm currently writing a few functions to ease SVG generation for me and SVG uses . as a decimal separator, while PowerShell honors my locale settings (de-DE) when converting floating-point numbers to strings.



Is there an easy way to set another locale for a function or so without sticking



.ToString((New-Object Globalization.CultureInfo ""))


after every double variable?



Note: This is about the locale used for formatting, not the format string.



(Side question: Should I use the invariant culture in that case or rather en-US?)



ETA: Well, what I'm trying here is something like the following:



function New-SvgWave([int]$HalfWaves, [double]$Amplitude, [switch]$Upwards) {
"<path d='M0,0q0.5,{0} 1,0{1}v1q-0.5,{2} -1,0{3}z'/>" -f (
$(if ($Upwards) {-$Amplitude} else {$Amplitude}),
("t1,0" * ($HalfWaves - 1)),
$(if ($Upwards -xor ($HalfWaves % 2 -eq 0)) {-$Amplitude} else {$Amplitude}),
("t-1,0" * ($HalfWaves - 1))
)
}


Just a little automation for stuff I tend to write all the time and the double values need to use the decimal point instead of a comma (which they use in my locale).



ETA2: Interesting trivia to add:



PS Home:> $d=1.23
PS Home:> $d
1,23
PS Home:> "$d"
1.23


By putting the variable into a string the set locale doesn't seem to apply, somehow.










share|improve this question
















Is there an easy way in PowerShell to format numbers and the like in another locale? I'm currently writing a few functions to ease SVG generation for me and SVG uses . as a decimal separator, while PowerShell honors my locale settings (de-DE) when converting floating-point numbers to strings.



Is there an easy way to set another locale for a function or so without sticking



.ToString((New-Object Globalization.CultureInfo ""))


after every double variable?



Note: This is about the locale used for formatting, not the format string.



(Side question: Should I use the invariant culture in that case or rather en-US?)



ETA: Well, what I'm trying here is something like the following:



function New-SvgWave([int]$HalfWaves, [double]$Amplitude, [switch]$Upwards) {
"<path d='M0,0q0.5,{0} 1,0{1}v1q-0.5,{2} -1,0{3}z'/>" -f (
$(if ($Upwards) {-$Amplitude} else {$Amplitude}),
("t1,0" * ($HalfWaves - 1)),
$(if ($Upwards -xor ($HalfWaves % 2 -eq 0)) {-$Amplitude} else {$Amplitude}),
("t-1,0" * ($HalfWaves - 1))
)
}


Just a little automation for stuff I tend to write all the time and the double values need to use the decimal point instead of a comma (which they use in my locale).



ETA2: Interesting trivia to add:



PS Home:> $d=1.23
PS Home:> $d
1,23
PS Home:> "$d"
1.23


By putting the variable into a string the set locale doesn't seem to apply, somehow.







powershell locale number-formatting






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 7 '10 at 17:16







Joey

















asked Mar 4 '10 at 13:21









JoeyJoey

267k66570602




267k66570602













  • It's interesting that [Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]::InvariantCulture doesn't work..

    – stej
    Mar 4 '10 at 13:35











  • I've had problems only with 1.5 vs. 1,5, that's why inv. culture would work for me. It sounded to me like a batch task, so I thought you could run it in a separate powershell.exe session.

    – stej
    Mar 4 '10 at 14:03











  • @stej: [Threading.Thread]::CurrentThread.CurrentUICulture determines the display language of UI elements, not number formatting; by contrast, it is [Threading.Thread]::CurrentThread.CurrentCulture that determines number formatting; try (on a single line) [Threading.Thread]::CurrentThread.CurrentCulture = 'de-DE'; 1.2.

    – mklement0
    Jun 2 '16 at 22:11






  • 1





    @Joey: As an aside: I can guess that by "ETA" you meant something like "update (later edit)"; however, "ETA" is typically used to represent "Expected Time of Arrival"; what did you intend it to mean?

    – mklement0
    Jun 2 '16 at 23:49











  • @mklement0: “edited to add”

    – Joey
    Jun 3 '16 at 5:34



















  • It's interesting that [Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]::InvariantCulture doesn't work..

    – stej
    Mar 4 '10 at 13:35











  • I've had problems only with 1.5 vs. 1,5, that's why inv. culture would work for me. It sounded to me like a batch task, so I thought you could run it in a separate powershell.exe session.

    – stej
    Mar 4 '10 at 14:03











  • @stej: [Threading.Thread]::CurrentThread.CurrentUICulture determines the display language of UI elements, not number formatting; by contrast, it is [Threading.Thread]::CurrentThread.CurrentCulture that determines number formatting; try (on a single line) [Threading.Thread]::CurrentThread.CurrentCulture = 'de-DE'; 1.2.

    – mklement0
    Jun 2 '16 at 22:11






  • 1





    @Joey: As an aside: I can guess that by "ETA" you meant something like "update (later edit)"; however, "ETA" is typically used to represent "Expected Time of Arrival"; what did you intend it to mean?

    – mklement0
    Jun 2 '16 at 23:49











  • @mklement0: “edited to add”

    – Joey
    Jun 3 '16 at 5:34

















It's interesting that [Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]::InvariantCulture doesn't work..

– stej
Mar 4 '10 at 13:35





It's interesting that [Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]::InvariantCulture doesn't work..

– stej
Mar 4 '10 at 13:35













I've had problems only with 1.5 vs. 1,5, that's why inv. culture would work for me. It sounded to me like a batch task, so I thought you could run it in a separate powershell.exe session.

– stej
Mar 4 '10 at 14:03





I've had problems only with 1.5 vs. 1,5, that's why inv. culture would work for me. It sounded to me like a batch task, so I thought you could run it in a separate powershell.exe session.

– stej
Mar 4 '10 at 14:03













@stej: [Threading.Thread]::CurrentThread.CurrentUICulture determines the display language of UI elements, not number formatting; by contrast, it is [Threading.Thread]::CurrentThread.CurrentCulture that determines number formatting; try (on a single line) [Threading.Thread]::CurrentThread.CurrentCulture = 'de-DE'; 1.2.

– mklement0
Jun 2 '16 at 22:11





@stej: [Threading.Thread]::CurrentThread.CurrentUICulture determines the display language of UI elements, not number formatting; by contrast, it is [Threading.Thread]::CurrentThread.CurrentCulture that determines number formatting; try (on a single line) [Threading.Thread]::CurrentThread.CurrentCulture = 'de-DE'; 1.2.

– mklement0
Jun 2 '16 at 22:11




1




1





@Joey: As an aside: I can guess that by "ETA" you meant something like "update (later edit)"; however, "ETA" is typically used to represent "Expected Time of Arrival"; what did you intend it to mean?

– mklement0
Jun 2 '16 at 23:49





@Joey: As an aside: I can guess that by "ETA" you meant something like "update (later edit)"; however, "ETA" is typically used to represent "Expected Time of Arrival"; what did you intend it to mean?

– mklement0
Jun 2 '16 at 23:49













@mklement0: “edited to add”

– Joey
Jun 3 '16 at 5:34





@mklement0: “edited to add”

– Joey
Jun 3 '16 at 5:34












4 Answers
4






active

oldest

votes


















9














This is a PowerShell function I use for testing script in other cultures. I believe it could be used for what you are after:



function Using-Culture ([System.Globalization.CultureInfo]$culture =(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"),
[ScriptBlock]$script=(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"))
{
$OldCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture
$OldUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture
try {
[System.Threading.Thread]::CurrentThread.CurrentCulture = $culture
[System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture
Invoke-Command $script
}
finally {
[System.Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture
[System.Threading.Thread]::CurrentThread.CurrentUICulture = $OldUICulture
}
}

PS> $res = Using-Culture fr-FR { 1.1 }
PS> $res
1.1





share|improve this answer
























  • Keith, could you explain me why this always returns my locale and not french? [Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]'fr-FR'; [Threading.Thread]::CurrentThread.CurrentUICulture.Name

    – stej
    Mar 4 '10 at 15:14






  • 5





    Stej, good question. Type this at the command line and execute it over and over: [Threading.Thread]::CurrentThread.ManagedThreadId. Now execute this: & { 1..5 | %{[Threading.Thread]::CurrentThread.ManagedThreadId} }. It would appear that as you execute commands interactively there's no guarantee they will execute on the same thread from one invocation to the next. But inside a scriptblock, the same thread is used.

    – Keith Hill
    Mar 4 '10 at 15:50








  • 3





    If you switch to STA (put the -STA argument on the PowerShell command-line), the thread will be reused (but the culture change still doesn't seem to stick past a single pipeline).

    – Jaykul
    Aug 16 '11 at 4:49






  • 2





    @Jaykul Confirmed. Starting PowerShell in single-threaded apartment with -STA, and typing (in one line): [System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]"ar-SA"; [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; changes the culture to Arabic (Saudi Arabia), writes the current date and time in some Arabic way, and finally writes a thread ID. But after that the line [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; will use the original culture. The thread ID is the same, though.

    – Jeppe Stig Nielsen
    Dec 19 '12 at 13:05






  • 1





    In PS3 they actually changed things so they reset the culture. As far as I know, you have to use something like Keith Hill's script so that it all runs in one pipeline...

    – Jaykul
    Jun 4 '16 at 3:44



















8














While Keith Hill's helpful answer shows you how to change a script's current culture on demand (more modern alternative as of PSv3+ and .NET framework v4.6+:
[cultureinfo]::CurrentCulture = [cultureinfo]::InvariantCulture), there is no need to change the culture, because - as you've discovered in your second update to the question - PowerShell's string interpolation (as opposed to using the -f operator) always uses the invariant rather than the current culture:



In other words:



If you replace 'val: {0}' -f 1.2 with "val: $(1.2)", the literal 1.2 is not formatted according to the rules of the current culture.

You can verify in the console by running (on a single line; PSv3+, .NET framework v4.6+):



 PS> [cultureinfo]::currentculture = 'de-DE'; 'val: {0}' -f 1.2; "val: $(1.2)"
val: 1,2 # -f operator: GERMAN culture applies, where ',' is the decimal mark
val: 1.2 # string interpolation: INVARIANT culture applies, where '.' is the decimal mark.




Background:



Surprisingly, PowerShell always applies the invariant rather than the current culture in the following string-related contexts, if the type at hand supports culture-specific conversion to and from strings:



As explained in this in-depth answer, PowerShell explicitly requests culture-invariant processing - by passing the [cultureinfo]::InvariantCulture instance - in the following scenarios:




  • When string-interpolating: if the object's type implements the IFormattable interface; otherwise, PowerShell calls .psobject.ToString() on the object.



  • When casting:





    • to a string, including when binding to a [string]-typed parameter: if the source type implements the [IFormattable] interface; otherwise, PowerShell calls .psobject.ToString().


    • from a string: if the target type's static .Parse() method has an overload with an [IFormatProvider]-typed parameter (which is an interface implemented by [cultureinfo]).



  • When string-comparing (-eq, -lt, -gt) , using the String.Compare() overload that accepts a CultureInfo parameter.


  • Others?



As for what the invariant culture is / is for:




The invariant culture is culture-insensitive; it is associated with the English language but not with any country/region.

[...]

Unlike culture-sensitive data, which is subject to change by user customization or by updates to the .NET Framework or the operating system, invariant culture data is stable over time and across installed cultures and cannot be customized by users. This makes the invariant culture particularly useful for operations that require culture-independent results, such as formatting and parsing operations that persist formatted data, or sorting and ordering operations that require that data be displayed in a fixed order regardless of culture.




Presumably, it is the stability across cultures that motivated PowerShell's designers to consistently use the invariant culture when implicitly converting to and from strings.



For instance, if you hard-code a date string such as '7/21/2017' into a script and later try to convert it to date with a [date] cast, PowerShell's culture-invariant behavior ensures that the script doesn't break even when run while a culture other than US-English is in effect - fortunately, the invariant culture also recognizes ISO 8601-format date and time strings;

e.g., [datetime] '2017-07-21' works too.



On the flip side, if you do want to convert to and from current-culture-appropriate strings, you must do so explicitly.



To summarize:





  • Converting to strings:




    • Embedding instances of data types with culture-sensitive-by-default string representations inside "..." yields a culture-invariant representation ([double] or [datetime] are examples of such types).

    • To get a current-culture representation, call .ToString() explicitly or use -f, the formatting operator (possibly inside "..." via an enclosing $(...)).




  • Converting from strings:




    • A direct cast ([<type>] ...) only ever recognizes culture-invariant string representations.


    • To convert from a current-culture-appropriate string representation (or a specific culture's representation), use the target type's static ::Parse() method explicitly (optionally with an explicit [cultureinfo] instance to represent a specific culture).







Culture-INVARIANT examples:





  • string interpolation and casts:





    • "$(1/10)" and [string] 1/10




      • both yield string literal 0.1, with decimal mark ., irrespective of the current culture.




    • Similarly, casts from strings are culture-invariant; e.g., [double] '1.2'





      • . is always recognized as the decimal mark, irrespective of the current culture.

      • Another way of putting it: [double] 1.2 is not translated to the culture-sensitive-by-default method overload [double]::Parse('1.2'), but to the culture-invariant [double]::Parse('1.2', [cultureinfo]::InvariantCulture)






  • string comparison (assume that [cultureinfo]::CurrentCulture='tr-TR' is in effect - Turkish, where i is NOT a lowercase representation of I)





    • [string]::Equals('i', 'I', 'CurrentCultureIgnoreCase')



      • $false with the Turkish culture in effect.


      • 'i'.ToUpper() shows that in the Turkish culture the uppercase is İ, not I.




    • 'i' -eq 'I'


      • is still $true, because the invariant culture is applied.

      • implicitly the same as: [string]::Equals('i', 'I', 'InvariantCultureIgnoreCase')








Culture-SENSITIVE examples:



The current culture IS respected in the following cases:





  • With -f, the string-formatting operator (as noted above):





    • [cultureinfo]::currentculture = 'de-DE'; '{0}' -f 1.2 yields 1,2

    • Pitfall: Due to operator precedence, any expression as the RHS of -f must be enclosed in (...) in order to be recognized as such:


      • E.g., '{0}' -f 1/10 is evaluated as if ('{0}' -f 1) / 10 had been specified;

        use '{0}' -f (1/10) instead.






  • Default output to the console:




    • e.g., [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 yields 1,2


    • The same applies to output from cmdlets; e.g.,
      [cultureinfo]::CurrentCulture = 'de-DE'; Get-Date '2017-01-01' yields
      Sonntag, 1. Januar 2017 00:00:00


    • Caveat: There appears to be a bug as of Windows PowerShell v5.1 / PowerShell Core v6.0.0-beta.5: in certain scenarios, literals passed to a script block as unconstrained parameters can result in culture-invariant default output - see this GitHub issue





  • When writing to a file with Set-Content/Add-Content or Out-File / > / >>:




    • e.g., [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 > tmp.txt; Get-Content tmp.txt yields 1,2




  • When using the static ::Parse() / ::TryParse() methods on number types such as [double] while passing only the string to parse; e.g., with culture fr-FR in effect (where , is the decimal mark), [double]::Parse('1,2') returns double 1.2 (i.e., 1 + 2/10).





    • Caveat: As bviktor points out, thousands separators are recognized by default, but in a very loose fashion: effectively, the thousands separator can be placed anywhere inside the integer portion, irrespective of how many digits are in the resulting groups, and a leading 0 is also accepted; e.g., in the en-US culture (where , is the thousands separator), [double]::Parse('0,18') perhaps surprisingly succeeds and yields 18.


      • To suppress recognition of thousands separators, use something like [double]::Parse('0,18', 'Float'), via the NumberStyles parameter






  • Unintentional culture-sensitivity that won't be corrected to preserve backward compatibility:





    • In parameter-binding type conversions for cmdlets (but not for functions) - see this GitHub issue.


    • In the -as operator - see this GitHub issue.


    • In [hashtable] key lookups - see this answer and this GitHub issue.



  • Others?







share|improve this answer

































    4














    I was thinking about how to make it easy and came up with accelerators:



    Add-type -typedef @"
    using System;

    public class InvFloat
    {
    double _f = 0;
    private InvFloat (double f) {
    _f = f;
    }
    private InvFloat(string f) {
    _f = Double.Parse(f, System.Globalization.CultureInfo.InvariantCulture);
    }
    public static implicit operator InvFloat (double f) {
    return new InvFloat(f);
    }
    public static implicit operator double(InvFloat f) {
    return f._f;
    }
    public static explicit operator InvFloat (string f) {
    return new InvFloat (f);
    }
    public override string ToString() {
    return _f.ToString(System.Globalization.CultureInfo.InvariantCulture);
    }
    }
    "@
    $acce = [type]::gettype("System.Management.Automation.TypeAccelerators")
    $acce::Add('f', [InvFloat])
    $y = 1.5.ToString()
    $z = ([f]1.5).ToString()


    I hope it will help.






    share|improve this answer

































      1














      If you already have the culture loaded in your environment,



          #>Get-Culture
      LCID Name DisplayName
      ---- ---- -----------
      1031 de-DE German (Germany)

      #>Get-UICulture

      LCID Name DisplayName
      ---- ---- -----------
      1033 en-US English (United States)


      it is possible to resolve this problem:



      PS Home:> $d=1.23
      PS Home:> $d
      1,23


      like this:



      $d.ToString([cultureinfo]::CurrentUICulture)
      1.23


      Of course you need to keep in mind that if other users run the script with a different locale setting, the results may not turn out as originally intended.



      Nevertheless, this solution could come in useful. Have fun!






      share|improve this answer


























      • ++ for a handy technique for ad-hoc stringification in a specific culture; to give the explicit equivalent of your example: $d.ToString([cultureinfo]::GetCultureInfo('en-US')). To stringify in the invariant culture (which is ultimately what the OP wanted), it is simplest to cast ([string] $d), or to use PowerShell's string interpolation ("$d").

        – mklement0
        Feb 26 '17 at 14:32











      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f2379514%2fpowershell-formatting-values-in-another-culture%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      9














      This is a PowerShell function I use for testing script in other cultures. I believe it could be used for what you are after:



      function Using-Culture ([System.Globalization.CultureInfo]$culture =(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"),
      [ScriptBlock]$script=(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"))
      {
      $OldCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture
      $OldUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture
      try {
      [System.Threading.Thread]::CurrentThread.CurrentCulture = $culture
      [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture
      Invoke-Command $script
      }
      finally {
      [System.Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture
      [System.Threading.Thread]::CurrentThread.CurrentUICulture = $OldUICulture
      }
      }

      PS> $res = Using-Culture fr-FR { 1.1 }
      PS> $res
      1.1





      share|improve this answer
























      • Keith, could you explain me why this always returns my locale and not french? [Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]'fr-FR'; [Threading.Thread]::CurrentThread.CurrentUICulture.Name

        – stej
        Mar 4 '10 at 15:14






      • 5





        Stej, good question. Type this at the command line and execute it over and over: [Threading.Thread]::CurrentThread.ManagedThreadId. Now execute this: & { 1..5 | %{[Threading.Thread]::CurrentThread.ManagedThreadId} }. It would appear that as you execute commands interactively there's no guarantee they will execute on the same thread from one invocation to the next. But inside a scriptblock, the same thread is used.

        – Keith Hill
        Mar 4 '10 at 15:50








      • 3





        If you switch to STA (put the -STA argument on the PowerShell command-line), the thread will be reused (but the culture change still doesn't seem to stick past a single pipeline).

        – Jaykul
        Aug 16 '11 at 4:49






      • 2





        @Jaykul Confirmed. Starting PowerShell in single-threaded apartment with -STA, and typing (in one line): [System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]"ar-SA"; [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; changes the culture to Arabic (Saudi Arabia), writes the current date and time in some Arabic way, and finally writes a thread ID. But after that the line [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; will use the original culture. The thread ID is the same, though.

        – Jeppe Stig Nielsen
        Dec 19 '12 at 13:05






      • 1





        In PS3 they actually changed things so they reset the culture. As far as I know, you have to use something like Keith Hill's script so that it all runs in one pipeline...

        – Jaykul
        Jun 4 '16 at 3:44
















      9














      This is a PowerShell function I use for testing script in other cultures. I believe it could be used for what you are after:



      function Using-Culture ([System.Globalization.CultureInfo]$culture =(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"),
      [ScriptBlock]$script=(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"))
      {
      $OldCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture
      $OldUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture
      try {
      [System.Threading.Thread]::CurrentThread.CurrentCulture = $culture
      [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture
      Invoke-Command $script
      }
      finally {
      [System.Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture
      [System.Threading.Thread]::CurrentThread.CurrentUICulture = $OldUICulture
      }
      }

      PS> $res = Using-Culture fr-FR { 1.1 }
      PS> $res
      1.1





      share|improve this answer
























      • Keith, could you explain me why this always returns my locale and not french? [Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]'fr-FR'; [Threading.Thread]::CurrentThread.CurrentUICulture.Name

        – stej
        Mar 4 '10 at 15:14






      • 5





        Stej, good question. Type this at the command line and execute it over and over: [Threading.Thread]::CurrentThread.ManagedThreadId. Now execute this: & { 1..5 | %{[Threading.Thread]::CurrentThread.ManagedThreadId} }. It would appear that as you execute commands interactively there's no guarantee they will execute on the same thread from one invocation to the next. But inside a scriptblock, the same thread is used.

        – Keith Hill
        Mar 4 '10 at 15:50








      • 3





        If you switch to STA (put the -STA argument on the PowerShell command-line), the thread will be reused (but the culture change still doesn't seem to stick past a single pipeline).

        – Jaykul
        Aug 16 '11 at 4:49






      • 2





        @Jaykul Confirmed. Starting PowerShell in single-threaded apartment with -STA, and typing (in one line): [System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]"ar-SA"; [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; changes the culture to Arabic (Saudi Arabia), writes the current date and time in some Arabic way, and finally writes a thread ID. But after that the line [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; will use the original culture. The thread ID is the same, though.

        – Jeppe Stig Nielsen
        Dec 19 '12 at 13:05






      • 1





        In PS3 they actually changed things so they reset the culture. As far as I know, you have to use something like Keith Hill's script so that it all runs in one pipeline...

        – Jaykul
        Jun 4 '16 at 3:44














      9












      9








      9







      This is a PowerShell function I use for testing script in other cultures. I believe it could be used for what you are after:



      function Using-Culture ([System.Globalization.CultureInfo]$culture =(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"),
      [ScriptBlock]$script=(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"))
      {
      $OldCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture
      $OldUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture
      try {
      [System.Threading.Thread]::CurrentThread.CurrentCulture = $culture
      [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture
      Invoke-Command $script
      }
      finally {
      [System.Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture
      [System.Threading.Thread]::CurrentThread.CurrentUICulture = $OldUICulture
      }
      }

      PS> $res = Using-Culture fr-FR { 1.1 }
      PS> $res
      1.1





      share|improve this answer













      This is a PowerShell function I use for testing script in other cultures. I believe it could be used for what you are after:



      function Using-Culture ([System.Globalization.CultureInfo]$culture =(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"),
      [ScriptBlock]$script=(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"))
      {
      $OldCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture
      $OldUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture
      try {
      [System.Threading.Thread]::CurrentThread.CurrentCulture = $culture
      [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture
      Invoke-Command $script
      }
      finally {
      [System.Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture
      [System.Threading.Thread]::CurrentThread.CurrentUICulture = $OldUICulture
      }
      }

      PS> $res = Using-Culture fr-FR { 1.1 }
      PS> $res
      1.1






      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Mar 4 '10 at 15:04









      Keith HillKeith Hill

      145k24263303




      145k24263303













      • Keith, could you explain me why this always returns my locale and not french? [Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]'fr-FR'; [Threading.Thread]::CurrentThread.CurrentUICulture.Name

        – stej
        Mar 4 '10 at 15:14






      • 5





        Stej, good question. Type this at the command line and execute it over and over: [Threading.Thread]::CurrentThread.ManagedThreadId. Now execute this: & { 1..5 | %{[Threading.Thread]::CurrentThread.ManagedThreadId} }. It would appear that as you execute commands interactively there's no guarantee they will execute on the same thread from one invocation to the next. But inside a scriptblock, the same thread is used.

        – Keith Hill
        Mar 4 '10 at 15:50








      • 3





        If you switch to STA (put the -STA argument on the PowerShell command-line), the thread will be reused (but the culture change still doesn't seem to stick past a single pipeline).

        – Jaykul
        Aug 16 '11 at 4:49






      • 2





        @Jaykul Confirmed. Starting PowerShell in single-threaded apartment with -STA, and typing (in one line): [System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]"ar-SA"; [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; changes the culture to Arabic (Saudi Arabia), writes the current date and time in some Arabic way, and finally writes a thread ID. But after that the line [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; will use the original culture. The thread ID is the same, though.

        – Jeppe Stig Nielsen
        Dec 19 '12 at 13:05






      • 1





        In PS3 they actually changed things so they reset the culture. As far as I know, you have to use something like Keith Hill's script so that it all runs in one pipeline...

        – Jaykul
        Jun 4 '16 at 3:44



















      • Keith, could you explain me why this always returns my locale and not french? [Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]'fr-FR'; [Threading.Thread]::CurrentThread.CurrentUICulture.Name

        – stej
        Mar 4 '10 at 15:14






      • 5





        Stej, good question. Type this at the command line and execute it over and over: [Threading.Thread]::CurrentThread.ManagedThreadId. Now execute this: & { 1..5 | %{[Threading.Thread]::CurrentThread.ManagedThreadId} }. It would appear that as you execute commands interactively there's no guarantee they will execute on the same thread from one invocation to the next. But inside a scriptblock, the same thread is used.

        – Keith Hill
        Mar 4 '10 at 15:50








      • 3





        If you switch to STA (put the -STA argument on the PowerShell command-line), the thread will be reused (but the culture change still doesn't seem to stick past a single pipeline).

        – Jaykul
        Aug 16 '11 at 4:49






      • 2





        @Jaykul Confirmed. Starting PowerShell in single-threaded apartment with -STA, and typing (in one line): [System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]"ar-SA"; [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; changes the culture to Arabic (Saudi Arabia), writes the current date and time in some Arabic way, and finally writes a thread ID. But after that the line [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; will use the original culture. The thread ID is the same, though.

        – Jeppe Stig Nielsen
        Dec 19 '12 at 13:05






      • 1





        In PS3 they actually changed things so they reset the culture. As far as I know, you have to use something like Keith Hill's script so that it all runs in one pipeline...

        – Jaykul
        Jun 4 '16 at 3:44

















      Keith, could you explain me why this always returns my locale and not french? [Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]'fr-FR'; [Threading.Thread]::CurrentThread.CurrentUICulture.Name

      – stej
      Mar 4 '10 at 15:14





      Keith, could you explain me why this always returns my locale and not french? [Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]'fr-FR'; [Threading.Thread]::CurrentThread.CurrentUICulture.Name

      – stej
      Mar 4 '10 at 15:14




      5




      5





      Stej, good question. Type this at the command line and execute it over and over: [Threading.Thread]::CurrentThread.ManagedThreadId. Now execute this: & { 1..5 | %{[Threading.Thread]::CurrentThread.ManagedThreadId} }. It would appear that as you execute commands interactively there's no guarantee they will execute on the same thread from one invocation to the next. But inside a scriptblock, the same thread is used.

      – Keith Hill
      Mar 4 '10 at 15:50







      Stej, good question. Type this at the command line and execute it over and over: [Threading.Thread]::CurrentThread.ManagedThreadId. Now execute this: & { 1..5 | %{[Threading.Thread]::CurrentThread.ManagedThreadId} }. It would appear that as you execute commands interactively there's no guarantee they will execute on the same thread from one invocation to the next. But inside a scriptblock, the same thread is used.

      – Keith Hill
      Mar 4 '10 at 15:50






      3




      3





      If you switch to STA (put the -STA argument on the PowerShell command-line), the thread will be reused (but the culture change still doesn't seem to stick past a single pipeline).

      – Jaykul
      Aug 16 '11 at 4:49





      If you switch to STA (put the -STA argument on the PowerShell command-line), the thread will be reused (but the culture change still doesn't seem to stick past a single pipeline).

      – Jaykul
      Aug 16 '11 at 4:49




      2




      2





      @Jaykul Confirmed. Starting PowerShell in single-threaded apartment with -STA, and typing (in one line): [System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]"ar-SA"; [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; changes the culture to Arabic (Saudi Arabia), writes the current date and time in some Arabic way, and finally writes a thread ID. But after that the line [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; will use the original culture. The thread ID is the same, though.

      – Jeppe Stig Nielsen
      Dec 19 '12 at 13:05





      @Jaykul Confirmed. Starting PowerShell in single-threaded apartment with -STA, and typing (in one line): [System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]"ar-SA"; [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; changes the culture to Arabic (Saudi Arabia), writes the current date and time in some Arabic way, and finally writes a thread ID. But after that the line [DateTime]::Now; [System.Threading.Thread]::CurrentThread.ManagedThreadId; will use the original culture. The thread ID is the same, though.

      – Jeppe Stig Nielsen
      Dec 19 '12 at 13:05




      1




      1





      In PS3 they actually changed things so they reset the culture. As far as I know, you have to use something like Keith Hill's script so that it all runs in one pipeline...

      – Jaykul
      Jun 4 '16 at 3:44





      In PS3 they actually changed things so they reset the culture. As far as I know, you have to use something like Keith Hill's script so that it all runs in one pipeline...

      – Jaykul
      Jun 4 '16 at 3:44













      8














      While Keith Hill's helpful answer shows you how to change a script's current culture on demand (more modern alternative as of PSv3+ and .NET framework v4.6+:
      [cultureinfo]::CurrentCulture = [cultureinfo]::InvariantCulture), there is no need to change the culture, because - as you've discovered in your second update to the question - PowerShell's string interpolation (as opposed to using the -f operator) always uses the invariant rather than the current culture:



      In other words:



      If you replace 'val: {0}' -f 1.2 with "val: $(1.2)", the literal 1.2 is not formatted according to the rules of the current culture.

      You can verify in the console by running (on a single line; PSv3+, .NET framework v4.6+):



       PS> [cultureinfo]::currentculture = 'de-DE'; 'val: {0}' -f 1.2; "val: $(1.2)"
      val: 1,2 # -f operator: GERMAN culture applies, where ',' is the decimal mark
      val: 1.2 # string interpolation: INVARIANT culture applies, where '.' is the decimal mark.




      Background:



      Surprisingly, PowerShell always applies the invariant rather than the current culture in the following string-related contexts, if the type at hand supports culture-specific conversion to and from strings:



      As explained in this in-depth answer, PowerShell explicitly requests culture-invariant processing - by passing the [cultureinfo]::InvariantCulture instance - in the following scenarios:




      • When string-interpolating: if the object's type implements the IFormattable interface; otherwise, PowerShell calls .psobject.ToString() on the object.



      • When casting:





        • to a string, including when binding to a [string]-typed parameter: if the source type implements the [IFormattable] interface; otherwise, PowerShell calls .psobject.ToString().


        • from a string: if the target type's static .Parse() method has an overload with an [IFormatProvider]-typed parameter (which is an interface implemented by [cultureinfo]).



      • When string-comparing (-eq, -lt, -gt) , using the String.Compare() overload that accepts a CultureInfo parameter.


      • Others?



      As for what the invariant culture is / is for:




      The invariant culture is culture-insensitive; it is associated with the English language but not with any country/region.

      [...]

      Unlike culture-sensitive data, which is subject to change by user customization or by updates to the .NET Framework or the operating system, invariant culture data is stable over time and across installed cultures and cannot be customized by users. This makes the invariant culture particularly useful for operations that require culture-independent results, such as formatting and parsing operations that persist formatted data, or sorting and ordering operations that require that data be displayed in a fixed order regardless of culture.




      Presumably, it is the stability across cultures that motivated PowerShell's designers to consistently use the invariant culture when implicitly converting to and from strings.



      For instance, if you hard-code a date string such as '7/21/2017' into a script and later try to convert it to date with a [date] cast, PowerShell's culture-invariant behavior ensures that the script doesn't break even when run while a culture other than US-English is in effect - fortunately, the invariant culture also recognizes ISO 8601-format date and time strings;

      e.g., [datetime] '2017-07-21' works too.



      On the flip side, if you do want to convert to and from current-culture-appropriate strings, you must do so explicitly.



      To summarize:





      • Converting to strings:




        • Embedding instances of data types with culture-sensitive-by-default string representations inside "..." yields a culture-invariant representation ([double] or [datetime] are examples of such types).

        • To get a current-culture representation, call .ToString() explicitly or use -f, the formatting operator (possibly inside "..." via an enclosing $(...)).




      • Converting from strings:




        • A direct cast ([<type>] ...) only ever recognizes culture-invariant string representations.


        • To convert from a current-culture-appropriate string representation (or a specific culture's representation), use the target type's static ::Parse() method explicitly (optionally with an explicit [cultureinfo] instance to represent a specific culture).







      Culture-INVARIANT examples:





      • string interpolation and casts:





        • "$(1/10)" and [string] 1/10




          • both yield string literal 0.1, with decimal mark ., irrespective of the current culture.




        • Similarly, casts from strings are culture-invariant; e.g., [double] '1.2'





          • . is always recognized as the decimal mark, irrespective of the current culture.

          • Another way of putting it: [double] 1.2 is not translated to the culture-sensitive-by-default method overload [double]::Parse('1.2'), but to the culture-invariant [double]::Parse('1.2', [cultureinfo]::InvariantCulture)






      • string comparison (assume that [cultureinfo]::CurrentCulture='tr-TR' is in effect - Turkish, where i is NOT a lowercase representation of I)





        • [string]::Equals('i', 'I', 'CurrentCultureIgnoreCase')



          • $false with the Turkish culture in effect.


          • 'i'.ToUpper() shows that in the Turkish culture the uppercase is İ, not I.




        • 'i' -eq 'I'


          • is still $true, because the invariant culture is applied.

          • implicitly the same as: [string]::Equals('i', 'I', 'InvariantCultureIgnoreCase')








      Culture-SENSITIVE examples:



      The current culture IS respected in the following cases:





      • With -f, the string-formatting operator (as noted above):





        • [cultureinfo]::currentculture = 'de-DE'; '{0}' -f 1.2 yields 1,2

        • Pitfall: Due to operator precedence, any expression as the RHS of -f must be enclosed in (...) in order to be recognized as such:


          • E.g., '{0}' -f 1/10 is evaluated as if ('{0}' -f 1) / 10 had been specified;

            use '{0}' -f (1/10) instead.






      • Default output to the console:




        • e.g., [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 yields 1,2


        • The same applies to output from cmdlets; e.g.,
          [cultureinfo]::CurrentCulture = 'de-DE'; Get-Date '2017-01-01' yields
          Sonntag, 1. Januar 2017 00:00:00


        • Caveat: There appears to be a bug as of Windows PowerShell v5.1 / PowerShell Core v6.0.0-beta.5: in certain scenarios, literals passed to a script block as unconstrained parameters can result in culture-invariant default output - see this GitHub issue





      • When writing to a file with Set-Content/Add-Content or Out-File / > / >>:




        • e.g., [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 > tmp.txt; Get-Content tmp.txt yields 1,2




      • When using the static ::Parse() / ::TryParse() methods on number types such as [double] while passing only the string to parse; e.g., with culture fr-FR in effect (where , is the decimal mark), [double]::Parse('1,2') returns double 1.2 (i.e., 1 + 2/10).





        • Caveat: As bviktor points out, thousands separators are recognized by default, but in a very loose fashion: effectively, the thousands separator can be placed anywhere inside the integer portion, irrespective of how many digits are in the resulting groups, and a leading 0 is also accepted; e.g., in the en-US culture (where , is the thousands separator), [double]::Parse('0,18') perhaps surprisingly succeeds and yields 18.


          • To suppress recognition of thousands separators, use something like [double]::Parse('0,18', 'Float'), via the NumberStyles parameter






      • Unintentional culture-sensitivity that won't be corrected to preserve backward compatibility:





        • In parameter-binding type conversions for cmdlets (but not for functions) - see this GitHub issue.


        • In the -as operator - see this GitHub issue.


        • In [hashtable] key lookups - see this answer and this GitHub issue.



      • Others?







      share|improve this answer






























        8














        While Keith Hill's helpful answer shows you how to change a script's current culture on demand (more modern alternative as of PSv3+ and .NET framework v4.6+:
        [cultureinfo]::CurrentCulture = [cultureinfo]::InvariantCulture), there is no need to change the culture, because - as you've discovered in your second update to the question - PowerShell's string interpolation (as opposed to using the -f operator) always uses the invariant rather than the current culture:



        In other words:



        If you replace 'val: {0}' -f 1.2 with "val: $(1.2)", the literal 1.2 is not formatted according to the rules of the current culture.

        You can verify in the console by running (on a single line; PSv3+, .NET framework v4.6+):



         PS> [cultureinfo]::currentculture = 'de-DE'; 'val: {0}' -f 1.2; "val: $(1.2)"
        val: 1,2 # -f operator: GERMAN culture applies, where ',' is the decimal mark
        val: 1.2 # string interpolation: INVARIANT culture applies, where '.' is the decimal mark.




        Background:



        Surprisingly, PowerShell always applies the invariant rather than the current culture in the following string-related contexts, if the type at hand supports culture-specific conversion to and from strings:



        As explained in this in-depth answer, PowerShell explicitly requests culture-invariant processing - by passing the [cultureinfo]::InvariantCulture instance - in the following scenarios:




        • When string-interpolating: if the object's type implements the IFormattable interface; otherwise, PowerShell calls .psobject.ToString() on the object.



        • When casting:





          • to a string, including when binding to a [string]-typed parameter: if the source type implements the [IFormattable] interface; otherwise, PowerShell calls .psobject.ToString().


          • from a string: if the target type's static .Parse() method has an overload with an [IFormatProvider]-typed parameter (which is an interface implemented by [cultureinfo]).



        • When string-comparing (-eq, -lt, -gt) , using the String.Compare() overload that accepts a CultureInfo parameter.


        • Others?



        As for what the invariant culture is / is for:




        The invariant culture is culture-insensitive; it is associated with the English language but not with any country/region.

        [...]

        Unlike culture-sensitive data, which is subject to change by user customization or by updates to the .NET Framework or the operating system, invariant culture data is stable over time and across installed cultures and cannot be customized by users. This makes the invariant culture particularly useful for operations that require culture-independent results, such as formatting and parsing operations that persist formatted data, or sorting and ordering operations that require that data be displayed in a fixed order regardless of culture.




        Presumably, it is the stability across cultures that motivated PowerShell's designers to consistently use the invariant culture when implicitly converting to and from strings.



        For instance, if you hard-code a date string such as '7/21/2017' into a script and later try to convert it to date with a [date] cast, PowerShell's culture-invariant behavior ensures that the script doesn't break even when run while a culture other than US-English is in effect - fortunately, the invariant culture also recognizes ISO 8601-format date and time strings;

        e.g., [datetime] '2017-07-21' works too.



        On the flip side, if you do want to convert to and from current-culture-appropriate strings, you must do so explicitly.



        To summarize:





        • Converting to strings:




          • Embedding instances of data types with culture-sensitive-by-default string representations inside "..." yields a culture-invariant representation ([double] or [datetime] are examples of such types).

          • To get a current-culture representation, call .ToString() explicitly or use -f, the formatting operator (possibly inside "..." via an enclosing $(...)).




        • Converting from strings:




          • A direct cast ([<type>] ...) only ever recognizes culture-invariant string representations.


          • To convert from a current-culture-appropriate string representation (or a specific culture's representation), use the target type's static ::Parse() method explicitly (optionally with an explicit [cultureinfo] instance to represent a specific culture).







        Culture-INVARIANT examples:





        • string interpolation and casts:





          • "$(1/10)" and [string] 1/10




            • both yield string literal 0.1, with decimal mark ., irrespective of the current culture.




          • Similarly, casts from strings are culture-invariant; e.g., [double] '1.2'





            • . is always recognized as the decimal mark, irrespective of the current culture.

            • Another way of putting it: [double] 1.2 is not translated to the culture-sensitive-by-default method overload [double]::Parse('1.2'), but to the culture-invariant [double]::Parse('1.2', [cultureinfo]::InvariantCulture)






        • string comparison (assume that [cultureinfo]::CurrentCulture='tr-TR' is in effect - Turkish, where i is NOT a lowercase representation of I)





          • [string]::Equals('i', 'I', 'CurrentCultureIgnoreCase')



            • $false with the Turkish culture in effect.


            • 'i'.ToUpper() shows that in the Turkish culture the uppercase is İ, not I.




          • 'i' -eq 'I'


            • is still $true, because the invariant culture is applied.

            • implicitly the same as: [string]::Equals('i', 'I', 'InvariantCultureIgnoreCase')








        Culture-SENSITIVE examples:



        The current culture IS respected in the following cases:





        • With -f, the string-formatting operator (as noted above):





          • [cultureinfo]::currentculture = 'de-DE'; '{0}' -f 1.2 yields 1,2

          • Pitfall: Due to operator precedence, any expression as the RHS of -f must be enclosed in (...) in order to be recognized as such:


            • E.g., '{0}' -f 1/10 is evaluated as if ('{0}' -f 1) / 10 had been specified;

              use '{0}' -f (1/10) instead.






        • Default output to the console:




          • e.g., [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 yields 1,2


          • The same applies to output from cmdlets; e.g.,
            [cultureinfo]::CurrentCulture = 'de-DE'; Get-Date '2017-01-01' yields
            Sonntag, 1. Januar 2017 00:00:00


          • Caveat: There appears to be a bug as of Windows PowerShell v5.1 / PowerShell Core v6.0.0-beta.5: in certain scenarios, literals passed to a script block as unconstrained parameters can result in culture-invariant default output - see this GitHub issue





        • When writing to a file with Set-Content/Add-Content or Out-File / > / >>:




          • e.g., [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 > tmp.txt; Get-Content tmp.txt yields 1,2




        • When using the static ::Parse() / ::TryParse() methods on number types such as [double] while passing only the string to parse; e.g., with culture fr-FR in effect (where , is the decimal mark), [double]::Parse('1,2') returns double 1.2 (i.e., 1 + 2/10).





          • Caveat: As bviktor points out, thousands separators are recognized by default, but in a very loose fashion: effectively, the thousands separator can be placed anywhere inside the integer portion, irrespective of how many digits are in the resulting groups, and a leading 0 is also accepted; e.g., in the en-US culture (where , is the thousands separator), [double]::Parse('0,18') perhaps surprisingly succeeds and yields 18.


            • To suppress recognition of thousands separators, use something like [double]::Parse('0,18', 'Float'), via the NumberStyles parameter






        • Unintentional culture-sensitivity that won't be corrected to preserve backward compatibility:





          • In parameter-binding type conversions for cmdlets (but not for functions) - see this GitHub issue.


          • In the -as operator - see this GitHub issue.


          • In [hashtable] key lookups - see this answer and this GitHub issue.



        • Others?







        share|improve this answer




























          8












          8








          8







          While Keith Hill's helpful answer shows you how to change a script's current culture on demand (more modern alternative as of PSv3+ and .NET framework v4.6+:
          [cultureinfo]::CurrentCulture = [cultureinfo]::InvariantCulture), there is no need to change the culture, because - as you've discovered in your second update to the question - PowerShell's string interpolation (as opposed to using the -f operator) always uses the invariant rather than the current culture:



          In other words:



          If you replace 'val: {0}' -f 1.2 with "val: $(1.2)", the literal 1.2 is not formatted according to the rules of the current culture.

          You can verify in the console by running (on a single line; PSv3+, .NET framework v4.6+):



           PS> [cultureinfo]::currentculture = 'de-DE'; 'val: {0}' -f 1.2; "val: $(1.2)"
          val: 1,2 # -f operator: GERMAN culture applies, where ',' is the decimal mark
          val: 1.2 # string interpolation: INVARIANT culture applies, where '.' is the decimal mark.




          Background:



          Surprisingly, PowerShell always applies the invariant rather than the current culture in the following string-related contexts, if the type at hand supports culture-specific conversion to and from strings:



          As explained in this in-depth answer, PowerShell explicitly requests culture-invariant processing - by passing the [cultureinfo]::InvariantCulture instance - in the following scenarios:




          • When string-interpolating: if the object's type implements the IFormattable interface; otherwise, PowerShell calls .psobject.ToString() on the object.



          • When casting:





            • to a string, including when binding to a [string]-typed parameter: if the source type implements the [IFormattable] interface; otherwise, PowerShell calls .psobject.ToString().


            • from a string: if the target type's static .Parse() method has an overload with an [IFormatProvider]-typed parameter (which is an interface implemented by [cultureinfo]).



          • When string-comparing (-eq, -lt, -gt) , using the String.Compare() overload that accepts a CultureInfo parameter.


          • Others?



          As for what the invariant culture is / is for:




          The invariant culture is culture-insensitive; it is associated with the English language but not with any country/region.

          [...]

          Unlike culture-sensitive data, which is subject to change by user customization or by updates to the .NET Framework or the operating system, invariant culture data is stable over time and across installed cultures and cannot be customized by users. This makes the invariant culture particularly useful for operations that require culture-independent results, such as formatting and parsing operations that persist formatted data, or sorting and ordering operations that require that data be displayed in a fixed order regardless of culture.




          Presumably, it is the stability across cultures that motivated PowerShell's designers to consistently use the invariant culture when implicitly converting to and from strings.



          For instance, if you hard-code a date string such as '7/21/2017' into a script and later try to convert it to date with a [date] cast, PowerShell's culture-invariant behavior ensures that the script doesn't break even when run while a culture other than US-English is in effect - fortunately, the invariant culture also recognizes ISO 8601-format date and time strings;

          e.g., [datetime] '2017-07-21' works too.



          On the flip side, if you do want to convert to and from current-culture-appropriate strings, you must do so explicitly.



          To summarize:





          • Converting to strings:




            • Embedding instances of data types with culture-sensitive-by-default string representations inside "..." yields a culture-invariant representation ([double] or [datetime] are examples of such types).

            • To get a current-culture representation, call .ToString() explicitly or use -f, the formatting operator (possibly inside "..." via an enclosing $(...)).




          • Converting from strings:




            • A direct cast ([<type>] ...) only ever recognizes culture-invariant string representations.


            • To convert from a current-culture-appropriate string representation (or a specific culture's representation), use the target type's static ::Parse() method explicitly (optionally with an explicit [cultureinfo] instance to represent a specific culture).







          Culture-INVARIANT examples:





          • string interpolation and casts:





            • "$(1/10)" and [string] 1/10




              • both yield string literal 0.1, with decimal mark ., irrespective of the current culture.




            • Similarly, casts from strings are culture-invariant; e.g., [double] '1.2'





              • . is always recognized as the decimal mark, irrespective of the current culture.

              • Another way of putting it: [double] 1.2 is not translated to the culture-sensitive-by-default method overload [double]::Parse('1.2'), but to the culture-invariant [double]::Parse('1.2', [cultureinfo]::InvariantCulture)






          • string comparison (assume that [cultureinfo]::CurrentCulture='tr-TR' is in effect - Turkish, where i is NOT a lowercase representation of I)





            • [string]::Equals('i', 'I', 'CurrentCultureIgnoreCase')



              • $false with the Turkish culture in effect.


              • 'i'.ToUpper() shows that in the Turkish culture the uppercase is İ, not I.




            • 'i' -eq 'I'


              • is still $true, because the invariant culture is applied.

              • implicitly the same as: [string]::Equals('i', 'I', 'InvariantCultureIgnoreCase')








          Culture-SENSITIVE examples:



          The current culture IS respected in the following cases:





          • With -f, the string-formatting operator (as noted above):





            • [cultureinfo]::currentculture = 'de-DE'; '{0}' -f 1.2 yields 1,2

            • Pitfall: Due to operator precedence, any expression as the RHS of -f must be enclosed in (...) in order to be recognized as such:


              • E.g., '{0}' -f 1/10 is evaluated as if ('{0}' -f 1) / 10 had been specified;

                use '{0}' -f (1/10) instead.






          • Default output to the console:




            • e.g., [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 yields 1,2


            • The same applies to output from cmdlets; e.g.,
              [cultureinfo]::CurrentCulture = 'de-DE'; Get-Date '2017-01-01' yields
              Sonntag, 1. Januar 2017 00:00:00


            • Caveat: There appears to be a bug as of Windows PowerShell v5.1 / PowerShell Core v6.0.0-beta.5: in certain scenarios, literals passed to a script block as unconstrained parameters can result in culture-invariant default output - see this GitHub issue





          • When writing to a file with Set-Content/Add-Content or Out-File / > / >>:




            • e.g., [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 > tmp.txt; Get-Content tmp.txt yields 1,2




          • When using the static ::Parse() / ::TryParse() methods on number types such as [double] while passing only the string to parse; e.g., with culture fr-FR in effect (where , is the decimal mark), [double]::Parse('1,2') returns double 1.2 (i.e., 1 + 2/10).





            • Caveat: As bviktor points out, thousands separators are recognized by default, but in a very loose fashion: effectively, the thousands separator can be placed anywhere inside the integer portion, irrespective of how many digits are in the resulting groups, and a leading 0 is also accepted; e.g., in the en-US culture (where , is the thousands separator), [double]::Parse('0,18') perhaps surprisingly succeeds and yields 18.


              • To suppress recognition of thousands separators, use something like [double]::Parse('0,18', 'Float'), via the NumberStyles parameter






          • Unintentional culture-sensitivity that won't be corrected to preserve backward compatibility:





            • In parameter-binding type conversions for cmdlets (but not for functions) - see this GitHub issue.


            • In the -as operator - see this GitHub issue.


            • In [hashtable] key lookups - see this answer and this GitHub issue.



          • Others?







          share|improve this answer















          While Keith Hill's helpful answer shows you how to change a script's current culture on demand (more modern alternative as of PSv3+ and .NET framework v4.6+:
          [cultureinfo]::CurrentCulture = [cultureinfo]::InvariantCulture), there is no need to change the culture, because - as you've discovered in your second update to the question - PowerShell's string interpolation (as opposed to using the -f operator) always uses the invariant rather than the current culture:



          In other words:



          If you replace 'val: {0}' -f 1.2 with "val: $(1.2)", the literal 1.2 is not formatted according to the rules of the current culture.

          You can verify in the console by running (on a single line; PSv3+, .NET framework v4.6+):



           PS> [cultureinfo]::currentculture = 'de-DE'; 'val: {0}' -f 1.2; "val: $(1.2)"
          val: 1,2 # -f operator: GERMAN culture applies, where ',' is the decimal mark
          val: 1.2 # string interpolation: INVARIANT culture applies, where '.' is the decimal mark.




          Background:



          Surprisingly, PowerShell always applies the invariant rather than the current culture in the following string-related contexts, if the type at hand supports culture-specific conversion to and from strings:



          As explained in this in-depth answer, PowerShell explicitly requests culture-invariant processing - by passing the [cultureinfo]::InvariantCulture instance - in the following scenarios:




          • When string-interpolating: if the object's type implements the IFormattable interface; otherwise, PowerShell calls .psobject.ToString() on the object.



          • When casting:





            • to a string, including when binding to a [string]-typed parameter: if the source type implements the [IFormattable] interface; otherwise, PowerShell calls .psobject.ToString().


            • from a string: if the target type's static .Parse() method has an overload with an [IFormatProvider]-typed parameter (which is an interface implemented by [cultureinfo]).



          • When string-comparing (-eq, -lt, -gt) , using the String.Compare() overload that accepts a CultureInfo parameter.


          • Others?



          As for what the invariant culture is / is for:




          The invariant culture is culture-insensitive; it is associated with the English language but not with any country/region.

          [...]

          Unlike culture-sensitive data, which is subject to change by user customization or by updates to the .NET Framework or the operating system, invariant culture data is stable over time and across installed cultures and cannot be customized by users. This makes the invariant culture particularly useful for operations that require culture-independent results, such as formatting and parsing operations that persist formatted data, or sorting and ordering operations that require that data be displayed in a fixed order regardless of culture.




          Presumably, it is the stability across cultures that motivated PowerShell's designers to consistently use the invariant culture when implicitly converting to and from strings.



          For instance, if you hard-code a date string such as '7/21/2017' into a script and later try to convert it to date with a [date] cast, PowerShell's culture-invariant behavior ensures that the script doesn't break even when run while a culture other than US-English is in effect - fortunately, the invariant culture also recognizes ISO 8601-format date and time strings;

          e.g., [datetime] '2017-07-21' works too.



          On the flip side, if you do want to convert to and from current-culture-appropriate strings, you must do so explicitly.



          To summarize:





          • Converting to strings:




            • Embedding instances of data types with culture-sensitive-by-default string representations inside "..." yields a culture-invariant representation ([double] or [datetime] are examples of such types).

            • To get a current-culture representation, call .ToString() explicitly or use -f, the formatting operator (possibly inside "..." via an enclosing $(...)).




          • Converting from strings:




            • A direct cast ([<type>] ...) only ever recognizes culture-invariant string representations.


            • To convert from a current-culture-appropriate string representation (or a specific culture's representation), use the target type's static ::Parse() method explicitly (optionally with an explicit [cultureinfo] instance to represent a specific culture).







          Culture-INVARIANT examples:





          • string interpolation and casts:





            • "$(1/10)" and [string] 1/10




              • both yield string literal 0.1, with decimal mark ., irrespective of the current culture.




            • Similarly, casts from strings are culture-invariant; e.g., [double] '1.2'





              • . is always recognized as the decimal mark, irrespective of the current culture.

              • Another way of putting it: [double] 1.2 is not translated to the culture-sensitive-by-default method overload [double]::Parse('1.2'), but to the culture-invariant [double]::Parse('1.2', [cultureinfo]::InvariantCulture)






          • string comparison (assume that [cultureinfo]::CurrentCulture='tr-TR' is in effect - Turkish, where i is NOT a lowercase representation of I)





            • [string]::Equals('i', 'I', 'CurrentCultureIgnoreCase')



              • $false with the Turkish culture in effect.


              • 'i'.ToUpper() shows that in the Turkish culture the uppercase is İ, not I.




            • 'i' -eq 'I'


              • is still $true, because the invariant culture is applied.

              • implicitly the same as: [string]::Equals('i', 'I', 'InvariantCultureIgnoreCase')








          Culture-SENSITIVE examples:



          The current culture IS respected in the following cases:





          • With -f, the string-formatting operator (as noted above):





            • [cultureinfo]::currentculture = 'de-DE'; '{0}' -f 1.2 yields 1,2

            • Pitfall: Due to operator precedence, any expression as the RHS of -f must be enclosed in (...) in order to be recognized as such:


              • E.g., '{0}' -f 1/10 is evaluated as if ('{0}' -f 1) / 10 had been specified;

                use '{0}' -f (1/10) instead.






          • Default output to the console:




            • e.g., [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 yields 1,2


            • The same applies to output from cmdlets; e.g.,
              [cultureinfo]::CurrentCulture = 'de-DE'; Get-Date '2017-01-01' yields
              Sonntag, 1. Januar 2017 00:00:00


            • Caveat: There appears to be a bug as of Windows PowerShell v5.1 / PowerShell Core v6.0.0-beta.5: in certain scenarios, literals passed to a script block as unconstrained parameters can result in culture-invariant default output - see this GitHub issue





          • When writing to a file with Set-Content/Add-Content or Out-File / > / >>:




            • e.g., [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 > tmp.txt; Get-Content tmp.txt yields 1,2




          • When using the static ::Parse() / ::TryParse() methods on number types such as [double] while passing only the string to parse; e.g., with culture fr-FR in effect (where , is the decimal mark), [double]::Parse('1,2') returns double 1.2 (i.e., 1 + 2/10).





            • Caveat: As bviktor points out, thousands separators are recognized by default, but in a very loose fashion: effectively, the thousands separator can be placed anywhere inside the integer portion, irrespective of how many digits are in the resulting groups, and a leading 0 is also accepted; e.g., in the en-US culture (where , is the thousands separator), [double]::Parse('0,18') perhaps surprisingly succeeds and yields 18.


              • To suppress recognition of thousands separators, use something like [double]::Parse('0,18', 'Float'), via the NumberStyles parameter






          • Unintentional culture-sensitivity that won't be corrected to preserve backward compatibility:





            • In parameter-binding type conversions for cmdlets (but not for functions) - see this GitHub issue.


            • In the -as operator - see this GitHub issue.


            • In [hashtable] key lookups - see this answer and this GitHub issue.



          • Others?








          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 15 '18 at 19:07

























          answered Jun 2 '16 at 23:29









          mklement0mklement0

          135k22252289




          135k22252289























              4














              I was thinking about how to make it easy and came up with accelerators:



              Add-type -typedef @"
              using System;

              public class InvFloat
              {
              double _f = 0;
              private InvFloat (double f) {
              _f = f;
              }
              private InvFloat(string f) {
              _f = Double.Parse(f, System.Globalization.CultureInfo.InvariantCulture);
              }
              public static implicit operator InvFloat (double f) {
              return new InvFloat(f);
              }
              public static implicit operator double(InvFloat f) {
              return f._f;
              }
              public static explicit operator InvFloat (string f) {
              return new InvFloat (f);
              }
              public override string ToString() {
              return _f.ToString(System.Globalization.CultureInfo.InvariantCulture);
              }
              }
              "@
              $acce = [type]::gettype("System.Management.Automation.TypeAccelerators")
              $acce::Add('f', [InvFloat])
              $y = 1.5.ToString()
              $z = ([f]1.5).ToString()


              I hope it will help.






              share|improve this answer






























                4














                I was thinking about how to make it easy and came up with accelerators:



                Add-type -typedef @"
                using System;

                public class InvFloat
                {
                double _f = 0;
                private InvFloat (double f) {
                _f = f;
                }
                private InvFloat(string f) {
                _f = Double.Parse(f, System.Globalization.CultureInfo.InvariantCulture);
                }
                public static implicit operator InvFloat (double f) {
                return new InvFloat(f);
                }
                public static implicit operator double(InvFloat f) {
                return f._f;
                }
                public static explicit operator InvFloat (string f) {
                return new InvFloat (f);
                }
                public override string ToString() {
                return _f.ToString(System.Globalization.CultureInfo.InvariantCulture);
                }
                }
                "@
                $acce = [type]::gettype("System.Management.Automation.TypeAccelerators")
                $acce::Add('f', [InvFloat])
                $y = 1.5.ToString()
                $z = ([f]1.5).ToString()


                I hope it will help.






                share|improve this answer




























                  4












                  4








                  4







                  I was thinking about how to make it easy and came up with accelerators:



                  Add-type -typedef @"
                  using System;

                  public class InvFloat
                  {
                  double _f = 0;
                  private InvFloat (double f) {
                  _f = f;
                  }
                  private InvFloat(string f) {
                  _f = Double.Parse(f, System.Globalization.CultureInfo.InvariantCulture);
                  }
                  public static implicit operator InvFloat (double f) {
                  return new InvFloat(f);
                  }
                  public static implicit operator double(InvFloat f) {
                  return f._f;
                  }
                  public static explicit operator InvFloat (string f) {
                  return new InvFloat (f);
                  }
                  public override string ToString() {
                  return _f.ToString(System.Globalization.CultureInfo.InvariantCulture);
                  }
                  }
                  "@
                  $acce = [type]::gettype("System.Management.Automation.TypeAccelerators")
                  $acce::Add('f', [InvFloat])
                  $y = 1.5.ToString()
                  $z = ([f]1.5).ToString()


                  I hope it will help.






                  share|improve this answer















                  I was thinking about how to make it easy and came up with accelerators:



                  Add-type -typedef @"
                  using System;

                  public class InvFloat
                  {
                  double _f = 0;
                  private InvFloat (double f) {
                  _f = f;
                  }
                  private InvFloat(string f) {
                  _f = Double.Parse(f, System.Globalization.CultureInfo.InvariantCulture);
                  }
                  public static implicit operator InvFloat (double f) {
                  return new InvFloat(f);
                  }
                  public static implicit operator double(InvFloat f) {
                  return f._f;
                  }
                  public static explicit operator InvFloat (string f) {
                  return new InvFloat (f);
                  }
                  public override string ToString() {
                  return _f.ToString(System.Globalization.CultureInfo.InvariantCulture);
                  }
                  }
                  "@
                  $acce = [type]::gettype("System.Management.Automation.TypeAccelerators")
                  $acce::Add('f', [InvFloat])
                  $y = 1.5.ToString()
                  $z = ([f]1.5).ToString()


                  I hope it will help.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Mar 4 '10 at 15:01

























                  answered Mar 4 '10 at 14:40









                  stejstej

                  21.9k105591




                  21.9k105591























                      1














                      If you already have the culture loaded in your environment,



                          #>Get-Culture
                      LCID Name DisplayName
                      ---- ---- -----------
                      1031 de-DE German (Germany)

                      #>Get-UICulture

                      LCID Name DisplayName
                      ---- ---- -----------
                      1033 en-US English (United States)


                      it is possible to resolve this problem:



                      PS Home:> $d=1.23
                      PS Home:> $d
                      1,23


                      like this:



                      $d.ToString([cultureinfo]::CurrentUICulture)
                      1.23


                      Of course you need to keep in mind that if other users run the script with a different locale setting, the results may not turn out as originally intended.



                      Nevertheless, this solution could come in useful. Have fun!






                      share|improve this answer


























                      • ++ for a handy technique for ad-hoc stringification in a specific culture; to give the explicit equivalent of your example: $d.ToString([cultureinfo]::GetCultureInfo('en-US')). To stringify in the invariant culture (which is ultimately what the OP wanted), it is simplest to cast ([string] $d), or to use PowerShell's string interpolation ("$d").

                        – mklement0
                        Feb 26 '17 at 14:32
















                      1














                      If you already have the culture loaded in your environment,



                          #>Get-Culture
                      LCID Name DisplayName
                      ---- ---- -----------
                      1031 de-DE German (Germany)

                      #>Get-UICulture

                      LCID Name DisplayName
                      ---- ---- -----------
                      1033 en-US English (United States)


                      it is possible to resolve this problem:



                      PS Home:> $d=1.23
                      PS Home:> $d
                      1,23


                      like this:



                      $d.ToString([cultureinfo]::CurrentUICulture)
                      1.23


                      Of course you need to keep in mind that if other users run the script with a different locale setting, the results may not turn out as originally intended.



                      Nevertheless, this solution could come in useful. Have fun!






                      share|improve this answer


























                      • ++ for a handy technique for ad-hoc stringification in a specific culture; to give the explicit equivalent of your example: $d.ToString([cultureinfo]::GetCultureInfo('en-US')). To stringify in the invariant culture (which is ultimately what the OP wanted), it is simplest to cast ([string] $d), or to use PowerShell's string interpolation ("$d").

                        – mklement0
                        Feb 26 '17 at 14:32














                      1












                      1








                      1







                      If you already have the culture loaded in your environment,



                          #>Get-Culture
                      LCID Name DisplayName
                      ---- ---- -----------
                      1031 de-DE German (Germany)

                      #>Get-UICulture

                      LCID Name DisplayName
                      ---- ---- -----------
                      1033 en-US English (United States)


                      it is possible to resolve this problem:



                      PS Home:> $d=1.23
                      PS Home:> $d
                      1,23


                      like this:



                      $d.ToString([cultureinfo]::CurrentUICulture)
                      1.23


                      Of course you need to keep in mind that if other users run the script with a different locale setting, the results may not turn out as originally intended.



                      Nevertheless, this solution could come in useful. Have fun!






                      share|improve this answer















                      If you already have the culture loaded in your environment,



                          #>Get-Culture
                      LCID Name DisplayName
                      ---- ---- -----------
                      1031 de-DE German (Germany)

                      #>Get-UICulture

                      LCID Name DisplayName
                      ---- ---- -----------
                      1033 en-US English (United States)


                      it is possible to resolve this problem:



                      PS Home:> $d=1.23
                      PS Home:> $d
                      1,23


                      like this:



                      $d.ToString([cultureinfo]::CurrentUICulture)
                      1.23


                      Of course you need to keep in mind that if other users run the script with a different locale setting, the results may not turn out as originally intended.



                      Nevertheless, this solution could come in useful. Have fun!







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Feb 24 '17 at 10:41

























                      answered Feb 24 '17 at 10:35









                      PorkyPorky

                      14714




                      14714













                      • ++ for a handy technique for ad-hoc stringification in a specific culture; to give the explicit equivalent of your example: $d.ToString([cultureinfo]::GetCultureInfo('en-US')). To stringify in the invariant culture (which is ultimately what the OP wanted), it is simplest to cast ([string] $d), or to use PowerShell's string interpolation ("$d").

                        – mklement0
                        Feb 26 '17 at 14:32



















                      • ++ for a handy technique for ad-hoc stringification in a specific culture; to give the explicit equivalent of your example: $d.ToString([cultureinfo]::GetCultureInfo('en-US')). To stringify in the invariant culture (which is ultimately what the OP wanted), it is simplest to cast ([string] $d), or to use PowerShell's string interpolation ("$d").

                        – mklement0
                        Feb 26 '17 at 14:32

















                      ++ for a handy technique for ad-hoc stringification in a specific culture; to give the explicit equivalent of your example: $d.ToString([cultureinfo]::GetCultureInfo('en-US')). To stringify in the invariant culture (which is ultimately what the OP wanted), it is simplest to cast ([string] $d), or to use PowerShell's string interpolation ("$d").

                      – mklement0
                      Feb 26 '17 at 14:32





                      ++ for a handy technique for ad-hoc stringification in a specific culture; to give the explicit equivalent of your example: $d.ToString([cultureinfo]::GetCultureInfo('en-US')). To stringify in the invariant culture (which is ultimately what the OP wanted), it is simplest to cast ([string] $d), or to use PowerShell's string interpolation ("$d").

                      – mklement0
                      Feb 26 '17 at 14:32


















                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f2379514%2fpowershell-formatting-values-in-another-culture%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Xamarin.iOS Cant Deploy on Iphone

                      Glorious Revolution

                      Dulmage-Mendelsohn matrix decomposition in Python