128 lines
3.0 KiB
Swift
128 lines
3.0 KiB
Swift
import Foundation
|
|
|
|
extension Decimal {
|
|
// MARK: - Formatting
|
|
|
|
var currencyString: String {
|
|
let formatter = NumberFormatter()
|
|
formatter.numberStyle = .currency
|
|
formatter.currencyCode = "EUR"
|
|
formatter.maximumFractionDigits = 2
|
|
return formatter.string(from: self as NSDecimalNumber) ?? "€0.00"
|
|
}
|
|
|
|
var compactCurrencyString: String {
|
|
let formatter = NumberFormatter()
|
|
formatter.numberStyle = .currency
|
|
formatter.currencyCode = "EUR"
|
|
formatter.maximumFractionDigits = 0
|
|
return formatter.string(from: self as NSDecimalNumber) ?? "€0"
|
|
}
|
|
|
|
var shortCurrencyString: String {
|
|
let value = NSDecimalNumber(decimal: self).doubleValue
|
|
|
|
switch abs(value) {
|
|
case 1_000_000...:
|
|
return String(format: "€%.1fM", value / 1_000_000)
|
|
case 1_000...:
|
|
return String(format: "€%.1fK", value / 1_000)
|
|
default:
|
|
return compactCurrencyString
|
|
}
|
|
}
|
|
|
|
var percentageString: String {
|
|
let formatter = NumberFormatter()
|
|
formatter.numberStyle = .percent
|
|
formatter.maximumFractionDigits = 2
|
|
formatter.multiplier = 1
|
|
return formatter.string(from: self as NSDecimalNumber) ?? "0%"
|
|
}
|
|
|
|
var signedPercentageString: String {
|
|
let prefix = self >= 0 ? "+" : ""
|
|
return prefix + percentageString
|
|
}
|
|
|
|
var decimalString: String {
|
|
let formatter = NumberFormatter()
|
|
formatter.numberStyle = .decimal
|
|
formatter.maximumFractionDigits = 2
|
|
return formatter.string(from: self as NSDecimalNumber) ?? "0"
|
|
}
|
|
|
|
// MARK: - Conversions
|
|
|
|
var doubleValue: Double {
|
|
NSDecimalNumber(decimal: self).doubleValue
|
|
}
|
|
|
|
var intValue: Int {
|
|
NSDecimalNumber(decimal: self).intValue
|
|
}
|
|
|
|
// MARK: - Math Operations
|
|
|
|
var abs: Decimal {
|
|
self < 0 ? -self : self
|
|
}
|
|
|
|
func rounded(scale: Int = 2) -> Decimal {
|
|
var result = Decimal()
|
|
var mutableSelf = self
|
|
NSDecimalRound(&result, &mutableSelf, scale, .plain)
|
|
return result
|
|
}
|
|
|
|
// MARK: - Comparisons
|
|
|
|
var isPositive: Bool {
|
|
self > 0
|
|
}
|
|
|
|
var isNegative: Bool {
|
|
self < 0
|
|
}
|
|
|
|
var isZero: Bool {
|
|
self == 0
|
|
}
|
|
|
|
// MARK: - Static Helpers
|
|
|
|
static func from(_ double: Double) -> Decimal {
|
|
Decimal(double)
|
|
}
|
|
|
|
static func from(_ string: String) -> Decimal? {
|
|
let formatter = NumberFormatter()
|
|
formatter.numberStyle = .decimal
|
|
return formatter.number(from: string)?.decimalValue
|
|
}
|
|
}
|
|
|
|
// MARK: - NSDecimalNumber Extension
|
|
|
|
extension NSDecimalNumber {
|
|
var currencyString: String {
|
|
decimalValue.currencyString
|
|
}
|
|
|
|
var compactCurrencyString: String {
|
|
decimalValue.compactCurrencyString
|
|
}
|
|
}
|
|
|
|
// MARK: - Optional Decimal
|
|
|
|
extension Optional where Wrapped == Decimal {
|
|
var orZero: Decimal {
|
|
self ?? Decimal.zero
|
|
}
|
|
|
|
var currencyString: String {
|
|
(self ?? Decimal.zero).currencyString
|
|
}
|
|
}
|