Skip to content

coenttb/swift-money

swift-money

CI Development Status

A Swift package providing type-safe monetary value representation with currency support.

Overview

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.

Features

  • Type-safe monetary value representation using Money enum
  • 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

Installation

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")
    ]
  )
]

Quick Start

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))

Usage Examples

Basic Operations

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.00

Working with Percentages

import 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.00

Division Operations

import 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)

Convenience Initializers

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)))

Physical Currency Representation

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.50

Formatting and Localization

import 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)"

Comparison Operations

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  // false

Codable Support

import 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)

API Reference

Money

The main type for representing monetary values:

public enum Money: Hashable, Comparable, Codable, SignedNumeric {
    case euro(Euro)
}

Properties:

  • value: Decimal - The numeric value
  • amount: Decimal - Alias for value

Methods:

  • description(include_words: Bool) -> Translated<String> - Formatted description

Operators:

  • +, -, * - Standard arithmetic operations
  • /, /= - Division operations
  • <, >, <=, >=, == - Comparison operations

Euro

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 value
  • symbol: String - Currency symbol ("EUR")
  • name: String - Currency name ("euro")
  • abbreviation: String - Currency abbreviation ("EUR")

Physical Denominations:

  • Note - Ten, twenty, fifty, hundred, twohundred, fivehundred
  • Coin.Cent - One, two, five, ten, twenty, fifty cents
  • Coin.Euro - One, two euro coins

MoneyType Protocol

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 }
}

Convenience Functions

// 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

Related Packages

Dependencies

Used By

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Contributing

Contributions are welcome. Please open an issue or submit a pull request.

About

A Swift package with foundational types for currency and monetary calculations.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Packages

 
 
 

Contributors

Languages