mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
251 lines
7.9 KiB
Swift
251 lines
7.9 KiB
Swift
import Foundation
|
|
import AppBundle
|
|
|
|
private final class CurrencyFormatterEntry {
|
|
let symbol: String
|
|
let thousandsSeparator: String
|
|
let decimalSeparator: String
|
|
let symbolOnLeft: Bool
|
|
let spaceBetweenAmountAndSymbol: Bool
|
|
let decimalDigits: Int
|
|
|
|
init(symbol: String, thousandsSeparator: String, decimalSeparator: String, symbolOnLeft: Bool, spaceBetweenAmountAndSymbol: Bool, decimalDigits: Int) {
|
|
self.symbol = symbol
|
|
self.thousandsSeparator = thousandsSeparator
|
|
self.decimalSeparator = decimalSeparator
|
|
self.symbolOnLeft = symbolOnLeft
|
|
self.spaceBetweenAmountAndSymbol = spaceBetweenAmountAndSymbol
|
|
self.decimalDigits = decimalDigits
|
|
}
|
|
}
|
|
|
|
private func getCurrencyExp(currency: String) -> Int {
|
|
switch currency {
|
|
case "CLF":
|
|
return 4
|
|
case "BHD", "IQD", "JOD", "KWD", "LYD", "OMR", "TND":
|
|
return 3
|
|
case "BIF", "BYR", "CLP", "CVE", "DJF", "GNF", "ISK", "JPY", "KMF", "KRW", "MGA", "PYG", "RWF", "UGX", "UYI", "VND", "VUV", "XAF", "XOF", "XPF":
|
|
return 0
|
|
case "MRO":
|
|
return 1
|
|
default:
|
|
return 2
|
|
}
|
|
}
|
|
|
|
private func loadCurrencyFormatterEntries() -> [String: CurrencyFormatterEntry] {
|
|
guard let filePath = getAppBundle().path(forResource: "currencies", ofType: "json") else {
|
|
return [:]
|
|
}
|
|
guard let data = try? Data(contentsOf: URL(fileURLWithPath: filePath)) else {
|
|
return [:]
|
|
}
|
|
|
|
guard let object = try? JSONSerialization.jsonObject(with: data, options: []), let dict = object as? [String: AnyObject] else {
|
|
return [:]
|
|
}
|
|
|
|
var result: [String: CurrencyFormatterEntry] = [:]
|
|
|
|
for (code, contents) in dict {
|
|
if let contentsDict = contents as? [String: AnyObject] {
|
|
let entry = CurrencyFormatterEntry(
|
|
symbol: contentsDict["symbol"] as! String,
|
|
thousandsSeparator: contentsDict["thousandsSeparator"] as! String,
|
|
decimalSeparator: contentsDict["decimalSeparator"] as! String,
|
|
symbolOnLeft: (contentsDict["symbolOnLeft"] as! NSNumber).boolValue,
|
|
spaceBetweenAmountAndSymbol: (contentsDict["spaceBetweenAmountAndSymbol"] as! NSNumber).boolValue,
|
|
decimalDigits: getCurrencyExp(currency: code.uppercased())
|
|
)
|
|
result[code] = entry
|
|
result[code.lowercased()] = entry
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
private let currencyFormatterEntries = loadCurrencyFormatterEntries()
|
|
|
|
public func setupCurrencyNumberFormatter(currency: String) -> NumberFormatter {
|
|
guard let entry = currencyFormatterEntries[currency] ?? currencyFormatterEntries["USD"] else {
|
|
preconditionFailure()
|
|
}
|
|
|
|
var result = ""
|
|
if entry.symbolOnLeft {
|
|
result.append("¤")
|
|
if entry.spaceBetweenAmountAndSymbol {
|
|
result.append(" ")
|
|
}
|
|
}
|
|
|
|
result.append("#")
|
|
|
|
if entry.decimalDigits != 0 {
|
|
result.append(entry.decimalSeparator)
|
|
}
|
|
|
|
for _ in 0 ..< entry.decimalDigits {
|
|
result.append("#")
|
|
}
|
|
if entry.decimalDigits != 0 {
|
|
result.append("0")
|
|
}
|
|
|
|
if !entry.symbolOnLeft {
|
|
if entry.spaceBetweenAmountAndSymbol {
|
|
result.append(" ")
|
|
}
|
|
result.append("¤")
|
|
}
|
|
|
|
let numberFormatter = NumberFormatter()
|
|
|
|
numberFormatter.numberStyle = .currency
|
|
|
|
numberFormatter.positiveFormat = result
|
|
numberFormatter.negativeFormat = "-\(result)"
|
|
|
|
numberFormatter.currencySymbol = ""
|
|
numberFormatter.currencyDecimalSeparator = entry.decimalSeparator
|
|
numberFormatter.currencyGroupingSeparator = entry.thousandsSeparator
|
|
|
|
numberFormatter.minimumFractionDigits = entry.decimalDigits
|
|
numberFormatter.maximumFractionDigits = entry.decimalDigits
|
|
numberFormatter.minimumIntegerDigits = 1
|
|
|
|
return numberFormatter
|
|
}
|
|
|
|
public func fractionalToCurrencyAmount(value: Double, currency: String) -> Int64? {
|
|
guard let entry = currencyFormatterEntries[currency] ?? currencyFormatterEntries["USD"] else {
|
|
return nil
|
|
}
|
|
var factor: Double = 1.0
|
|
for _ in 0 ..< entry.decimalDigits {
|
|
factor *= 10.0
|
|
}
|
|
if value > Double(Int64.max) / factor {
|
|
return nil
|
|
} else {
|
|
return Int64(value * factor)
|
|
}
|
|
}
|
|
|
|
public func currencyToFractionalAmount(value: Int64, currency: String) -> Double? {
|
|
guard let entry = currencyFormatterEntries[currency] ?? currencyFormatterEntries["USD"] else {
|
|
return nil
|
|
}
|
|
var factor: Double = 1.0
|
|
for _ in 0 ..< entry.decimalDigits {
|
|
factor *= 10.0
|
|
}
|
|
return Double(value) / factor
|
|
}
|
|
|
|
public func formatCurrencyAmount(_ amount: Int64, currency: String) -> String {
|
|
if let entry = currencyFormatterEntries[currency] ?? currencyFormatterEntries["USD"] {
|
|
var result = ""
|
|
if amount < 0 {
|
|
result.append("-")
|
|
}
|
|
if entry.symbolOnLeft {
|
|
result.append(entry.symbol)
|
|
if entry.spaceBetweenAmountAndSymbol {
|
|
result.append(" ")
|
|
}
|
|
}
|
|
var integerPart = abs(amount)
|
|
var fractional: [Character] = []
|
|
for _ in 0 ..< entry.decimalDigits {
|
|
let part = integerPart % 10
|
|
integerPart /= 10
|
|
if let scalar = UnicodeScalar(UInt32(part + 48)) {
|
|
fractional.append(Character(scalar))
|
|
}
|
|
}
|
|
result.append("\(integerPart)")
|
|
if !fractional.isEmpty {
|
|
result.append(entry.decimalSeparator)
|
|
}
|
|
for i in 0 ..< fractional.count {
|
|
result.append(fractional[fractional.count - i - 1])
|
|
}
|
|
if !entry.symbolOnLeft {
|
|
if entry.spaceBetweenAmountAndSymbol {
|
|
result.append(" ")
|
|
}
|
|
result.append(entry.symbol)
|
|
}
|
|
|
|
return result
|
|
} else {
|
|
assertionFailure()
|
|
let formatter = NumberFormatter()
|
|
formatter.numberStyle = .currency
|
|
formatter.currencyCode = currency
|
|
formatter.negativeFormat = "-¤#,##0.00"
|
|
return formatter.string(from: (Float(amount) * 0.01) as NSNumber) ?? ""
|
|
}
|
|
}
|
|
|
|
public func formatCurrencyAmountCustom(_ amount: Int64, currency: String) -> (String, String, Bool) {
|
|
if let entry = currencyFormatterEntries[currency] ?? currencyFormatterEntries["USD"] {
|
|
var result = ""
|
|
if amount < 0 {
|
|
result.append("-")
|
|
}
|
|
/*if entry.symbolOnLeft {
|
|
result.append(entry.symbol)
|
|
if entry.spaceBetweenAmountAndSymbol {
|
|
result.append(" ")
|
|
}
|
|
}*/
|
|
var integerPart = abs(amount)
|
|
var fractional: [Character] = []
|
|
for _ in 0 ..< entry.decimalDigits {
|
|
let part = integerPart % 10
|
|
integerPart /= 10
|
|
if let scalar = UnicodeScalar(UInt32(part + 48)) {
|
|
fractional.append(Character(scalar))
|
|
}
|
|
}
|
|
result.append("\(integerPart)")
|
|
if !fractional.isEmpty {
|
|
result.append(entry.decimalSeparator)
|
|
}
|
|
for i in 0 ..< fractional.count {
|
|
result.append(fractional[fractional.count - i - 1])
|
|
}
|
|
/*if !entry.symbolOnLeft {
|
|
if entry.spaceBetweenAmountAndSymbol {
|
|
result.append(" ")
|
|
}
|
|
result.append(entry.symbol)
|
|
}*/
|
|
|
|
return (result, entry.symbol, entry.symbolOnLeft)
|
|
} else {
|
|
return ("", "", false)
|
|
}
|
|
}
|
|
|
|
public struct CurrencyFormat {
|
|
public var symbol: String
|
|
public var symbolOnLeft: Bool
|
|
public var decimalSeparator: String
|
|
public var decimalDigits: Int
|
|
|
|
public init?(currency: String) {
|
|
guard let entry = currencyFormatterEntries[currency] else {
|
|
return nil
|
|
}
|
|
self.symbol = entry.symbol
|
|
self.symbolOnLeft = entry.symbolOnLeft
|
|
self.decimalSeparator = entry.decimalSeparator
|
|
self.decimalDigits = entry.decimalDigits
|
|
}
|
|
}
|