При использовании NumberFormatter
и установке numberStyle
на .currency
форматтер округляет все числа до 2 десятичных знаков, как и ожидалось. Однако для небольших отрицательных чисел, значение которых округлено до 2 десятичных знаков 0 (число> = -0,005), выходная строка содержит знак отрицания и, следовательно, становится -$0.00
вместо $0.00
.
Есть ли способ изменить это поведение, просто переключая некоторые свойства NumberFormatter
вместо использования обходного пути? В данный момент я сам округляю значение до 2 десятичных разрядов, проверяю, равен ли вывод -0
, и действую соответствующим образом. Тем не менее, было бы здорово, если бы NumberFormatter
можно было настроить так, чтобы он не различал -0
и 0
.
Ниже код показывает проблему и мой текущий способ ее обхода (не стесняйтесь тестировать на игровой площадке) - я знаю, что Locale
должен быть установлен на основе currencySymbol
, но это всего лишь код для демонстрации проблемы, а не производственный код):
public class CurrencyFormatter {
private let formatter: NumberFormatter
public init(locale: Locale = Locale.current) {
let formatter = NumberFormatter()
formatter.locale = locale
formatter.numberStyle = .currency
self.formatter = formatter
}
// Adds currency symbol and returns a string e.g. input 1 output "£1"
public func formatWithCurrencySymbol(value: Decimal, currencyCode: String) -> String? {
formatter.currencyCode = currencyCode
// Workaround for cases when the currency behaviour rounds small negative values (<0.0051) to -0.00, where we don't want to have a - sign
var value = value
if value < 0 {
let roundedValue = round(Double(truncating: value as NSDecimalNumber) * 100.0)
if roundedValue == 0 && roundedValue.sign == .minus {
value = 0
}
}
return formatter.string(for: value)
}
public func formatWithCurrencySymbolNoWorkaround(value: Decimal, currencyCode: String) -> String? {
formatter.currencyCode = currencyCode
return formatter.string(for: value)
}
}
let formatter = CurrencyFormatter()
formatter.formatWithCurrencySymbol(value: 0.01, currencyCode: "USD") // "$0.01"
formatter.formatWithCurrencySymbol(value: -0.001, currencyCode: "EUR") // "€0.00"
formatter.formatWithCurrencySymbol(value: -0.0002, currencyCode: "EUR") // "€0.00"
formatter.formatWithCurrencySymbol(value: -0.01, currencyCode: "EUR") // "-€0.01"
formatter.formatWithCurrencySymbol(value: 0.01, currencyCode: "USD") // "$0.01"
formatter.formatWithCurrencySymbol(value: -0.001, currencyCode: "EUR") // "-€0.00"
formatter.formatWithCurrencySymbol(value: -0.0002, currencyCode: "EUR") // "-€0.00"
formatter.formatWithCurrencySymbol(value: -0.01, currencyCode: "EUR") // "-€0.01"
formatter.formatWithCurrencySymbolNoWorkaround(value: -0.005, currencyCode: "EUR") // "-€0.00"