Merge pull request #3740 from eviltofu/3531_Override_Locale_Number_Formatting

Removed unused Formatters, CurrencyFormatter and other NumberFormatters replaced with Formatters #3531
pull/3758/head
Jerome Chan 3 years ago committed by GitHub
commit 90820dfb6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 28
      AlphaWallet.xcodeproj/project.pbxproj
  2. 2
      AlphaWallet/Accounts/ViewModels/WalletSummaryViewModel.swift
  3. 2
      AlphaWallet/Alerts/ViewControllers/EditPriceAlertViewController.swift
  4. 4
      AlphaWallet/Alerts/ViewModels/EditPriceAlertViewModel.swift
  5. 4
      AlphaWallet/Browser/Coordinators/QRCodeResolutionCoordinator.swift
  6. 2
      AlphaWallet/Core/Coordinators/Alerts/Types/PriceAlert.swift
  7. 84
      AlphaWallet/Core/Formatters/CurrencyFormatter.swift
  8. 2
      AlphaWallet/Core/Types/ERC20BalanceViewModel.swift
  9. 2
      AlphaWallet/Core/Types/NativecryptoBalanceViewModel.swift
  10. 4
      AlphaWallet/Core/Types/WalletBalance.swift
  11. 4
      AlphaWallet/Core/Types/WalletSummary.swift
  12. 2
      AlphaWallet/Export/ViewModels/PromptBackupWalletAfterExceedingThresholdViewViewModel.swift
  13. 67
      AlphaWallet/Foundation/DecimalFormatter.swift
  14. 124
      AlphaWallet/Foundation/Formatter.swift
  15. 32
      AlphaWallet/Foundation/StringFormatter.swift
  16. 6
      AlphaWallet/Tokens/ViewModels/EthTokenViewCellViewModel.swift
  17. 4
      AlphaWallet/Tokens/ViewModels/FungibleTokenViewCellViewModel.swift
  18. 2
      AlphaWallet/Transactions/ViewModels/BalanceViewModel.swift
  19. 2
      AlphaWallet/Transactions/Views/TokenHistoryChartView.swift
  20. 3
      AlphaWallet/Transactions/Views/XYMarkerView.swift
  21. 2
      AlphaWallet/Transfer/Types/CurrencyRate+Fee.swift
  22. 4
      AlphaWallet/Transfer/ViewControllers/SendViewController.swift
  23. 13
      AlphaWallet/Transfer/ViewModels/ConfigureTransactionViewModel.swift
  24. 16
      AlphaWallet/Transfer/ViewModels/SendHeaderViewViewModel.swift
  25. 50
      AlphaWalletTests/Foundation/DecimalNumberFormatterTest.swift
  26. 165
      AlphaWalletTests/Foundation/FormatterTests.swift

@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
021746122763311D00BAF19C /* ExportJsonKeystoreFileViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 021746112763311D00BAF19C /* ExportJsonKeystoreFileViewModel.swift */; };
02220CFC273A9A02006A09BF /* SaveCustomRpcCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02220CFB273A9A02006A09BF /* SaveCustomRpcCoordinator.swift */; };
0224D26727980664003D022A /* FormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0224D26627980664003D022A /* FormatterTests.swift */; };
022CED7E277B01E10043287F /* ScrollableSegmentedControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022CED7B277B01E10043287F /* ScrollableSegmentedControl.swift */; };
022CED7F277B01E10043287F /* ScrollableSegmentedControlHighlightableLineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022CED7C277B01E10043287F /* ScrollableSegmentedControlHighlightableLineView.swift */; };
022CED80277B01E10043287F /* ScrollableSegmentedControlCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022CED7D277B01E10043287F /* ScrollableSegmentedControlCell.swift */; };
@ -35,6 +36,7 @@
02D8BF89277D56F700EEE8E9 /* SaveCustomRpcManualEntryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D8BF88277D56F700EEE8E9 /* SaveCustomRpcManualEntryViewModel.swift */; };
02D8BF8B277D570900EEE8E9 /* SaveCustomRpcManualEntryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D8BF8A277D570900EEE8E9 /* SaveCustomRpcManualEntryViewController.swift */; };
02D8BF8D277D572600EEE8E9 /* SaveCustomRpcManualEntryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D8BF8C277D572600EEE8E9 /* SaveCustomRpcManualEntryView.swift */; };
02E7B6782795352E00311218 /* Formatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02E7B6772795352E00311218 /* Formatter.swift */; };
02F4E8B627715EA000D89C19 /* SaveCustomRpcOverallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F4E8B527715EA000D89C19 /* SaveCustomRpcOverallViewController.swift */; };
02F4E8B827715EC100D89C19 /* SaveCustomRpcOverallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F4E8B727715EC100D89C19 /* SaveCustomRpcOverallView.swift */; };
02F4E8BC2771763800D89C19 /* SaveCustomRpcOverallModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F4E8BB2771763800D89C19 /* SaveCustomRpcOverallModel.swift */; };
@ -91,7 +93,6 @@
2959961C1FAE3EDF00DB66A8 /* AlphaWalletService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2959961B1FAE3EDF00DB66A8 /* AlphaWalletService.swift */; };
2959961F1FAE759700DB66A8 /* RawTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2959961E1FAE759700DB66A8 /* RawTransaction.swift */; };
295A59381F71C1B90092F0FC /* AccountsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 295A59371F71C1B90092F0FC /* AccountsCoordinator.swift */; };
295B61D41FE7D5B500642E60 /* CurrencyFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 295B61D31FE7D5B500642E60 /* CurrencyFormatter.swift */; };
295B61D61FE7FC8300642E60 /* FakeTokensDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 295B61D51FE7FC8300642E60 /* FakeTokensDataStore.swift */; };
296105931FA2AA2100292494 /* UnsignedTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 296105921FA2AA2100292494 /* UnsignedTransaction.swift */; };
296105951FA2DEF000292494 /* TransactionDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 296105941FA2DEF000292494 /* TransactionDirection.swift */; };
@ -700,8 +701,6 @@
73C41C71201B46AD00243C6C /* LockEnterPasscodeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73C41C70201B46AD00243C6C /* LockEnterPasscodeViewModel.swift */; };
73C41C73201B5EFF00243C6C /* LockCreatePasscodeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73C41C72201B5EFF00243C6C /* LockCreatePasscodeViewModel.swift */; };
73CBC761202139FB00374666 /* FakeGetBalanceCoordinator(.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73CBC760202139FB00374666 /* FakeGetBalanceCoordinator(.swift */; };
73D26837202E827E009777A1 /* DecimalFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73D26836202E827E009777A1 /* DecimalFormatter.swift */; };
73D2683B202E8411009777A1 /* DecimalNumberFormatterTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73D2683A202E8411009777A1 /* DecimalNumberFormatterTest.swift */; };
73ED85A520349BE400593BF3 /* StringFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73ED85A420349BE400593BF3 /* StringFormatter.swift */; };
73ED85A72034BFEF00593BF3 /* UITextFieldAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73ED85A62034BFEF00593BF3 /* UITextFieldAdditions.swift */; };
73ED85A92034C42D00593BF3 /* StringFormatterTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73ED85A82034C42D00593BF3 /* StringFormatterTest.swift */; };
@ -1093,6 +1092,7 @@
/* Begin PBXFileReference section */
021746112763311D00BAF19C /* ExportJsonKeystoreFileViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExportJsonKeystoreFileViewModel.swift; sourceTree = "<group>"; };
02220CFB273A9A02006A09BF /* SaveCustomRpcCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SaveCustomRpcCoordinator.swift; sourceTree = "<group>"; };
0224D26627980664003D022A /* FormatterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormatterTests.swift; sourceTree = "<group>"; };
022CED7B277B01E10043287F /* ScrollableSegmentedControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScrollableSegmentedControl.swift; sourceTree = "<group>"; };
022CED7C277B01E10043287F /* ScrollableSegmentedControlHighlightableLineView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScrollableSegmentedControlHighlightableLineView.swift; sourceTree = "<group>"; };
022CED7D277B01E10043287F /* ScrollableSegmentedControlCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScrollableSegmentedControlCell.swift; sourceTree = "<group>"; };
@ -1119,6 +1119,7 @@
02D8BF88277D56F700EEE8E9 /* SaveCustomRpcManualEntryViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SaveCustomRpcManualEntryViewModel.swift; sourceTree = "<group>"; };
02D8BF8A277D570900EEE8E9 /* SaveCustomRpcManualEntryViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SaveCustomRpcManualEntryViewController.swift; sourceTree = "<group>"; };
02D8BF8C277D572600EEE8E9 /* SaveCustomRpcManualEntryView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SaveCustomRpcManualEntryView.swift; sourceTree = "<group>"; };
02E7B6772795352E00311218 /* Formatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Formatter.swift; sourceTree = "<group>"; };
02F4E8B527715EA000D89C19 /* SaveCustomRpcOverallViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveCustomRpcOverallViewController.swift; sourceTree = "<group>"; };
02F4E8B727715EC100D89C19 /* SaveCustomRpcOverallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveCustomRpcOverallView.swift; sourceTree = "<group>"; };
02F4E8BB2771763800D89C19 /* SaveCustomRpcOverallModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveCustomRpcOverallModel.swift; sourceTree = "<group>"; };
@ -1180,7 +1181,6 @@
2959961B1FAE3EDF00DB66A8 /* AlphaWalletService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlphaWalletService.swift; sourceTree = "<group>"; };
2959961E1FAE759700DB66A8 /* RawTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RawTransaction.swift; sourceTree = "<group>"; };
295A59371F71C1B90092F0FC /* AccountsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsCoordinator.swift; sourceTree = "<group>"; };
295B61D31FE7D5B500642E60 /* CurrencyFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyFormatter.swift; sourceTree = "<group>"; };
295B61D51FE7FC8300642E60 /* FakeTokensDataStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakeTokensDataStore.swift; sourceTree = "<group>"; };
296105921FA2AA2100292494 /* UnsignedTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsignedTransaction.swift; sourceTree = "<group>"; };
296105941FA2DEF000292494 /* TransactionDirection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionDirection.swift; sourceTree = "<group>"; };
@ -1790,8 +1790,6 @@
73C41C70201B46AD00243C6C /* LockEnterPasscodeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockEnterPasscodeViewModel.swift; sourceTree = "<group>"; };
73C41C72201B5EFF00243C6C /* LockCreatePasscodeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockCreatePasscodeViewModel.swift; sourceTree = "<group>"; };
73CBC760202139FB00374666 /* FakeGetBalanceCoordinator(.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FakeGetBalanceCoordinator(.swift"; sourceTree = "<group>"; };
73D26836202E827E009777A1 /* DecimalFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecimalFormatter.swift; sourceTree = "<group>"; };
73D2683A202E8411009777A1 /* DecimalNumberFormatterTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecimalNumberFormatterTest.swift; sourceTree = "<group>"; };
73ED85A420349BE400593BF3 /* StringFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringFormatter.swift; sourceTree = "<group>"; };
73ED85A62034BFEF00593BF3 /* UITextFieldAdditions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITextFieldAdditions.swift; sourceTree = "<group>"; };
73ED85A82034C42D00593BF3 /* StringFormatterTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringFormatterTest.swift; sourceTree = "<group>"; };
@ -2577,14 +2575,6 @@
path = TrustClient;
sourceTree = "<group>";
};
295B61D21FE7D5AB00642E60 /* Formatters */ = {
isa = PBXGroup;
children = (
295B61D31FE7D5B500642E60 /* CurrencyFormatter.swift */,
);
path = Formatters;
sourceTree = "<group>";
};
296106C01F7640240006164B /* Tokens */ = {
isa = PBXGroup;
children = (
@ -2936,8 +2926,8 @@
children = (
299573A11FA1F369006F17FD /* QRCodeValueParserTests.swift */,
61FC5ED01FCFBDEB00CCB12A /* EtherNumberFormatterTests.swift */,
73D2683A202E8411009777A1 /* DecimalNumberFormatterTest.swift */,
73ED85A82034C42D00593BF3 /* StringFormatterTest.swift */,
0224D26627980664003D022A /* FormatterTests.swift */,
);
path = Foundation;
sourceTree = "<group>";
@ -3069,7 +3059,6 @@
29AD8A0A1F93FBB7008E10E7 /* Foundation */ = {
isa = PBXGroup;
children = (
73D26836202E827E009777A1 /* DecimalFormatter.swift */,
29FC0CB71F8299510036089F /* Coordinator.swift */,
29AD8A0B1F93FBBF008E10E7 /* Subscribable.swift */,
2995739E1FA1F294006F17FD /* QRCodeValueParser.swift */,
@ -3079,6 +3068,7 @@
5E7C762E8065342D6B80BE56 /* CoordinatorThatEnds.swift */,
5E7C7AE608A39793F8BA3911 /* Eip681Parser.swift */,
5E7C7C4A58D1A4361E4F66E0 /* AddressOrEnsName.swift */,
02E7B6772795352E00311218 /* Formatter.swift */,
);
path = Foundation;
sourceTree = "<group>";
@ -3368,7 +3358,6 @@
879599482604A5A2006722B2 /* CoinTicker */,
87584B4225EFAFB60070063B /* BuyToken */,
87B65268256FBF22000EF927 /* SwapToken */,
295B61D21FE7D5AB00642E60 /* Formatters */,
29E9CFD01FE737EE00017744 /* Types */,
CCA4FE341FD427CA00749AE4 /* Helpers */,
CCCD74FF1FD2D95F004A087D /* Coordinators */,
@ -5752,13 +5741,11 @@
296421951F70C1EC00EB363B /* LoadingView.swift in Sources */,
87D732692763E59700375C18 /* FungiblesTransactionAmount.swift in Sources */,
2961BD071FB146EB00C4B840 /* ChainState.swift in Sources */,
73D26837202E827E009777A1 /* DecimalFormatter.swift in Sources */,
879F184426E73BFF000602F2 /* SingleTokenCardSelectionView.swift in Sources */,
2996F14D1F6CA743005C33AE /* UIViewController.swift in Sources */,
2959961F1FAE759700DB66A8 /* RawTransaction.swift in Sources */,
87E2555824F52EBF00F025F7 /* GasSpeedTableViewCellViewModel.swift in Sources */,
025F5D202760C76A00B2A3BC /* ExportJsonKeystorePasswordView.swift in Sources */,
295B61D41FE7D5B500642E60 /* CurrencyFormatter.swift in Sources */,
296421991F70C1F900EB363B /* EmptyView.swift in Sources */,
8728FFE527429967008E5524 /* TokensCardCollectionViewControllerViewModel.swift in Sources */,
8795994A2604A5B6006722B2 /* CoinTickersFetcher.swift in Sources */,
@ -6277,6 +6264,7 @@
5E7C745ECFCAE8B1A52B7FAC /* EnabledServersViewModel.swift in Sources */,
5E7C78FF93B0DD68700FAFB6 /* NativeCryptoCurrencyBalanceView.swift in Sources */,
5E7C751D847B47B2BA67F6B5 /* PaymentFlowFromEip681UrlResolver.swift in Sources */,
02E7B6782795352E00311218 /* Formatter.swift in Sources */,
5E7C76C8A983A91A82F646E5 /* TokenInstanceWebView.swift in Sources */,
5E7C742DDE5C63804A2C420D /* Collection+UIView.swift in Sources */,
8712A38526F475A20009C376 /* PriceAlertDataStore.swift in Sources */,
@ -6577,7 +6565,6 @@
29FF13081F75F0AE00AFD326 /* AppCoordinatorTests.swift in Sources */,
2923D9B71FDA5E51000CF3F8 /* PasswordGeneratorTests.swift in Sources */,
29F1C865200384FE003780D8 /* Wallet.swift in Sources */,
73D2683B202E8411009777A1 /* DecimalNumberFormatterTest.swift in Sources */,
29FF130D1F7626E800AFD326 /* FakeNavigationController.swift in Sources */,
61DCE17D2001A7A20053939F /* RLPTests.swift in Sources */,
299573A41FA27A15006F17FD /* TestKeyStore.swift in Sources */,
@ -6625,6 +6612,7 @@
2981F4731F8303E600CA6590 /* TransactionCoordinatorTests.swift in Sources */,
76F1D137B10D8309E513BBDD /* OrderSigningTests.swift in Sources */,
76F1D13FC8A41AD967C59947 /* ClaimOrderCoordinatorTests.swift in Sources */,
0224D26727980664003D022A /* FormatterTests.swift in Sources */,
76F1DD10DF9A6C844E5F57D6 /* CreateRedeemTests.swift in Sources */,
87F9972824E155280092D262 /* SeedPhraseBackupIntroductionViewControllerTests.swift in Sources */,
442FC8E82231273273B95D85 /* FakeClaimOrderCoordinator.swift in Sources */,

@ -74,7 +74,7 @@ extension WalletSummaryViewModel {
static func todaysApprecationColorAndStringValuePair(summary: WalletSummary?) -> (String, UIColor) {
let valueChangeValue: String = {
if let value = summary?.changeDouble {
return NumberFormatter.usd(format: .priceChangeFormat).string(from: value) ?? "-"
return Formatter.priceChange.string(from: value) ?? "-"
} else {
return "-"
}

@ -126,7 +126,7 @@ class EditPriceAlertViewController: UIViewController {
}
@objc private func saveAlertSelected(_ sender: UIButton) {
guard let value = amountTextField.value.flatMap({ NumberFormatter().number(from: $0) }), let marketPrice = viewModel.marketPrice else { return }
guard let value = amountTextField.value.flatMap({ Formatter.default.number(from: $0) }), let marketPrice = viewModel.marketPrice else { return }
switch viewModel.configuration {
case .create:

@ -57,7 +57,7 @@ struct EditPriceAlertViewModel {
var marketPriceString: String {
let value: String = {
guard let value = marketPrice else { return "-" }
return NumberFormatter.usd(format: .fiatFormat).string(from: value) ?? "-"
return Formatter.fiat.string(from: value) ?? "-"
}()
return "Current price: \(value)"
@ -65,6 +65,6 @@ struct EditPriceAlertViewModel {
var isEditingAvailable: Bool {
guard let value = marketPrice else { return false }
return NumberFormatter.usd(format: .fiatFormat).string(from: value) != nil
return Formatter.fiat.string(from: value) != nil
}
}

@ -293,9 +293,7 @@ extension QRCodeResolutionCoordinator: ScanQRCodeCoordinatorDelegate {
private extension String {
var scientificAmountToBigInt: BigInt? {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
numberFormatter.usesGroupingSeparator = false
let numberFormatter = Formatter.scientificAmount
let amountString = numberFormatter.number(from: self).flatMap { numberFormatter.string(from: $0) }
return amountString.flatMap { BigInt($0) }

@ -68,7 +68,7 @@ enum AlertType: Codable {
var title: String {
switch self {
case .price(let priceTarget, let value):
let result = NumberFormatter.usd(format: .fiatFormat).string(from: value) ?? "-"
let result = Formatter.fiat.string(from: value) ?? "-"
return "\(priceTarget.title) \(result)"
}
}

@ -1,84 +0,0 @@
// Copyright SIX DAY LLC. All rights reserved.
import Foundation
extension NumberFormatter {
static let currency = Formatter(.currency)
static let usd = Formatter(.usd(format: .withTrailingCurrency))
static let percent = Formatter(.percent)
static let shortCrypto = Formatter(.shortCrypto)
static func usd(format: USDFormat) -> Formatter {
Formatter(.usd(format: format))
}
class Formatter {
private let formatter: NumberFormatter
fileprivate init(_ configuration: NumberFormatterConfiguration) {
formatter = configuration.formatter
}
func string(from number: Double) -> String? {
return formatter.string(from: number as NSNumber)
}
}
}
enum USDFormat {
case withTrailingCurrency
case withLeadingCurrencySymbol(positiveSymbol: String)
static var priceChangeFormat: USDFormat {
.withLeadingCurrencySymbol(positiveSymbol: "+")
}
static var fiatFormat: USDFormat {
.withLeadingCurrencySymbol(positiveSymbol: "")
}
}
private enum NumberFormatterConfiguration {
case usd(format: USDFormat)
case currency
case percent
case shortCrypto
var formatter: NumberFormatter {
let formatter = NumberFormatter()
formatter.roundingMode = .down
formatter.numberStyle = .currency
formatter.minimumFractionDigits = Constants.formatterFractionDigits
formatter.maximumFractionDigits = Constants.formatterFractionDigits
switch self {
case .currency:
//TODO support multiple currency values
formatter.currencyCode = Currency.USD.rawValue
case .usd(let format):
switch format {
case .withTrailingCurrency:
formatter.positiveFormat = "0.00" + " " + Constants.Currency.usd
formatter.negativeFormat = "-0.00" + " " + Constants.Currency.usd
case .withLeadingCurrencySymbol(let positiveSymbol):
formatter.positiveFormat = positiveSymbol + "$0.00"
formatter.negativeFormat = "-$0.00"
}
formatter.currencyCode = String()
case .percent:
formatter.positiveFormat = "0.00"
formatter.negativeFormat = "-0.00"
formatter.numberStyle = .percent
case .shortCrypto:
formatter.positiveFormat = "0.0000"
formatter.negativeFormat = "-0.0000"
formatter.numberStyle = .none
formatter.minimumFractionDigits = Constants.etherFormatterFractionDigits
formatter.maximumFractionDigits = Constants.etherFormatterFractionDigits
}
return formatter
}
}

@ -39,7 +39,7 @@ struct ERC20BalanceViewModel: BalanceBaseViewModel {
var currencyAmount: String? {
guard let totalAmount = currencyAmountWithoutSymbol else { return nil }
return NumberFormatter.usd.string(from: totalAmount)
return Formatter.usd.string(from: totalAmount)
}
var currencyAmountWithoutSymbol: Double? {

@ -39,7 +39,7 @@ struct NativecryptoBalanceViewModel: BalanceBaseViewModel {
var currencyAmount: String? {
guard let totalAmount = currencyAmountWithoutSymbol else { return nil }
return NumberFormatter.usd.string(from: totalAmount)
return Formatter.usd.string(from: totalAmount)
}
var currencyAmountWithoutSymbol: Double? {

@ -18,7 +18,7 @@ struct WalletBalance: Equatable {
}
var totalAmountString: String {
if let totalAmount = totalAmountDouble, let value = NumberFormatter.usd.string(from: totalAmount) {
if let totalAmount = totalAmountDouble, let value = Formatter.usd.string(from: totalAmount) {
return value
} else if let etherAmount = etherAmountShort {
return "\(etherAmount) \(RPCServer.main.symbol)"
@ -30,7 +30,7 @@ struct WalletBalance: Equatable {
var etherAmountShort: String? {
guard let token = etherTokenObject, let value = token.valueDecimal else { return nil }
return NumberFormatter.shortCrypto.string(from: value.doubleValue)
return Formatter.shortCrypto.string(from: value.doubleValue)
}
var etherTokenObject: Activity.AssignedToken? {

@ -17,9 +17,9 @@ struct WalletSummary: Equatable {
}
var totalAmount: String {
if let amount = totalAmountDouble, let value = NumberFormatter.usd(format: .fiatFormat).string(from: amount) {
if let amount = totalAmountDouble, let value = Formatter.fiat.string(from: amount) {
return value
} else if let amount = etherTotalAmountDouble, let value = NumberFormatter.shortCrypto.string(from: amount.doubleValue) {
} else if let amount = etherTotalAmountDouble, let value = Formatter.shortCrypto.string(from: amount.doubleValue) {
return "\(value) \(RPCServer.main.symbol)"
} else {
return "--"

@ -16,7 +16,7 @@ struct PromptBackupWalletAfterExceedingThresholdViewViewModel: PromptBackupWalle
}
var description: String {
let prettyAmount = NumberFormatter.currency.string(from: dollarValueInUsd) ?? "-"
let prettyAmount = Formatter.currency.string(from: dollarValueInUsd) ?? "-"
return R.string.localizable.backupPromptAfterHittingThresholdDescription(prettyAmount)
}

@ -1,67 +0,0 @@
// Copyright SIX DAY LLC. All rights reserved.
import Foundation
final class DecimalFormatter {
var groupingSeparator: String {
return numberFormatter.groupingSeparator
}
/// Locale of a `DecimalFormatter`.
var locale: Locale
/// numberFormatter of a `DecimalFormatter` to represent current locale.
private lazy var numberFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.locale = locale
formatter.numberStyle = .decimal
formatter.isLenient = true
return formatter
}()
/// usFormatter of a `DecimalFormatter` to represent decimal separator ".".
private lazy var usFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.locale = Locale(identifier: "en_US")
formatter.numberStyle = .decimal
formatter.isLenient = true
return formatter
}()
/// frFormatter of a `DecimalFormatter` to represent decimal separator ",".
private lazy var frFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.locale = Locale(identifier: "fr_FR")
formatter.numberStyle = .decimal
formatter.isLenient = true
return formatter
}()
/// enCaFormatter of a `DecimalFormatter` to represent decimal separator "'".
private lazy var enCaFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.locale = Locale(identifier: "en_CA")
formatter.numberStyle = .decimal
formatter.isLenient = true
return formatter
}()
/// Initializes a `DecimalFormatter` with a `Locale`.
init(locale: Locale = Config.locale) {
self.locale = locale
self.numberFormatter = NumberFormatter()
self.numberFormatter.locale = self.locale
self.numberFormatter.numberStyle = .decimal
self.numberFormatter.isLenient = true
}
/// Converts a String to a `NSNumber`.
///
/// - Parameters:
/// - string: string to convert.
/// - Returns: `NSNumber` representation.
func number(from string: String) -> NSNumber? {
return numberFormatter.number(from: string) ?? usFormatter.number(from: string) ?? frFormatter.number(from: string) ?? enCaFormatter.number(from: string)
}
/// Converts a NSNumber to a `String`.
///
/// - Parameters:
/// - number: NSNumber to convert.
/// - Returns: `NSumber` representation.
func string(from number: NSNumber) -> String? {
return numberFormatter.string(from: number)
}
}

@ -0,0 +1,124 @@
//
// Formatters.swift
// AlphaWallet
//
// Created by Jerome Chan on 17/1/22.
//
import Foundation
struct Formatter {
static let currency: NumberFormatter = {
let formatter = basicCurrencyFormatter()
formatter.minimumFractionDigits = Constants.formatterFractionDigits
formatter.maximumFractionDigits = Constants.formatterFractionDigits
formatter.currencySymbol = "$"
return formatter
}()
static let usd: NumberFormatter = {
let formatter = basicCurrencyFormatter()
formatter.positiveFormat = ",###.# " + Constants.Currency.usd
formatter.negativeFormat = "-,###.# " + Constants.Currency.usd
formatter.minimumFractionDigits = Constants.formatterFractionDigits
formatter.maximumFractionDigits = Constants.formatterFractionDigits
return formatter
}()
static let percent: NumberFormatter = {
let formatter = basicCurrencyFormatter()
formatter.positiveFormat = ",###.#"
formatter.negativeFormat = "-,###.#"
formatter.minimumFractionDigits = Constants.formatterFractionDigits
formatter.maximumFractionDigits = Constants.formatterFractionDigits
formatter.numberStyle = .percent
return formatter
}()
static let shortCrypto: NumberFormatter = {
let formatter = basicCurrencyFormatter()
formatter.positiveFormat = ",###.#"
formatter.negativeFormat = "-,###.#"
formatter.minimumFractionDigits = Constants.etherFormatterFractionDigits
formatter.maximumFractionDigits = Constants.etherFormatterFractionDigits
formatter.numberStyle = .none
return formatter
}()
static let priceChange: NumberFormatter = {
let formatter = basicCurrencyFormatter()
formatter.positiveFormat = "+$,###.#"
formatter.negativeFormat = "-$,###.#"
formatter.minimumFractionDigits = Constants.formatterFractionDigits
formatter.maximumFractionDigits = Constants.formatterFractionDigits
return formatter
}()
static let fiat: NumberFormatter = {
let formatter = basicCurrencyFormatter()
formatter.positiveFormat = "$,###.#"
formatter.negativeFormat = "-$,###.#"
formatter.minimumFractionDigits = Constants.formatterFractionDigits
formatter.maximumFractionDigits = Constants.formatterFractionDigits
return formatter
}()
static let `default`: NumberFormatter = {
let formatter = NumberFormatter()
return formatter
}()
static let scientificAmount: NumberFormatter = {
let formatter = Formatter.default
formatter.numberStyle = .decimal
formatter.usesGroupingSeparator = false
return formatter
}()
static let currencyAccounting: NumberFormatter = {
let formatter = basicCurrencyFormatter()
formatter.currencySymbol = ""
formatter.minimumFractionDigits = Constants.formatterFractionDigits
formatter.maximumFractionDigits = Constants.formatterFractionDigits
formatter.numberStyle = .currencyAccounting
formatter.isLenient = true
return formatter
}()
static let alternateAmount: NumberFormatter = {
let formatter = basicCurrencyFormatter()
formatter.currencySymbol = ""
formatter.minimumFractionDigits = Constants.etherFormatterFractionDigits
formatter.maximumFractionDigits = Constants.etherFormatterFractionDigits
return formatter
}()
}
fileprivate func basicCurrencyFormatter() -> NumberFormatter {
let formatter = basicNumberFormatter()
formatter.numberStyle = .currency
formatter.roundingMode = .down
return formatter
}
fileprivate func basicNumberFormatter() -> NumberFormatter {
let formatter = NumberFormatter()
formatter.locale = Locale(identifier: "en_US")
formatter.generatesDecimalNumbers = true
formatter.alwaysShowsDecimalSeparator = true
formatter.usesGroupingSeparator = true
formatter.isLenient = false
formatter.isPartialStringValidationEnabled = false
formatter.groupingSeparator = ","
formatter.decimalSeparator = "."
return formatter
}
extension NumberFormatter {
func string(from source: Double) -> String? {
return self.string(from: source as NSNumber)
}
}

@ -3,29 +3,6 @@
import UIKit
final class StringFormatter {
/// currencyFormatter of a `StringFormatter` to represent current locale.
private lazy var currencyFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.currencySymbol = ""
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2
formatter.roundingMode = .down
formatter.numberStyle = .currencyAccounting
formatter.isLenient = true
return formatter
}()
private let alternateAmountFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.currencySymbol = ""
formatter.minimumFractionDigits = Constants.etherFormatterFractionDigits
formatter.maximumFractionDigits = Constants.etherFormatterFractionDigits
formatter.roundingMode = .down
formatter.numberStyle = .currency
return formatter
}()
/// Converts a Double to a `currency String`.
///
/// - Parameters:
@ -33,7 +10,7 @@ final class StringFormatter {
/// - currencyCode: code of the currency.
/// - Returns: Currency `String` representation.
func currency(with value: Double, and currencyCode: String = "") -> String {
let formatter = currencyFormatter
let formatter = Formatter.currencyAccounting
formatter.currencyCode = currencyCode
//Trimming is important because the formatter output for `1.2` becomes "1.2 " (with trailing space) when region = Poland
return (formatter.string(from: NSNumber(value: value))?.trimmed ?? "\(value)").droppedTrailingZeros
@ -45,7 +22,7 @@ final class StringFormatter {
/// - currencyCode: code of the currency.
/// - Returns: Currency `String` representation.
func currency(with value: NSDecimalNumber, and currencyCode: String = "", usesGroupingSeparator: Bool = true) -> String {
let formatter = currencyFormatter
let formatter = Formatter.currencyAccounting
formatter.currencyCode = currencyCode
formatter.usesGroupingSeparator = usesGroupingSeparator
@ -71,10 +48,11 @@ final class StringFormatter {
}
func alternateAmount(value: NSDecimalNumber, usesGroupingSeparator: Bool = false) -> String {
alternateAmountFormatter.usesGroupingSeparator = usesGroupingSeparator
let formatter = Formatter.alternateAmount
formatter.usesGroupingSeparator = usesGroupingSeparator
//For some reasons formatter adds trailing whitespace
if let value = alternateAmountFormatter.string(from: value) {
if let value = formatter.string(from: value) {
return value.trimmingCharacters(in: .whitespacesAndNewlines).droppedTrailingZeros
} else {
return value.stringValue.droppedTrailingZeros

@ -98,7 +98,7 @@ struct EthTokenViewCellViewModel {
private var priceChangeUSDValue: String {
if let result = EthCurrencyHelper(ticker: ticker).valueChanged24h(value: token.optionalDecimalValue) {
return NumberFormatter.usd(format: .priceChangeFormat).string(from: result) ?? UiTweaks.noPriceMarker
return Formatter.priceChange.string(from: result) ?? UiTweaks.noPriceMarker
} else {
return UiTweaks.noPriceMarker
}
@ -115,7 +115,7 @@ struct EthTokenViewCellViewModel {
if token.server.isTestnet {
return UiTweaks.noPriceMarker
} else {
return currencyAmount.flatMap { NumberFormatter.usd(format: .fiatFormat).string(from: $0) ?? UiTweaks.noPriceMarker }
return currencyAmount.flatMap { Formatter.fiat.string(from: $0) ?? UiTweaks.noPriceMarker }
}
}
@ -155,7 +155,7 @@ struct EthTokenViewCellViewModel {
private func priceChangeUSDValue(ticker: CoinTicker?) -> String {
if let result = EthCurrencyHelper(ticker: ticker).valueChanged24h(value: token.optionalDecimalValue) {
return NumberFormatter.usd.string(from: result) ?? "-"
return Formatter.usd.string(from: result) ?? "-"
} else {
return "-"
}

@ -102,7 +102,7 @@ struct FungibleTokenViewCellViewModel {
private var priceChangeUSDValue: String {
if let result = EthCurrencyHelper(ticker: ticker).valueChanged24h(value: token.optionalDecimalValue) {
return NumberFormatter.usd(format: .priceChangeFormat).string(from: result) ?? UiTweaks.noPriceMarker
return Formatter.priceChange.string(from: result) ?? UiTweaks.noPriceMarker
} else {
return UiTweaks.noPriceMarker
}
@ -117,7 +117,7 @@ struct FungibleTokenViewCellViewModel {
private var fiatValue: String {
if let fiatValue = EthCurrencyHelper(ticker: ticker).fiatValue(value: token.optionalDecimalValue) {
return NumberFormatter.usd(format: .fiatFormat).string(from: fiatValue) ?? UiTweaks.noPriceMarker
return Formatter.fiat.string(from: fiatValue) ?? UiTweaks.noPriceMarker
} else {
return UiTweaks.noPriceMarker
}

@ -38,7 +38,7 @@ struct BalanceViewModel: BalanceBaseViewModel {
var currencyAmount: String? {
guard let totalAmount = currencyAmountWithoutSymbol else { return nil }
return NumberFormatter.usd.string(from: totalAmount)
return Formatter.usd.string(from: totalAmount)
}
var currencyAmountWithoutSymbol: Double? {

@ -37,7 +37,7 @@ class TokenHistoryChartView: UIView {
private class YMinMaxOnlyAxisValueFormatter: IAxisValueFormatter {
//NOTE: helper index for determining right label position
private var index: Int = 0
private let formatter = NumberFormatter.usd(format: .fiatFormat)
private let formatter = Formatter.fiat
func stringForValue(_ value: Double, axis: AxisBase?) -> String {
guard let axis = axis else { return "" }

@ -11,7 +11,6 @@ import Charts
#endif
open class XYMarkerView: BalloonMarker {
fileprivate var yFormatter = NumberFormatter()
private static let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "MM-dd-yyyy HH:mm"
@ -21,7 +20,7 @@ open class XYMarkerView: BalloonMarker {
open override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
let date = Date(timeIntervalSince1970: TimeInterval(entry.x))
let usdValue = NumberFormatter.usd.string(from: entry.y) ?? "-"
let usdValue = Formatter.usd.string(from: entry.y) ?? "-"
let dateValue = XYMarkerView.dateFormatter.string(from: date)
setLabel("\(dateValue)\n\(usdValue)")

@ -12,7 +12,7 @@ extension CurrencyRate {
guard let price = rates.filter({ $0.code.lowercased() == symbol }).first else {
return nil
}
let formattedFee = NumberFormatter.currency.string(from: price.price * feeInDouble)
let formattedFee = Formatter.currency.string(from: price.price * feeInDouble)
return formattedFee
}
}

@ -349,9 +349,7 @@ class SendViewController: UIViewController {
//This function is required because BigInt.init(String) doesn't handle scientific notation
private func convertMaybeScientificAmountToBigInt(_ maybeScientificAmountString: String) -> BigInt? {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
numberFormatter.usesGroupingSeparator = false
let numberFormatter = Formatter.scientificAmount
let amountString = numberFormatter.number(from: maybeScientificAmountString).flatMap { numberFormatter.string(from: $0) }
return amountString.flatMap { BigInt($0) }
}

@ -186,16 +186,3 @@ struct ConfigureTransactionViewModel {
}
}
}
private let numberValueFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
return formatter
}()
extension String {
var numberValue: NSNumber? {
return numberValueFormatter.number(from: self)
}
}

@ -110,7 +110,7 @@ struct TokenInfoPageViewModel {
private var maxSupplyViewModel: TickerFieldValueViewModel {
let value: String = {
if let max_supply = ticker?.max_supply, let value = NumberFormatter.usd.string(from: max_supply) {
if let max_supply = ticker?.max_supply, let value = Formatter.usd.string(from: max_supply) {
return String(value)
} else {
return "-"
@ -127,7 +127,7 @@ struct TokenInfoPageViewModel {
private var yearLowViewModel: TickerFieldValueViewModel {
let value: String = {
let history = values[safe: ChartHistoryPeriod.year.index]
if let min = HistoryHelper(history: history).minMax?.min, let value = NumberFormatter.usd.string(from: min) {
if let min = HistoryHelper(history: history).minMax?.min, let value = Formatter.usd.string(from: min) {
return value
} else {
return "-"
@ -144,7 +144,7 @@ struct TokenInfoPageViewModel {
private var yearHighViewModel: TickerFieldValueViewModel {
let value: String = {
let history = values[safe: ChartHistoryPeriod.year.index]
if let max = HistoryHelper(history: history).minMax?.max, let value = NumberFormatter.usd.string(from: max) {
if let max = HistoryHelper(history: history).minMax?.max, let value = Formatter.usd.string(from: max) {
return value
} else {
return "-"
@ -184,13 +184,13 @@ struct TokenInfoPageViewModel {
switch result.change {
case .appreciate(let percentage, let value):
let p = NumberFormatter.percent.string(from: percentage) ?? "-"
let v = NumberFormatter.usd.string(from: value) ?? "-"
let p = Formatter.percent.string(from: percentage) ?? "-"
let v = Formatter.usd.string(from: value) ?? "-"
return ("\(v) (\(p)%)", Colors.appActionButtonGreen)
case .depreciate(let percentage, let value):
let p = NumberFormatter.percent.string(from: percentage) ?? "-"
let v = NumberFormatter.usd.string(from: value) ?? "-"
let p = Formatter.percent.string(from: percentage) ?? "-"
let v = Formatter.usd.string(from: value) ?? "-"
return ("\(v) (\(p)%)", Colors.appRed)
case .none:
@ -286,7 +286,7 @@ struct TokenInfoPageViewModel {
private var marketPriceValue: String? {
if let value = EthCurrencyHelper(ticker: ticker).marketPrice {
return NumberFormatter.usd.string(from: value)
return Formatter.usd.string(from: value)
} else {
return nil
}

@ -1,50 +0,0 @@
// Copyright SIX DAY LLC. All rights reserved.
@testable import AlphaWallet
import XCTest
class DecimalFormatterTest: XCTestCase {
let usDecimalFormatter = DecimalFormatter(locale: Locale(identifier: "en_US"))
let frDecimalFormatter = DecimalFormatter(locale: Locale(identifier: "fr_FR"))
func testDecimalPointInUS() {
XCTAssertEqual(usDecimalFormatter.number(from: "1000.25"), NSNumber(value: 1000.25))
XCTAssertEqual(usDecimalFormatter.number(from: ".25"), NSNumber(value: 0.25))
}
func testDecimalAndThousandsPointsInUS() {
XCTAssertEqual(usDecimalFormatter.number(from: "1,000.25"), NSNumber(value: 1000.25))
XCTAssertEqual(usDecimalFormatter.number(from: "1.000,25"), NSNumber(value: 1000.25))
XCTAssertEqual(usDecimalFormatter.number(from: "1'000,25"), NSNumber(value: 1000.25))
}
func testThousandsPointsInUS() {
XCTAssertEqual(usDecimalFormatter.number(from: ",25"), NSNumber(value: 25))
}
func testNumberToStingInUS() {
XCTAssertEqual(usDecimalFormatter.string(from: NSNumber(value: 1000.25)), "1,000.25")
XCTAssertEqual(usDecimalFormatter.string(from: NSNumber(value: 0.25)), "0.25")
}
func testInvalidStringInUS() {
XCTAssertEqual(usDecimalFormatter.number(from: "test"), nil)
}
func testDecimalPointInFr() {
XCTAssertEqual(frDecimalFormatter.number(from: "1 000,25"), NSNumber(value: 1000.25))
XCTAssertEqual(frDecimalFormatter.number(from: ".25"), NSNumber(value: 25))
}
func testDecimalAndThousandsPointsInFr() {
XCTAssertEqual(frDecimalFormatter.number(from: "1,000.25"), NSNumber(value: 1000.25))
XCTAssertEqual(frDecimalFormatter.number(from: "1.000,25"), NSNumber(value: 1000.25))
XCTAssertEqual(frDecimalFormatter.number(from: "1'000,25"), NSNumber(value: 1000.25))
}
func testThousandsPointsInFr() {
XCTAssertEqual(frDecimalFormatter.number(from: ",25"), NSNumber(value: 0.25))
}
func testNumberToStingInFr() {
//NOTE: There some cases when for different simulators it uses different characters for space like \u{202F} or \u{00A0}.
let value: String = "1"+frDecimalFormatter.groupingSeparator+"000,25"
XCTAssertEqual(frDecimalFormatter.string(from: NSNumber(value: 1000.25))!, value)
XCTAssertEqual(frDecimalFormatter.string(from: NSNumber(value: 0.25)), "0,25")
}
func testInvalidStringInFr() {
XCTAssertEqual(frDecimalFormatter.number(from: "test"), nil)
}
}

@ -0,0 +1,165 @@
//
// FormattersTests.swift
// AlphaWalletTests
//
// Created by Jerome Chan on 19/1/22.
//
@testable import AlphaWallet
import XCTest
class FormattersTestCase: XCTestCase {
func testCurrency() {
XCTAssertEqual(Formatter.currency.string(from: 0.0)!, "$0.00")
XCTAssertEqual(Formatter.currency.string(from: 10.100)!, "$10.10")
XCTAssertEqual(Formatter.currency.string(from: 100.105)!, "$100.10")
XCTAssertEqual(Formatter.currency.string(from: 1000.109)!, "$1,000.10")
XCTAssertEqual(Formatter.currency.string(from: 9999999999999.999)!, "$9,999,999,999,999.99")
XCTAssertEqual(Formatter.currency.string(from: -0.0)!, "-$0.00")
XCTAssertEqual(Formatter.currency.string(from: -10.100)!, "-$10.10")
XCTAssertEqual(Formatter.currency.string(from: -100.105)!, "-$100.10")
XCTAssertEqual(Formatter.currency.string(from: -1000.109)!, "-$1,000.10")
XCTAssertEqual(Formatter.currency.string(from: -9999999999999.999)!, "-$9,999,999,999,999.99")
// XCTAssertEqual(Formatters.currency.string(from: 123456789123456789.056), "$123,456,789,123,456,789.05")
}
func testUsd() {
XCTAssertEqual(Formatter.usd.string(from: 0.0)!, "0.00 USD")
XCTAssertEqual(Formatter.usd.string(from: 10.100)!, "10.10 USD")
XCTAssertEqual(Formatter.usd.string(from: 100.105)!, "100.10 USD")
XCTAssertEqual(Formatter.usd.string(from: 1000.109)!, "1,000.10 USD")
XCTAssertEqual(Formatter.usd.string(from: 9999999999999.999)!, "9,999,999,999,999.99 USD")
XCTAssertEqual(Formatter.usd.string(from: -0.0)!, "-0.00 USD")
XCTAssertEqual(Formatter.usd.string(from: -10.100)!, "-10.10 USD")
XCTAssertEqual(Formatter.usd.string(from: -100.105)!, "-100.10 USD")
XCTAssertEqual(Formatter.usd.string(from: -1000.109)!, "-1,000.10 USD")
XCTAssertEqual(Formatter.usd.string(from: -9999999999999.999)!, "-9,999,999,999,999.99 USD")
}
func testPercent() {
XCTAssertEqual(Formatter.percent.string(from: 0.0)!, "0.00")
XCTAssertEqual(Formatter.percent.string(from: 10.100)!, "10.10")
XCTAssertEqual(Formatter.percent.string(from: 100.105)!, "100.10")
XCTAssertEqual(Formatter.percent.string(from: 1000.109)!, "1,000.10")
XCTAssertEqual(Formatter.percent.string(from: 9999999999999.999)!, "9,999,999,999,999.99")
XCTAssertEqual(Formatter.percent.string(from: -0.0)!, "-0.00")
XCTAssertEqual(Formatter.percent.string(from: -10.100)!, "-10.10")
XCTAssertEqual(Formatter.percent.string(from: -100.105)!, "-100.10")
XCTAssertEqual(Formatter.percent.string(from: -1000.109)!, "-1,000.10")
XCTAssertEqual(Formatter.percent.string(from: -9999999999999.999)!, "-9,999,999,999,999.99")
}
func testShortCrypto() {
XCTAssertEqual(Formatter.shortCrypto.string(from: 0.0)!, "0.0000")
XCTAssertEqual(Formatter.shortCrypto.string(from: 10.100)!, "10.1000")
XCTAssertEqual(Formatter.shortCrypto.string(from: 100.105)!, "100.1050")
XCTAssertEqual(Formatter.shortCrypto.string(from: 1000.109)!, "1,000.1090")
XCTAssertEqual(Formatter.shortCrypto.string(from: 999999999999.999)!, "999,999,999,999.9990")
XCTAssertEqual(Formatter.shortCrypto.string(from: -0.0)!, "-0.0000")
XCTAssertEqual(Formatter.shortCrypto.string(from: -10.100)!, "-10.1000")
XCTAssertEqual(Formatter.shortCrypto.string(from: -100.105)!, "-100.1050")
XCTAssertEqual(Formatter.shortCrypto.string(from: -1000.109)!, "-1,000.1090")
XCTAssertEqual(Formatter.shortCrypto.string(from: -999999999999.999)!, "-999,999,999,999.9990")
}
func testPriceChange() {
XCTAssertEqual(Formatter.priceChange.string(from: 0.0)!, "+$0.00")
XCTAssertEqual(Formatter.priceChange.string(from: 10.100)!, "+$10.10")
XCTAssertEqual(Formatter.priceChange.string(from: 100.105)!, "+$100.10")
XCTAssertEqual(Formatter.priceChange.string(from: 1000.109)!, "+$1,000.10")
XCTAssertEqual(Formatter.priceChange.string(from: 9999999999999.999)!, "+$9,999,999,999,999.99")
XCTAssertEqual(Formatter.priceChange.string(from: -0.0)!, "-$0.00")
XCTAssertEqual(Formatter.priceChange.string(from: -10.100)!, "-$10.10")
XCTAssertEqual(Formatter.priceChange.string(from: -100.105)!, "-$100.10")
XCTAssertEqual(Formatter.priceChange.string(from: -1000.109)!, "-$1,000.10")
XCTAssertEqual(Formatter.priceChange.string(from: -9999999999999.999)!, "-$9,999,999,999,999.99")
}
func testFiat() {
XCTAssertEqual(Formatter.fiat.string(from: 0.0)!, "$0.00")
XCTAssertEqual(Formatter.fiat.string(from: 10.100)!, "$10.10")
XCTAssertEqual(Formatter.fiat.string(from: 100.105)!, "$100.10")
XCTAssertEqual(Formatter.fiat.string(from: 1000.109)!, "$1,000.10")
XCTAssertEqual(Formatter.fiat.string(from: 9999999999999.999)!, "$9,999,999,999,999.99")
XCTAssertEqual(Formatter.fiat.string(from: -0.0)!, "-$0.00")
XCTAssertEqual(Formatter.fiat.string(from: -10.100)!, "-$10.10")
XCTAssertEqual(Formatter.fiat.string(from: -100.105)!, "-$100.10")
XCTAssertEqual(Formatter.fiat.string(from: -1000.109)!, "-$1,000.10")
XCTAssertEqual(Formatter.fiat.string(from: -9999999999999.999)!, "-$9,999,999,999,999.99")
}
func testDefault() {
XCTAssertEqual(Formatter.default.string(from: 0.0)!, "0")
XCTAssertEqual(Formatter.default.string(from: 10.1)!, "10")
XCTAssertEqual(Formatter.default.string(from: 100.50)!, "100")
XCTAssertEqual(Formatter.default.string(from: 100.51)!, "101")
XCTAssertEqual(Formatter.default.string(from: 1000.9)!, "1001")
XCTAssertEqual(Formatter.default.string(from: 9999999999999.999)!, "10000000000000")
XCTAssertEqual(Formatter.default.string(from: -0.0)!, "-0")
XCTAssertEqual(Formatter.default.string(from: -10.1)!, "-10")
XCTAssertEqual(Formatter.default.string(from: -100.50)!, "-100")
XCTAssertEqual(Formatter.default.string(from: -100.51)!, "-101")
XCTAssertEqual(Formatter.default.string(from: -1000.9)!, "-1001")
XCTAssertEqual(Formatter.default.string(from: -9999999999999.999)!, "-10000000000000")
}
func testStringCurrency() {
XCTAssertEqual(Formatter.currencyAccounting.string(from: 0.0)!, "0.00")
XCTAssertEqual(Formatter.currencyAccounting.string(from: 0.500)!, "0.50")
XCTAssertEqual(Formatter.currencyAccounting.string(from: 0.505)!, "0.50")
XCTAssertEqual(Formatter.currencyAccounting.string(from: 0.509)!, "0.50")
XCTAssertEqual(Formatter.currencyAccounting.string(from: 1000.50)!, "1,000.50")
XCTAssertEqual(Formatter.currencyAccounting.string(from: 9999999999999.999)!, "9,999,999,999,999.99")
XCTAssertEqual(Formatter.currencyAccounting.string(from: -0.0)!, "(0.00)")
XCTAssertEqual(Formatter.currencyAccounting.string(from: -0.500)!, "(0.50)")
XCTAssertEqual(Formatter.currencyAccounting.string(from: -0.505)!, "(0.50)")
XCTAssertEqual(Formatter.currencyAccounting.string(from: -0.509)!, "(0.50)")
XCTAssertEqual(Formatter.currencyAccounting.string(from: -1000.50)!, "(1,000.50)")
XCTAssertEqual(Formatter.currencyAccounting.string(from: -9999999999999.999)!, "(9,999,999,999,999.99)")
}
func testAlternateAmount() {
XCTAssertEqual(Formatter.alternateAmount.string(from: 0.0)!, "0.0000")
XCTAssertEqual(Formatter.alternateAmount.string(from: 0.5)!, "0.5000")
XCTAssertEqual(Formatter.alternateAmount.string(from: 0.05)!, "0.0500")
XCTAssertEqual(Formatter.alternateAmount.string(from: 0.005)!, "0.0050")
XCTAssertEqual(Formatter.alternateAmount.string(from: 0.0005)!, "0.0005")
XCTAssertEqual(Formatter.alternateAmount.string(from: 0.00005)!, "0.0000")
XCTAssertEqual(Formatter.alternateAmount.string(from: 12341234.12345)!, "12,341,234.1234")
XCTAssertEqual(Formatter.alternateAmount.string(from: -0.0)!, "-0.0000")
XCTAssertEqual(Formatter.alternateAmount.string(from: -0.5)!, "-0.5000")
XCTAssertEqual(Formatter.alternateAmount.string(from: -0.05)!, "-0.0500")
XCTAssertEqual(Formatter.alternateAmount.string(from: -0.005)!, "-0.0050")
XCTAssertEqual(Formatter.alternateAmount.string(from: -0.0005)!, "-0.0005")
XCTAssertEqual(Formatter.alternateAmount.string(from: -0.00005)!, "-0.0000")
XCTAssertEqual(Formatter.alternateAmount.string(from: -12341234.12345)!, "-12,341,234.1234")
}
func testScientificAmount() {
XCTAssertEqual(Formatter.scientificAmount.string(from: 0.0)!, "0")
XCTAssertEqual(Formatter.scientificAmount.string(from: 0 as NSNumber)!, "0")
XCTAssertEqual(Formatter.scientificAmount.string(from: 1.0)!, "1")
XCTAssertEqual(Formatter.scientificAmount.string(from: 10.0)!, "10")
XCTAssertEqual(Formatter.scientificAmount.string(from: 100.0)!, "100")
XCTAssertEqual(Formatter.scientificAmount.string(from: 1000.0)!, "1000")
XCTAssertEqual(Formatter.scientificAmount.string(from: 12345.0)!, "12345")
XCTAssertEqual(Formatter.scientificAmount.string(from: 12345.49)!, "12345.49")
XCTAssertEqual(Formatter.scientificAmount.string(from: 12345.50)!, "12345.5")
XCTAssertEqual(Formatter.scientificAmount.string(from: 12345.51)!, "12345.51")
XCTAssertEqual(Formatter.scientificAmount.string(from: -0.0)!, "-0")
XCTAssertEqual(Formatter.scientificAmount.string(from: -0 as NSNumber)!, "0")
XCTAssertEqual(Formatter.scientificAmount.string(from: -1.0)!, "-1")
XCTAssertEqual(Formatter.scientificAmount.string(from: -10.0)!, "-10")
XCTAssertEqual(Formatter.scientificAmount.string(from: -100.0)!, "-100")
XCTAssertEqual(Formatter.scientificAmount.string(from: -1000.0)!, "-1000")
XCTAssertEqual(Formatter.scientificAmount.string(from: -12345.0)!, "-12345")
XCTAssertEqual(Formatter.scientificAmount.string(from: -12345.49)!, "-12345.49")
XCTAssertEqual(Formatter.scientificAmount.string(from: -12345.50)!, "-12345.5")
XCTAssertEqual(Formatter.scientificAmount.string(from: -12345.51)!, "-12345.51")
XCTAssertEqual(Formatter.scientificAmount.number(from: "1.25E+12")!, 1.25E12)
XCTAssertEqual(Formatter.scientificAmount.number(from: "-1.25E+12")!, -1.25E12)
XCTAssertEqual(Formatter.scientificAmount.number(from: "1.25E-12")!, 1.25E-12)
XCTAssertEqual(Formatter.scientificAmount.number(from: "-1.25E-12")!, -1.25E-12)
}
}
Loading…
Cancel
Save