将带有区域性的标准数字格式转换为自定义数字格式

时间:2014-02-18 17:01:29

标签: c# formatting

在C#中,有没有办法获得具有指定用户文化的标准数字格式的等效自定义数字格式?

示例(不确定我的转换是否正确):

  • C3 in fr-FR = 0.000''
  • D2 = 0.00
  • P0 =%#0

请参阅以下链接:

3 个答案:

答案 0 :(得分:1)

给定CultureInfo,您可以检查NumberFormatInfo类型的NumberFormat属性,以获取.NET在格式化不同数字类型时使用的所有信息。 E.g:

var frenchCultureInfo = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(frenchCultureInfo.NumberFormat.CurrencySymbol);

这将打印。要重建完整格式,您必须检查NumberFormat属性上的多个属性。这可能变得非常乏味。作为一项实验,我尝试使用Decimal格式说明符编写格式化C所需的代码:

var value = -123456.789M;
var cultureInfo = CultureInfo.GetCultureInfo("as-IN");
var numberFormat = cultureInfo.NumberFormat;

// Create group format like "#,##,###".
var groups = numberFormat
  .CurrencyGroupSizes
  .Reverse()
  .Select(groupSize => new String('#', groupSize));
var format1 = "#," + String.Join(",", groups);

// Create number format like "#,##,##0.00".
var format2 = format1.Substring(0, format1.Length - 1)
  + "0." + new String('0', numberFormat.CurrencyDecimalDigits);

// Format the number without a sign.
// Note that it is necessary to use the correct CultureInfo here.
var formattedNumber = Math.Abs(value).ToString(format2, cultureInfo);

// Combine sign, currency symbol and number.
var currencyPositivePatterns = new Dictionary<Int32, String> {
  { 0, "{0}{1}" },
  { 1, "{1}{0}" },
  { 2, "{0} {1}" },
  { 3, "{1} {0}" }
};
var currencyNegativePatterns = new Dictionary<Int32, String> {
  { 0, "({0}{1})" },
  { 1, "-{0}{1}" },
  { 2, "{0}-{1}" },
  { 3, "{0}{1}-" },
  { 4, "({1}{0})" },
  { 5, "-{1}{0}" },
  { 6, "{1}-{0}" },
  { 7, "{1}{0}-" },
  { 8, "-{1} {0}" },
  { 9, "-{0} {1}" },
  { 10, "{1} {0}-)" },
  { 11, "{0} {1}-" },
  { 12, "{0} -{1}" },
  { 13, "{1}- {0}" },
  { 14, "({0} {1})" },
  { 15, "({1} {0})" }
};
var currencyPattern = value >= Decimal.Zero
  ? currencyPositivePatterns[numberFormat.CurrencyPositivePattern]
  : currencyNegativePatterns[numberFormat.CurrencyNegativePattern];
var formattedValue = String.Format(
  currencyPattern,
  numberFormat.CurrencySymbol,
  formattedNumber
);

formattedValue的值为₹ -1,23,456.79,与评估value.ToString("C", cultureInfo)时的值相同。显然,后者要简单得多。

请注意,某些货币符号可以包含.',这些符号在自定义数字格式中具有特殊含义。因此,您无法始终创建自定义格式字符串来替换C。例如。对于da-DK文化,正数的C格式等同于kr. #,##0.00,但kr之后的点将无法使用该格式。相反,您必须使用一种方法,在格式化数字后添加货币符号,或者您可以转义有问题的字符。

答案 1 :(得分:0)

与小数分隔符或千位分隔符不同,Afaik没有文化货币的格式字符串。也许这是因为每个文化中的数字总是相同的,但根据货币,金额是不同的。因此,您必须提前知道货币。

但是,如果您事先知道货币,则可以将货币符号用作普通文字字符。

因此,您可以使用“0.000€”(法国人不会使用,作为小数点分隔符吗?)。

答案 2 :(得分:0)

如果您事先了解文化,可以获取用于货币的格式字符串并自行使用。

在您的示例中,您将使用以下方法检索fr-FR文化的CultureInfo对象:

CultureInfo French = new CultureInfo("fr-FR");

您可以将此CultureInfo对象传递给ToString()方法,也可以从NumberFormatInfo获取CultureInfo对象:

NumberFormatInfo numberFormat = French.NumberFormat;

NumberFormatInfo对象具有以下属性:CurrencySymbolCurrencyDecimalDigitsCurrencyDecimalSeparator,'CurrencyGroupSeparator , CurrencyGroupSizes`。使用它们,您可以构建自己的格式字符串:

string fmt = numberFormat.CurrencySymbol + "#" + numberFormat.CurrencyGroupSeparator;

for ( int i = 0; i < numberFormat.CurrencyGroupSizes - 1; i++ ) 
    fmt += "#";

fmt += "0" + numberFormat.CurrencyDecimalSeparator;

for ( int d = 0; i < numberFormat.CurrencyDecimalDigits; i++ )
    fmt += "0";

NumberFormatInfo类的另外两个属性叫做CurrencyNegativePatternCurrencyPositivePattern,它们告诉你小数符号和&amp; sign go,或者是否将负值放在括号中。我会留给你决定你是否需要这些&amp;编写构建格式字符串所需的代码。