InvestmentTrackerApp/InvestmentTracker/Utilities/Extensions/Decimal+Extensions.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
}
}