Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Currency in Swift

I am trying to create a function in Swift that accepts an integer as a param and returns a double in the locale currency e.g:

input : 1250

output : £12.50

input: 12500

output: £125.00

I noticed there is a third party library that supports this but unfortunately the repo is archived. The type of units used is the smallest type of currency which is minorUnits.

Network Call

/// GET - Retrive a feed of transactions during a certain period
static func get(accountUID: String, categoryUID: String, queryStartDate: String, queryEndDate: String , completionHandler: @escaping ([FeedItem], Error?) -> Void) {
    let sessionObject : URLSession = URLSession.shared
    let taskObject = sessionObject.dataTask(with: URLS().feedURLObject(accountUID,categoryUID,queryStartDate,queryEndDate)) { (Data, Response, Error) in
        guard Error == nil else {
            return
        }
        guard let Data = Data else {
            return
        }
        do {
            let feed = try JSONDecoder().decode(Feed.self, from: Data).feedItems.filter({ (item) -> Bool in
                item.direction == Direction.out
            })
            completionHandler(feed, nil)
        } catch let error  {
            print(error.localizedDescription)
        }
    }
    taskObject.resume()
}

Model Feed Struct Amount

struct Amount: Codable {
let currency: Currency
let minorUnits: Int}

Single Item JSON response

FeedItem(feedItemUid: "0651afe9-f568-4623-ad26-31974e26015c", categoryUid: "a68f9445-4d59-44e5-9c3f-dce2df0f53d2", amount: Banking_App.Amount(currency: Banking_App.Currency.gbp, minorUnits: 551), sourceAmount: Banking_App.Amount(currency: Banking_App.Currency.gbp, minorUnits: 551), direction: Banking_App.Direction.out, updatedAt: "2020-02-04T14:09:49.072Z", transactionTime: "2020-02-04T14:09:48.743Z", settlementTime: "2020-02-04T14:09:48.992Z", source: Banking_App.Source.fasterPaymentsOut, status: Banking_App.Status.settled, counterPartyType: Banking_App.CounterPartyType.payee, counterPartyUid: Optional("fed4d40b-9ccc-411d-81c7-870164876d04"), counterPartyName: Banking_App.CounterPartyName.mickeyMouse, counterPartySubEntityUid: Optional("d6d444c0-942f-4f85-b076-d30c2f745a6f"), counterPartySubEntityName: Banking_App.CounterPartySubEntityName.ukAccount, counterPartySubEntityIdentifier: "204514", counterPartySubEntitySubIdentifier: "00000825", reference: Banking_App.Reference.externalPayment, country: Banking_App.Country.gb, spendingCategory: Banking_App.SpendingCategory.payments)

Thanks

like image 602
Furqan Agwan Avatar asked Oct 19 '25 07:10

Furqan Agwan


1 Answers

Currency codes are defined in the standard ISO 4217 and as part of the standard is the number of decimal digits used for each currency and since swift's NumberFormatter has a style for this ISO standard we can use it for this case.

Create an instance and set the style

let currencyFormatter = NumberFormatter()
currencyFormatter.numberStyle = .currencyISOCode

Set the currency code

currencyFormatter.currencyCode = "SEK"

Now currencyFormatter.minimumFractionDigit and currencyFormatter.maximumFractionDigits will both contain the number of decimals define for the given currency

So now we can put this together in a function for instance

func convertMinorUnits(_ units: Int, currencyCode: String) -> Decimal {
    let currencyFormatter = NumberFormatter()
    currencyFormatter.numberStyle = .currencyISOCode
    currencyFormatter.currencyCode = currencyCode.uppercased()

    return Decimal(units) / pow(10, currencyFormatter.minimumFractionDigits)
}

example

print(convertMinorUnits(551, currencyCode: "GBP")

5.51

like image 115
Joakim Danielson Avatar answered Oct 20 '25 21:10

Joakim Danielson