A Swift package providing type-safe monetary value representation with currency support.
swift-money provides type-safe abstractions for working with monetary values in Swift. The package uses Swift's type system to prevent common errors in financial calculations, such as mixing incompatible currencies or losing precision with floating-point arithmetic. All monetary values use Decimal for precision-safe calculations.
- Type-safe monetary value representation using
Moneyenum - Decimal-based arithmetic preventing floating-point precision loss
- Euro currency support with cash and physical denomination tracking
- Arithmetic operations: addition, subtraction, multiplication, division
- Percentage-based calculations via swift-percent integration
- Localized formatting with swift-translating
- Physical currency representation (notes and coins)
- Comparable and Hashable conformance
- Codable support for serialization
Add swift-money to your Swift package dependencies:
dependencies: [
.package(url: "https://github.com/coenttb/swift-money.git", from: "0.1.0")
]Then add the product to your target:
targets: [
.target(
name: "YourTarget",
dependencies: [
.product(name: "Money", package: "swift-money")
]
)
]import Money
// Create monetary values
let price: Money = .euro(Euro(50.00))
let discount: Money = .euro(Euro(10.00))
// Perform calculations
let total = price - discount // Money.euro(Euro(40.00))
// Use convenience syntax
let amount = €(25.50) // Money.euro(Euro(25.50))
// Extension syntax
let payment = 100.euro // Money.euro(Euro(100.00))import Money
// Create money values
let a: Money = .euro(Euro(100))
let b: Money = .euro(Euro(50))
// Addition
let sum = a + b // €150.00
// Subtraction
let difference = a - b // €50.00
// Multiplication
let doubled = a * 2 // €200.00import Money
import Percent
let price: Money = .euro(Euro(100))
let taxRate = Percentage(fraction: 0.21) // 21%
let tax = price * taxRate // €21.00
let totalPrice = price + tax // €121.00import Money
let total: Money = .euro(Euro(100))
let perPerson = total / 4.0 // €25.00
// Division by Decimal
let result = total / Decimal(3) // €33.33 (rounded)import Money
// Using euro operator
let price = €(99.99)
// Using extension syntax
let amount = 50.euro
let cost = 75.50.euro
// Direct initialization
let value: Money = .euro(Euro.cash(Decimal(123.45)))import Money
// Represent physical notes and coins
let physical: Euro = .chartered(
notes: [.fifty, .twenty, .ten],
coins: [.euro(.two), .euro(.one), .cent(.fifty)]
)
// Value is calculated from all denominations
physical.value // Decimal: 83.50import Money
import Translating
let amount: Money = .euro(Euro(1234.56))
// Basic formatting
let formatted = amount.description(include_words: false)
// Returns: "€ 1,234.56"
// With written words
let withWords = amount.description(include_words: true)
// Returns localized string like: "one thousand two hundred thirty-four euros (€ 1,234.56)"import Money
let a: Money = .euro(Euro(100))
let b: Money = .euro(Euro(50))
if a > b {
print("a is greater")
}
// Direct Euro comparison
let euro1 = Euro(100)
let euro2 = Euro(50)
euro1 < euro2 // falseimport Money
import Foundation
let price: Money = .euro(Euro(99.99))
// Encode to JSON
let encoder = JSONEncoder()
let data = try encoder.encode(price)
// Decode from JSON
let decoder = JSONDecoder()
let decoded = try decoder.decode(Money.self, from: data)The main type for representing monetary values:
public enum Money: Hashable, Comparable, Codable, SignedNumeric {
case euro(Euro)
}Properties:
value: Decimal- The numeric valueamount: Decimal- Alias for value
Methods:
description(include_words: Bool) -> Translated<String>- Formatted description
Operators:
+, -, *- Standard arithmetic operations/, /=- Division operations<, >, <=, >=, ==- Comparison operations
Currency-specific type for euros:
public enum Euro: MoneyType, Hashable, Comparable, Codable {
case cash(Decimal)
case chartered(notes: [Note], coins: [Coin])
}Properties:
value: Decimal- The numeric valuesymbol: String- Currency symbol ("EUR")name: String- Currency name ("euro")abbreviation: String- Currency abbreviation ("EUR")
Physical Denominations:
Note- Ten, twenty, fifty, hundred, twohundred, fivehundredCoin.Cent- One, two, five, ten, twenty, fifty centsCoin.Euro- One, two euro coins
Protocol for currency types:
public protocol MoneyType {
static var symbol: String { get }
static var name: String { get }
static var abbreviation: String { get }
var value: Decimal { get }
var money: Money { get }
}// Euro operator
public func €(_ value: Decimal) -> Money
// Integer extensions
extension Int {
var euro: Money { get }
}
// Double extensions
extension Double {
var euro: Money { get }
}
// Division operations
public func /(_ money: Money, _ decimal: Decimal) -> Money
public func /(_ money: Money, _ double: Double) -> Money
// MoneyType operations
public func +(_ t1: MoneyType, _ t2: MoneyType) -> MoneyType
public func >=(_ t1: MoneyType, _ t2: MoneyType) -> Bool- swift-percent: A Swift package with foundational types for percentages.
- swift-translating: A Swift package for inline translations.
- swift-bunq: A Swift package for the Bunq banking API.
- swift-document-templates: A Swift package for data-driven business document creation.
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Contributions are welcome. Please open an issue or submit a pull request.