feat: v2
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import Foundation
|
||||
|
||||
/// Форматирование рыночных значений.
|
||||
///
|
||||
/// `NumberFormatter`/`DateFormatter` дороги в создании, поэтому все экземпляры
|
||||
/// кэшируются (чтение форматтеров потокобезопасно начиная с macOS 10.9).
|
||||
enum MarketFormatting {
|
||||
|
||||
// MARK: - Публичное API
|
||||
|
||||
/// Цена с точностью, зависящей от порядка величины:
|
||||
/// «70 324,00», «90,0800», «0,338200».
|
||||
static func price(_ value: Double) -> String {
|
||||
priceFormatter(for: value).string(from: NSNumber(value: value))
|
||||
?? String(format: "%.2f", value)
|
||||
}
|
||||
|
||||
/// Абсолютное изменение со знаком: «+1 676,00».
|
||||
static func signedAmount(_ value: Double) -> String {
|
||||
let formatter = abs(value) >= 100 ? signedTwoDigits : signedFourDigits
|
||||
return formatter.string(from: NSNumber(value: value))
|
||||
?? String(format: "%+.2f", value)
|
||||
}
|
||||
|
||||
/// Доля → проценты: 0.0234 → «2.34%» или «+2.34%».
|
||||
static func percent(_ share: Double, signed: Bool) -> String {
|
||||
String(format: signed ? "%+.2f%%" : "%.2f%%", share * 100)
|
||||
}
|
||||
|
||||
/// Метка обновления: «27 октября 17:10» или «17:10».
|
||||
static func updated(_ date: Date, withDate: Bool) -> String {
|
||||
(withDate ? dateTime : timeOnly).string(from: date)
|
||||
}
|
||||
|
||||
// MARK: - Кэш форматтеров
|
||||
|
||||
private static let priceTwoDigits = decimal(maxFraction: 2)
|
||||
private static let priceFourDigits = decimal(maxFraction: 4)
|
||||
private static let priceSixDigits = decimal(maxFraction: 6)
|
||||
private static let signedTwoDigits = decimal(maxFraction: 2, signed: true)
|
||||
private static let signedFourDigits = decimal(maxFraction: 4, signed: true)
|
||||
|
||||
private static func priceFormatter(for value: Double) -> NumberFormatter {
|
||||
switch abs(value) {
|
||||
case 1000...: priceTwoDigits
|
||||
case 1...: priceFourDigits
|
||||
default: priceSixDigits
|
||||
}
|
||||
}
|
||||
|
||||
private static func decimal(maxFraction: Int, signed: Bool = false) -> NumberFormatter {
|
||||
let formatter = NumberFormatter()
|
||||
formatter.numberStyle = .decimal
|
||||
formatter.minimumFractionDigits = 2
|
||||
formatter.maximumFractionDigits = maxFraction
|
||||
if signed {
|
||||
formatter.positivePrefix = formatter.plusSign
|
||||
}
|
||||
return formatter
|
||||
}
|
||||
|
||||
private static let dateTime = dateFormatter("d MMMM HH:mm")
|
||||
private static let timeOnly = dateFormatter("HH:mm")
|
||||
|
||||
private static func dateFormatter(_ format: String) -> DateFormatter {
|
||||
let formatter = DateFormatter()
|
||||
formatter.locale = .current
|
||||
formatter.dateFormat = format
|
||||
return formatter
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user