Git Product home page Git Product logo

rusty_money's People

Contributors

affanshahid avatar agentydragon avatar andreastedile avatar brokenthorn avatar diegooliveira avatar firelightflagboy avatar horgix avatar javednissar avatar kn0wmad avatar oti-dev avatar paupino avatar saebs avatar sjoerdsimons avatar takenoko-gohan avatar varunsrin avatar zacharra avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

rusty_money's Issues

Format Money with exactly n minor digits

Currently, Formatter::money does not include trailing zeros even if this results in less than params.rounding minor digits. Is this intentional? If it is, I would appreciate an option to format a Money instance with exactly n minor digits (instead of up to n).

`Money::from_str` cannot parse numbers greater than `i32::MAX`

Money::from_str only allows values that fit in a 32 bit integer to be parsed, while other methods allow for at least 64 bit integers.

assert_eq!(
	Money::from_major(i64::MAX, iso::EUR)
		.amount()
		.to_i64()
		.unwrap(),
	i64::MAX
);
assert!(Money::from_str(&i32::MAX.to_string(), iso::EUR).is_ok());
assert!(Money::from_str(&(i32::MAX as i64 + 1).to_string(), iso::EUR).is_err()); // the problem

Add FromStr impl for &'static Currency

Would be handy to have this FromStr impl. Usually have data from a database with currency strings and need them parsed into a Currency type.

ex:

let currency: &Currency = "USD".parse().unwrap()

See PR #68

`Money::from_str` returns `Err(InvalidAmount)` for typical cryptocurrency value

use rusty_money::{crypto, Money};

fn main() {
    let text = "1.11111111111";
    dbg!(Money::from_decimal(text.parse().unwrap(), crypto::ETH));
    dbg!(Money::from_str(text, crypto::ETH));
}
[src/main.rs:5] Money::from_decimal(text.parse().unwrap(), crypto::ETH) = Money {
    amount: 1.11111111111,
    currency: Currency {
        code: "ETH",
        exponent: 18,
        locale: EnUs,
        minor_units: 1000000000000000000,
        name: "Ethereum",
        symbol: "ETH",
        symbol_first: false,
    },
}
[src/main.rs:6] Money::from_str(text, crypto::ETH) = Err(
    InvalidAmount,
)

`Currency::minor_units` can be removed

(Taking into account that Currency is Copy, so we put all its fields on stack) Currency::minor_units seems to be redundant, because it can be computed from something like dec!(10).powd(-Currency::exponent)

Documentation: Examples

Write more thorough documentation and example code for:

  • Formatter
  • Rounding
  • Locale / LocalFormat
  • Allocation

Monetary amounts should not keep excess precision

When handling monetary amounts, the precision should be that of the minor unit instead of mathematical correct fractions. Current implementation seems to maintain the mathematical fraction

let amount: Money<Currency> = Money::from_major(100, iso::EUR) / 3;
assert_eq!(amount.to_string(), "€33,33");   // that is what I expect

let triple_amount: Money<Currency> = amount * 3;
assert_eq!(triple_amount.to_string(), "€99,99");    // assert fail because expected is "€100,00", but 3 x  €33,33 = €99,99

When parsing Euro amounts, amounts that should be valid throw an error

Here is a test case that will fail (and shouldn't, unless I am missing something):

#[test]
fn test_rusty_money() {
	let eur = Money::from_str("2.00", iso::EUR).unwrap();

}

Euro's are divided into 100 cents (much like the GBP and the USD), and yet the parser is treating an amount like "2.00" or "2.50" as invalid. If I change that line to have 3 digits after the decimal, it magically works, even though "2.00" and "2.000" are the same number. Seems like bug, but perhaps I am missing something.

Why Currency as ref?

Hi, just wondering why the Currency is passed as a ref and not as owned? It makes getting started in fast manner pretty hard as pollution with lifetimes is hugely annoying in nested and complex data structures.

Missed currencies

Greetings to all,

Need to cover other currencies, which is not covered yet. For example I tried with Egyptian Pound but it pancis.
Library should return a clear error message that this currency is not supported yet.

Support for serde Serialize / Deserialize

I am using this library to represent Money in the backend of a web-app. Sometimes I need to serialise and need to translate into another struct for that. Could we add a feature to (de-)serialise via Serde?

Alternatively perhaps we could make Iso Copy/Clone to make it easier to pass around and embed in other structs.

Request: make it possible to save writing `<T: FormattableCurrency>`, and store multiple currencies in one place

Current implementation requires something like this:

use {
	std::collections::HashMap,
	rusty_money::{Money, FormattableCurrency, iso, crypto},
};

#[derive(Debug)]
struct PriceList<'pl, T: FormattableCurrency> {
	pub prices: HashMap<String, Money<'pl, T>>,
}

impl<'pl, T: FormattableCurrency> PriceList<'pl, T> {
    fn new() -> Self {
        Self{ prices: HashMap::new() }
    }

    fn set_price<S: Into<String>>(&mut self, thing: S, price: Money<'pl, T>) {
        self.prices.insert(thing.into(), price);
    }

    fn get_price(&self, name: &str) -> Option<&Money<T>> {
    	self.prices.get(name)
    }
}

fn main() {
	let mut pl = PriceList::new();
	pl.set_price("one", Money::from_major(1, iso::CNY));
	pl.set_price("two", Money::from_major(1, iso::USD));
	pl.set_price("coin", Money::from_str("0.01", crypto::BTC).unwrap());
	// expected struct `rusty_money::iso::Currency`, found struct `rusty_money::crypto::Currency`
	dbg!(&pl);
	dbg!(pl.get_price("one"));
}
  1. It seems somewhat cumbersome.
  2. We can't store prices of both the ISO currencies and cryptos in one list.

Make currency hashable

Adding a simple #[derive(Hash)] will make the currencies hashable, so we can use then in a hashmap

Change exchange.get_rate to use &self instead of self

In it's current form, Exchange.get_rate consumes the exchange on every use which makes it hard to re-use an Exchange throughout a particular section of code. It would be ideal, if exchange.get_rate would borrow itself rather than consume itself when used.

An alternative fix would be to derive the Clone trait for the Exchange struct but I imagine that one would introduce more overhead on use.

`Display` impl writes "-$0.00" when precision is higher than two decimal places

use rusty_money::{iso, Money};

fn main() {
    let money = Money::from_str("-0.005", iso::USD).unwrap();
    assert_eq!(format!("{money}"), "$0.00");
}

Fails with:

thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `"-$0.00"`,
 right: `"$0.00"`', src\main.rs:5:5

The Display impl should never print "negative zero dollars".

`allocate()` allocate remainder incorrectly

If the total to be allocated cannot be divided fully, it will add remainder to each ratio which in order.

For example, we need to divide $613 to participants with $98, $92, $98, $123, $102, $92. It will be:

98 => 100
92 => 94
98 => 99
123 => 124
102 => 103
92 => 93

but if we change the order of ratios to $123, $102, $98, $98, $92, $92:

123 => 125
102 => 104
98 =>99
98 =>99
92 => 93
92 => 93

This behaviour is not fair. The remainder should be allocated by ratio size, not order.

Request: NaiveMoney

It would be a useful abstraction to allow an unknown-currency NaiveMoney type that works as follows:

let money: NaiveMoney = NaiveMoney::from_minor(10);
let money: Money<USD> = money.with_currency(&USD);
  • NaiveMoney can only be constructed and converted to a Money<C>

In the abstract, this would be for any data structure that needs to store N monetary values where the currency type is determined dynamically from some other source.

As a concrete use case, I'd like to use this to represent MONEY from Postgres in SQLx.

Thoughts?

Make Money implement Copy

Money has two fields, a rust_decimal::Decimal instance and a reference. Both implement Copy, so Money should be able to derive Copy. The Copy documentation recommends that ‘[g]enerally speaking, if your type can implement Copy, it should.’ What do you think about making Money implement Copy? This would make calculations much less awkward.

Make Currency Ord

Similar to #74, it's currently not possible to add Currency to BTreeSet / BTreeMap.

to_string() returns different values according to the fact that we use from_minor or from_major

Hi, Thanks for this great library. Amazing job.
I'm having trouble to print numbers. It'm getting different display depending on the constructor I used. Not sure it is intended...

 #[test]
    fn test_to_string_formatter() {
        let sut = rusty_money::Money::from_minor(10000, rusty_money::iso::EUR);
        let actual = format!("{}", sut);
        assert_eq!("€100,00", actual)
    } // pass

    #[test]
    fn test_to_string_formatter_from_major() {
        let sut = rusty_money::Money::from_major(100, rusty_money::iso::EUR);
        //let sut = Money::from_major(100);
        let actual = format!("{}", sut);
        assert_eq!("€100,00", actual)
    } //fails with   left: "€100.00". right: "€100"

Any idea how to prevent this?

Benchmarks for Performance

  • Add benchmarks to track performance of common operations like find, from_str, round and mathematical operations.
  • Integrate them into CI to prevent perf regressions when making changes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.