Skip to content

Instantly share code, notes, and snippets.

@wildthink
Last active December 11, 2017 15:48
Show Gist options
  • Save wildthink/e0fd6c371dea54af7bd117e627be1df7 to your computer and use it in GitHub Desktop.
Save wildthink/e0fd6c371dea54af7bd117e627be1df7 to your computer and use it in GitHub Desktop.
import Foundation
protocol Currency {
static var code: String { get }
static var factor: NSDecimalNumber { get }
}
enum GBP: Currency {
static let code = "GBP"
static let factor: NSDecimalNumber = 1.44
}
enum EUR: Currency {
static let code = "EUR"
static let factor: NSDecimalNumber = 1.13
}
enum USD: Currency {
static let code = "USD"
static let factor: NSDecimalNumber = 1.0
}
struct Money<Cur: Currency>: CustomStringConvertible, FloatLiteralConvertible, IntegerLiteralConvertible {
let amount: NSDecimalNumber
var description: String {
let f = NSNumberFormatter()
f.numberStyle = .CurrencyStyle
f.currencyCode = Cur.code
return f.stringFromNumber(self.amount)!
}
init(floatLiteral value: Double) { self.amount = NSDecimalNumber(double: value) }
init(integerLiteral value: Int) { self.amount = NSDecimalNumber(integer: value) }
init(_ amount: NSDecimalNumber) { self.amount = amount }
func convertTo<C: Currency>() -> Money<C> {
let baseAmount = amount.decimalNumberByMultiplyingBy(Cur.factor)
let convertedAmount = baseAmount.decimalNumberByDividingBy(C.factor)
return Money<C>(convertedAmount)
}
}
extension Money {
var gbp: Money<GBP> { return convertTo() }
var eur: Money<EUR> { return convertTo() }
var usd: Money<USD> { return convertTo() }
}
let fivePound: Money<GBP> = 5 // £5
let threeEuro: Money<EUR> = 3 // €3
print(fivePound.eur) // €6.35
print(threeEuro.gbp) // £2.37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment