static string FormatNumber(double value, DecimalSection format, CultureInfo culture) { bool thousandSeparator = format.ThousandSeparator; value = value / format.ThousandDivisor; value = value * format.PercentMultiplier; var result = new StringBuilder(); FormatNumber(value, format.BeforeDecimal, format.DecimalSeparator, format.AfterDecimal, thousandSeparator, culture, result); return(result.ToString()); }
public static bool TryParse(List <string> tokens, out DecimalSection format) { if (Parser.ParseNumberTokens(tokens, 0, out var beforeDecimal, out var decimalSeparator, out var afterDecimal) == tokens.Count) { bool thousandSeparator; var divisor = GetTrailingCommasDivisor(tokens, out thousandSeparator); var multiplier = GetPercentMultiplier(tokens); format = new DecimalSection() { BeforeDecimal = beforeDecimal, DecimalSeparator = decimalSeparator, AfterDecimal = afterDecimal, PercentMultiplier = multiplier, ThousandDivisor = divisor, ThousandSeparator = thousandSeparator }; return(true); } format = null; return(false); }
private static Section ParseSection(Tokenizer reader, int index, out bool syntaxError) { bool hasDateParts = false; bool hasDurationParts = false; bool hasGeneralPart = false; bool hasTextPart = false; bool hasPlaceholders = false; Condition condition = null; Color color = null; string token; List <string> tokens = new List <string>(); syntaxError = false; while ((token = ReadToken(reader, out syntaxError)) != null) { if (token == ";") { break; } hasPlaceholders |= Token.IsPlaceholder(token); if (Token.IsDatePart(token)) { hasDateParts |= true; hasDurationParts |= Token.IsDurationPart(token); tokens.Add(token); } else if (Token.IsGeneral(token)) { hasGeneralPart |= true; tokens.Add(token); } else if (token == "@") { hasTextPart |= true; tokens.Add(token); } else if (token.StartsWith("[")) { // Does not add to tokens. Absolute/elapsed time tokens // also start with '[', but handled as date part above var expression = token.Substring(1, token.Length - 2); if (TryParseCondition(expression, out var parseCondition)) { condition = parseCondition; } else if (TryParseColor(expression, out var parseColor)) { color = parseColor; } else if (TryParseCurrencySymbol(expression, out var parseCurrencySymbol)) { tokens.Add("\"" + parseCurrencySymbol + "\""); } } else { tokens.Add(token); } } if (syntaxError || tokens.Count == 0) { return(null); } if ( (hasDateParts && (hasGeneralPart || hasTextPart)) || (hasGeneralPart && (hasDateParts || hasTextPart)) || (hasTextPart && (hasGeneralPart || hasDateParts))) { // Cannot mix date, general and/or text parts syntaxError = true; return(null); } SectionType type; FractionSection fraction = null; ExponentialSection exponential = null; DecimalSection number = null; List <string> generalTextDateDuration = null; if (hasDateParts) { if (hasDurationParts) { type = SectionType.Duration; } else { type = SectionType.Date; } ParseMilliseconds(tokens, out generalTextDateDuration); } else if (hasGeneralPart) { type = SectionType.General; generalTextDateDuration = tokens; } else if (hasTextPart || !hasPlaceholders) { type = SectionType.Text; generalTextDateDuration = tokens; } else if (FractionSection.TryParse(tokens, out fraction)) { type = SectionType.Fraction; } else if (ExponentialSection.TryParse(tokens, out exponential)) { type = SectionType.Exponential; } else if (DecimalSection.TryParse(tokens, out number)) { type = SectionType.Number; } else { // Unable to parse format string syntaxError = true; return(null); } return(new Section() { Type = type, SectionIndex = index, Color = color, Condition = condition, Fraction = fraction, Exponential = exponential, Number = number, GeneralTextDateDurationParts = generalTextDateDuration }); }