#货币 #货币 #金额 #算术运算 #十进制 #货币 #转换

oxydized-money

提供用于操作特定货币的金额以及在这些金额之间进行转换的数据类型的库

3 个版本 (重大更新)

0.3.0 2024 年 3 月 10 日
0.2.0 2024 年 3 月 3 日
0.1.0 2024 年 3 月 3 日

金融 中排名 #228

Download history 47/week @ 2024-04-02

每月下载量 107

MIT 许可证

43KB
844

氧化货币 💵 ↔ 💶

Build Test Clippy Doc

Crates.io Docs.rs Crates.io Crates.io

本软件包旨在提供用于操作特定货币的金额、在不同货币之间转换金额并确保任何计算都在同一货币的金额上执行的数据类型。

动机

引入此软件包是因为所有现有的已知替代品都有一些显著的缺点

  • 使用原生的浮点类型如 f32f64 由于其缺乏精度而存在问题。
  • 使用 rust_decimal::Decimal 解决了这个问题,但无法防止在不同货币中添加金额。
  • 使用 rusty_money::Money,虽然稍微好一些,但并没有真正解决转换问题,因为对不同货币的金额执行算术运算会导致恐慌。

Rust 致力于正确的错误处理,所有这些选项都感觉像是一种妥协。本软件包旨在通过提供三种不同的数据类型来改进这一点

  • Amount 用于存储给定货币的金额。
  • CurrencyError 用于表示在 Amount 上执行算术操作期间出现的任何错误(货币不匹配等)。
  • AmountResult 用于存储算术运算的结果(一个 AmountCurrencyError)。

算术运算被定义为这三种类型几乎无缝地交互。然而,在进行运算时,输出类型总是反映了是否可能发生错误。不会失败的运算将输出Amount,而可能失败的运算将输出AmountResult。在获取底层Amount之前,需要适当检查AmountResult是否存在错误。

不再有🦶-枪

示例

use oxydized_money_macros::{eur, usd, dec};
use oxydized_money::{
    Currency::{EUR,USD},
    CurrencyError,
    Decimal,
};

// Amount(USD)
let capital = usd!(10_000);

// Decinal
let exchange_rate = dec!(0.928);

// Amount(EUR)
let converted = capital.converted_to(EUR, exchange_rate);

// Amount(EUR)
let fees = eur!(15.2);

// Amount(EUR) + Amount(EUR) => AmountResult(EUR)
let subtotal = converted + fees;

// Amount(EUR) * Decimal => Amount(EUR)
let extras = eur!(50) * dec!(2);

// AmountResult(EUR) + Amount(EUR) => AmountResult(EUR)
let total = subtotal + extras;

// Comparing AmountResult with Amounts
assert_eq!(total, eur!(9_395.200));
#
// AmountResult(EUR) + Amount(USD) => AmountResult(Mismatch(EUR,USD))
let oops = total + usd!(20);

// Comparing AmountResult with CurrencyError
assert_eq!(oops, CurrencyError::Mismatch(EUR,USD));

// AmountResult(Mismatch(EUR,USD)) + Amount(USD) => AmountResult(Mismatch(EUR,USD))
let oh_my = oops + usd!(200);
assert_eq!(oh_my, CurrencyError::Mismatch(EUR,USD));

// "Everything, everywhere, all at once."
assert_eq!(
    usd!(10_000).converted_to(EUR, dec!(0.928)) + eur!(15.2) + eur!(50)*dec!(2),
    eur!(9_395.200)
);

支持的运算

二元运算

Amount

左操作数 运算符 右操作数 输出
Amount * 十进制 Amount
Amount / 十进制 AmountResult
Amount {+,-} Amount AmountResult
Amount {+,-} AmountResult AmountResult
Amount {==,!=} Amount 布尔型
Amount {==,!=} AmountResult 布尔型
Amount {<,>,>=,<= } Amount 布尔型

AmountResult

左操作数 运算符 右操作数 输出
AmountResult * 十进制 AmountResult
AmountResult / 十进制 AmountResult
AmountResult {+,-} Amount AmountResult
AmountResult {+,-} AmountResult AmountResult
AmountResult {==,!=} Amount 布尔型
AmountResult {==,!=} AmountResult 布尔型
AmountResult {==,!=} CurrencyError 布尔型

CurrencyError

左操作数 运算符 右操作数 输出
CurrencyError {==,!=} AmountResult 布尔型
CurrencyError {==,!=} CurrencyError 布尔型

一元运算

Amount

运算符 操作数 输出
- Amount Amount

AmountResult

运算符 操作数 输出
- AmountResult AmountResult

依赖项

~0.7–1MB
~22K SLoC