[{"data":1,"prerenderedAt":868},["ShallowReactive",2],{"project-41776878":3},{"id":4,"name":5,"line":6,"line_source":7,"title":8,"url":9,"domain":10,"maker":11,"posted_at":12,"year":13,"points":14,"comments":15,"rank_in_year":16,"shown_in_year":17,"top":18,"tier":19,"category":20,"subcategory":21,"format":22,"keywords":23,"reception":29,"sentiment":30,"stance_mix":31,"scored_comments":36,"aspects":37,"strip":47,"post_text":50,"what":51,"said":77,"maker_in_thread":197,"shape":208,"grid":213,"attempts":831,"same_week":832,"maker_shows":34,"maker_hidden":860,"reader_version":861,"card":862},"41776878","Kotlin Money","Manipulating monetary amounts is a common computing chore.","post","Show HN: Kotlin Money","https:\u002F\u002Fblog.eriksen.com.br\u002Fen\u002Fintroducing-kotlin-money","blog.eriksen.com.br","eriksencosta",1728392392,2024,427,228,99,3515,3,"legend","languages","money library","library",[24,25,26,27,28],"kotlin","money","currency","bigdecimal","rounding","curious",-0.141,{"positive":32,"neutral":33,"mixed":34,"critical":35},8,43,1,22,74,{"design":38,"idea":40,"execution":43,"pricing":45,"docs":46},{"positive":18,"critical":39},15,{"positive":41,"critical":42},2,7,{"positive":41,"critical":44},0,{"positive":44,"critical":44},{"positive":44,"critical":44},[48,44,44,34,34,34,44,44,18,48,18,18,18,44,44,18,41,49,18,18,34,18,18,34,41,34,18,18,48,18,18,34,18,44,44,34,44,44,44,34],5,4,"Manipulating monetary amounts is a common computing chore. However, no mainstream language has a first-class data type for representing money, it’s up to programmers to code abstractions for it. This isn’t an issue per se until dealing with rounding issues from operations like installment payments (e.g., buy now, pay later), foreign exchange, or even simple things like fee processing and tax collection.\n\nInspired by my days at N26 Brasil dealing with these challenges, I introduce Money: a Kotlin library that makes monetary calculations and allocations easy.",{"problem":52,"audience":57,"pricing":57,"motivation":58,"time_to_build":57,"stack":62,"openness":75,"stage":76,"team_size":76},{"value":53,"source":54,"evidence":55},"Monetary calculations, rounding and allocations are error-prone without a dedicated type.","maker",[56],{"id":7},null,{"value":59,"source":54,"evidence":60},"Inspired by challenges at N26 Brasil dealing with monetary rounding issues.",[61],{"id":7},[63,69],{"value":64,"source":54,"evidence":65},"BigDecimal",[66],{"id":67,"by":11,"text":68},"41777198","It uses BigDecimal. My first goal with the library was to provide a well-designed API. So to keep it simple for myself, I relied on BigDecimal for the calculations.",{"value":70,"source":54,"evidence":71},"ICU\u002FCLDR currency data",[72],{"id":73,"by":11,"text":74},"41780421","I'll introduce l10n support in a future release. My starting point was to make currency names and symbols unaware of the locale as I embedded cryptocurrency data in the mix.…","open_source","unknown",{"praise":78,"objections":98,"requests":135,"questions":161,"alternatives":176},[79,91],{"value":80,"source":81,"evidence":82},"Useful API and good ergonomics compared to alternatives","commenter",[83,87],{"id":84,"by":85,"text":86},"41777190","Ygg2","Nice library! Manipulating money is probably trickiest thing since time was invented. Library looks very usable. I have to ask though: > val transactionFee = 1.25.percent() \u002F\u002F…",{"id":88,"by":89,"text":90},"41778702","donjigweed","Nice. Looks like it satisfies all the requirements detailed here [0]. Also, good discussion of the major difficulty dealing with money here [1]. [0]…",{"value":92,"source":81,"evidence":93},"Allocation feature is useful for splitting amounts",[94],{"id":95,"by":96,"text":97},"41783613","monkaiju","I just had to implement the 'allocate' functionality described here, specifically with the %-based weights, and it was a pain that required careful comments to ensure was clear!…",[99,114,120],{"value":100,"source":81,"evidence":101},"Too much infix notation makes the API hard to read",[102,106,110],{"id":103,"by":104,"text":105},"41777794","Exerosis","My only complaint is that there seems to be too much infix. Why not just do 50.btc, 25.3.usd This would keep it inline with the time API doing 20.seconds Also percentages could…",{"id":107,"by":108,"text":109},"41779951","wiseowise","Infix functions is one of the worst features of Kotlin.",{"id":111,"by":112,"text":113},"41778815","textlapse","Kotlin has the problem of \"I had N problems, so I think I can create 1 new solution, now I have N+1 problems\" (obligatory https:\u002F\u002Fxkcd.com\u002F927\u002F). The 'money\u002Fpercent\u002Fusd' are…",{"value":115,"source":54,"evidence":116},"No support for cash rounding rules yet",[117],{"id":118,"by":11,"text":119},"41777318","This is something I am aware but there is no support for this rounding scheme at the moment.",{"value":121,"source":81,"evidence":122},"Prior art exists in Java Money, F# units of measure and other languages",[123,127,131],{"id":124,"by":125,"text":126},"41779029","jsiepkes","Java has JSR 354 for money [1]. There is also a reference implementation [2]. So there is official support for money in Java. [1] https:\u002F\u002Fjcp.org\u002Fen\u002Fjsr\u002Fdetail?id=354 [2]…",{"id":128,"by":129,"text":130},"41777558","psd1","> no mainstream language has a first-class data type for representing money I don't think that's correct, absent some no-true-scotsman gymnastics. F# has units-of-measure (UoM)…",{"id":132,"by":133,"text":134},"41779381","yett","C# has a decimal type: \"The decimal type is a 128-bit data type suitable for financial and monetary calculations.\"…",[136,143,150],{"value":137,"source":81,"evidence":138},"Cash rounding support",[139],{"id":140,"by":141,"text":142},"41777232","Etheryte","Does this library handle rounding rules [0]? In many countries, prices are rounded to the nearest 5 cent, but the rules can often be elaborate. It looks like the allocation…",{"value":144,"source":81,"evidence":145},"Localization of currency symbols",[146],{"id":147,"by":148,"text":149},"41777737","bojanz","I like the support for custom currencies, as that is an edge case that often pops up. On the other hand, be careful about tying the symbol to the currency, as symbols are locale…",{"value":151,"source":81,"evidence":152},"Compile-time currency mismatch checks",[153,157],{"id":154,"by":155,"text":156},"41779261","rebeccaskinner","Neat. It seems to me like this is filling three separate gaps: ``` - fixed point arithmetic - tagging values with units - localization for parsing currency names into units ```…",{"id":158,"by":159,"text":160},"41777450","boronine","I think most of this is covered by a good Decimal API, currency stuff probably shouldn't be embedded into a language because it changes: currencies come and go, get redenominated…",[162,169],{"value":163,"source":81,"evidence":164},"How does adding different currencies behave",[165],{"id":166,"by":167,"text":168},"41779858","hathawsh","I have questions about some edge cases I've encountered in dealing with money. - Let's say I load two money values from a database. Value A is 1 USD and value B is 1 BTC. If I…",{"value":170,"source":81,"evidence":171},"How is rounding configured",[172,173],{"id":166,"by":167,"text":168},{"id":174,"by":11,"text":175},"41780249","Thanks for the questions. Answers: 1. You get an exception 2. You may specify the rounding rule: https:\u002F\u002Fgithub.com\u002Feriksencosta\u002Fmoney\u002Fblob\u002Ftrunk\u002Fdocs\u002Fusage\u002Frounding.md 3. It has…",[177,185,189],{"value":178,"source":81,"evidence":179},"Java Money (JSR 354 \u002F Moneta)",[180,181],{"id":124,"by":125,"text":126},{"id":182,"by":183,"text":184},"41777430","hiddew","How does it compare to the Java money API (https:\u002F\u002Fjcp.org\u002Fen\u002Fjsr\u002Fdetail?id=354) and the related Kotlin DSL in…",{"value":186,"source":81,"evidence":187},"F# units of measure",[188],{"id":128,"by":129,"text":130},{"value":190,"source":81,"evidence":191},"C# and Delphi decimal\u002Fcurrency types",[192,193],{"id":132,"by":133,"text":134},{"id":194,"by":195,"text":196},"41779669","vintagedave","Delphi has a currency type, as does C++Builder (so, a native Currency type available in C++ with that toolchain.) This one seems to carry units, as in, it is not a type with math…",{"comments":198,"answered":199,"key":200},29,11,[201,204,207],{"id":202,"text":203},"41806659","In my previous job, we had a mid-sized team of ~34 software engineers and Kotlin worked like a charm. We set common standards and practices early on and it paid off. The lone…",{"id":205,"text":206},"41780722","The currency exchange support is way simpler than this. The library only provides a method that will calculate the monetary amount given another Money object as the rate: val…",{"id":73,"text":74},{"commenters":209,"max_depth":210,"maker_replies":198,"first_comment_mins":211,"lifespan_hours":212},139,9,26,101,[214,218,222,226,230,233,235,237,240,242,244,247,249,253,255,257,260,263,267,270,273,276,278,281,283,286,288,292,294,297,301,302,306,309,312,314,317,319,323,325,329,332,334,337,340,343,346,349,351,354,358,362,365,368,371,373,375,377,379,381,383,385,386,389,392,395,398,400,403,405,407,410,413,414,417,420,423,426,428,431,433,436,439,442,444,447,450,453,456,458,461,462,465,468,470,473,475,477,479,482,484,488,490,492,494,497,500,503,506,509,511,513,516,517,519,522,524,527,530,533,537,541,544,546,548,550,554,556,560,563,566,568,571,573,576,578,582,585,589,591,594,596,599,601,603,607,610,612,616,617,620,622,626,630,633,636,638,639,641,645,649,652,656,657,659,662,665,667,669,671,675,679,682,684,688,690,695,699,702,704,706,709,712,714,716,719,722,724,727,730,732,736,739,741,744,746,750,753,756,758,761,762,764,766,768,772,774,776,779,781,784,786,789,791,793,795,798,800,802,804,807,809,812,816,819,823,825,827],[215,44,18,216,217,44],"41777532","project\u002Fneutral\u002Fdesign","occz",[219,44,48,220,221,44],"41778015","project\u002Fpositive\u002Fdesign","nwatson",[223,44,44,224,225,44],"41778555","commenter\u002Fneutral\u002Fdesign","sigh_again",[227,44,44,228,229,44],"41778780","other\u002Fcritical\u002Fdesign","refulgentis",[231,44,44,224,232,44],"41779371","t-writescode",[234,44,44,224,229,44],"41780051",[236,44,44,224,232,44],"41782883",[238,44,44,224,239,44],"41779524","mrcrumb1",[241,44,44,224,229,44],"41779728",[243,44,44,224,108,44],"41786168",[245,44,44,224,246,44],"41786916","beeboobaa3",[202,44,44,248,11,34],"maker\u002Fpositive\u002Fdesign",[250,44,44,251,252,44],"41779654","commenter\u002Fneutral\u002Fnone","zoogeny",[254,44,44,224,229,44],"41779894",[256,44,44,224,252,44],"41780438",[258,44,44,224,259,44],"41780936","Clamchop",[261,44,44,224,262,44],"41784229","ulrikrasmussen",[264,44,34,265,266,44],"41782177","project\u002Fcritical\u002Fdesign","gus_massa",[268,44,34,265,269,44],"41782391","callmeal",[271,44,44,224,272,44],"41782525","ternaryoperator",[274,44,18,216,275,44],"41784169","bloated5048",[277,44,44,224,266,44],"41786684",[279,44,34,265,280,44],"41783652","kelnos",[282,44,34,265,266,44],"41786763",[284,44,44,224,285,44],"41792185","calfuris",[287,44,18,216,217,44],"41785469",[289,34,18,290,291,44],"41780037","maker\u002Fneutral\u002Fnone","proper_elb",[205,34,44,293,11,34],"maker\u002Fneutral\u002Fidea",[295,34,34,296,291,44],"41782040","project\u002Fcritical\u002Fidea",[298,34,44,299,300,44],"41795752","commenter\u002Fneutral\u002Fidea","alluringorange",[147,41,18,216,148,44],[303,41,44,304,305,44],"41777955","other\u002Fneutral\u002Fnone","dkarl",[307,41,44,304,308,44],"41791650","andylynch",[310,41,44,304,311,44],"41778022","samatman",[313,41,44,304,148,44],"41778068",[315,41,44,304,316,44],"41779246","ahoka",[73,41,44,318,11,34],"maker\u002Fneutral\u002Fdesign",[320,18,44,321,322,44],"41777196","other\u002Fpositive\u002Fidea","getfroggie",[324,18,44,290,11,34],"41777237",[326,18,44,327,328,44],"41777447","other\u002Fneutral\u002Fidea","ebiester",[330,18,44,327,331,44],"41777592","coreload",[333,18,44,327,328,44],"41777685",[335,18,44,304,336,44],"41779517","benatkin",[338,18,44,327,339,44],"41778544","carapace",[341,18,44,327,342,44],"41778869","skybrian",[344,18,44,327,345,44],"41779035","JumpCrisscross",[347,18,44,251,348,44],"41779842","tomcam",[350,18,44,251,345,44],"41780288",[352,18,44,304,353,44],"41780375","tvaughan",[355,18,18,356,357,44],"41821274","project\u002Fneutral\u002Fidea","hakfoo",[359,18,44,360,361,44],"41778713","other\u002Fcritical\u002Fidea","weego",[363,18,44,299,364,44],"41779010","chipdart",[366,49,48,220,367,44],"41779155","wiremine",[369,49,44,370,11,34],"41780299","maker\u002Fpositive\u002Fnone",[372,48,44,327,252,44],"41779747",[103,374,18,216,104,44],6,[376,374,44,318,11,34],"41780505",[378,374,44,318,11,34],"41806386",[166,42,18,380,167,44],"project\u002Fneutral\u002Fexecution",[174,42,44,382,11,34],"maker\u002Fneutral\u002Fdocs",[140,32,18,384,141,44],"project\u002Fneutral\u002Fpricing",[118,32,44,380,11,34],[387,32,18,384,388,44],"41777391","amluto",[390,32,18,384,391,44],"41777456","criddell",[393,32,18,384,394,44],"41777514","vetinari",[396,32,44,251,397,44],"41777680","cyxxon",[399,32,44,251,394,44],"41778126",[401,32,44,251,402,44],"41785203","jeroenhd",[404,32,44,251,225,44],"41778927",[406,32,44,384,11,34],"41806405",[408,32,18,356,409,44],"41777429","graypegg",[411,32,44,304,412,44],"41781995","sernamar",[132,210,44,327,133,44],[415,210,18,356,416,44],"41779763","nsxwolf",[418,210,44,251,419,44],"41779965","tightbookkeeper",[421,210,44,251,422,44],"41780145","maest",[424,210,44,251,425,44],"41780314","serial_dev",[427,210,44,251,419,44],"41780879",[429,210,44,251,430,44],"41781166","dmoy",[432,210,44,251,419,44],"41781331",[434,210,44,251,435,44],"41780883","Phrodo_00",[437,210,44,251,438,44],"41780979","V41frQo1SccpfHI",[440,210,44,251,441,44],"41781897","amoshebb",[443,210,44,251,419,44],"41784409",[445,210,44,304,446,44],"41781282","knodi123",[448,210,44,304,449,44],"41781894","irq-1",[451,210,18,356,452,44],"41780488","epolanski",[454,210,34,296,455,44],"41781424","moomin",[457,210,44,356,11,34],"41806478",[88,459,48,460,89,44],10,"project\u002Fpositive\u002Fidea",[124,199,44,304,125,44],[463,199,18,356,464,44],"41779825","owlstuffing",[466,199,18,216,467,44],"41781183","willcipriano",[469,199,18,216,464,44],"41782033",[471,199,34,296,472,44],"41784451","wtetzner",[474,199,44,251,464,44],"41784918",[476,199,18,216,472,44],"41784444",[478,199,44,251,464,44],"41785169",[480,199,18,356,481,44],"41791746","oftenwrong",[483,199,44,304,402,44],"41785180",[485,199,48,486,487,44],"41789203","project\u002Fpositive\u002Fexecution","flykespice",[489,199,44,251,125,44],"41798118",[491,199,44,380,11,34],"41806502",[182,493,18,356,183,44],12,[495,493,18,356,496,44],"41777756","rafaelferreira",[498,493,18,356,499,44],"41777855","stickfigure",[501,493,44,304,502,44],"41779272","nogridbag",[504,493,44,505,11,34],"41780290","project\u002Fneutral\u002Fdocs",[507,508,44,370,11,34],"41780640",13,[84,510,48,486,85,44],14,[512,510,44,380,11,34],"41777201",[514,510,44,304,515,44],"41785726","stefs",[111,39,34,265,112,44],[518,39,44,304,217,44],"41778966",[520,39,44,304,521,44],"41779665","dakiol",[523,39,44,304,402,44],"41785295",[525,39,44,304,526,44],"41787269","alleskleber",[528,39,34,265,529,44],"41780448","ttymck",[531,39,34,265,532,44],"41781217","vips7L",[534,535,44,327,536,44],"41781445",16,"0rzech",[538,539,18,356,540,44],"41777534",17,"DaiPlusPlus",[542,539,44,251,543,44],"41777660","sam0x17",[545,539,44,251,540,44],"41778008",[547,539,44,304,11,34],"41780859",[549,539,44,251,540,44],"41779563",[551,552,44,304,553,44],"41780601",18,"kens",[555,552,44,304,11,34],"41780732",[557,558,18,216,559,44],"41778494",19,"zellyn",[561,558,18,216,562,44],"41778543","lolinder",[564,558,18,565,559,44],"41780126","project\u002Fneutral\u002Fnone",[567,558,18,216,562,44],"41780212",[569,558,18,216,570,44],"41778577","thomascgalvin",[572,558,44,251,559,44],"41780149",[574,558,34,265,575,44],"41781648","adamgordonbell",[107,577,34,265,108,44],20,[579,580,18,581,425,44],"41780373",21,"project\u002Fmixed\u002Fdesign",[583,35,18,356,584,44],"41779124","afh1",[586,587,18,216,588,44],"41777466",23,"yafetn",[590,587,34,296,225,44],"41778580",[592,587,44,251,593,44],"41778664","946789987649",[595,587,44,251,225,44],"41778718",[597,587,18,216,598,44],"41787972","Tainnor",[600,587,34,265,225,44],"41792019",[602,587,44,224,598,44],"41802277",[604,605,34,265,606,44],"41780544",24,"ppeetteerr",[608,605,34,265,609,44],"41780594","foooorsyth",[611,605,34,265,606,44],"41784532",[613,614,18,505,615,44],"41781167",25,"pmarreck",[154,211,18,216,155,44],[618,211,18,216,619,44],"41779832","ackfoobar",[621,211,44,216,11,34],"41780432",[623,624,18,380,625,44],"41781803",27,"xyst",[627,628,18,380,629,44],"41778575",28,"mplewis",[631,628,44,251,632,44],"41779273","pasc1878",[634,628,44,251,635,44],"41780164","jpollock",[637,628,44,216,11,34],"41780838",[194,198,18,356,195,44],[640,198,44,356,11,34],"41780346",[642,643,44,304,644,44],"41781748",30,"pbreit",[646,643,44,647,648,44],"41781773","other\u002Fneutral\u002Fperformance","hansonkd",[650,643,44,304,651,44],"41781885","jacobsenscott",[653,654,18,380,655,44],"41777139",31,"atemerev",[67,654,44,380,11,34],[658,654,48,220,655,44],"41777315",[660,654,44,251,661,44],"41779436","vamega",[663,654,44,251,664,44],"41782251","pcl",[666,654,44,251,655,44],"41785597",[95,668,48,460,96,44],32,[670,668,44,370,11,34],"41806546",[672,673,34,265,674,44],"41777622",33,"bradley13",[676,677,18,216,678,44],"41783678",34,"endgame",[680,681,34,265,104,44],"41777781",35,[683,681,44,318,11,34],"41780593",[685,686,44,304,687,44],"41777144",36,"sandGorgon",[689,686,44,304,11,34],"41777212",[691,692,48,693,694,44],"41777521",37,"project\u002Fpositive\u002Fnone","xiaodai",[696,697,44,304,698,44],"41779611",38,"sgt",[700,701,44,304,543,44],"41777497",39,[703,701,44,505,11,34],"41780571",[128,705,34,296,129,44],40,[707,705,44,251,708,44],"41777624","oblio",[710,705,44,251,711,44],"41777760","__MatrixMan__",[713,705,44,251,364,44],"41778887",[715,705,18,384,711,44],"41780745",[717,705,44,251,718,44],"41778775","slekker",[720,705,44,251,721,44],"41779070","williamcotton",[723,705,44,251,364,44],"41778859",[725,705,44,251,726,44],"41778965","nostrademons",[728,705,44,251,729,44],"41779223","explorigin",[731,705,44,293,11,34],"41780359",[733,734,44,251,735,44],"41777460",41,"bayindirh",[737,734,44,251,738,44],"41777523","jeremyjh",[740,734,44,251,735,44],"41777569",[742,734,44,299,743,44],"41777557","mhluongo",[745,734,44,251,735,44],"41777575",[747,748,44,251,749,44],"41777238",42,"shortrounddev2",[751,748,44,251,752,44],"41777259","millerm",[754,748,44,251,755,44],"41777285","wiether",[757,748,44,382,11,34],"41777441",[759,748,44,251,760,44],"41780106","throw16180339",[158,33,34,296,159,44],[763,33,44,251,708,44],"41777625",[765,33,44,251,729,44],"41779236",[767,33,44,251,708,44],"41791054",[769,770,18,565,771,44],"41777123",44,"systems",[773,770,44,565,11,34],"41777164",[775,770,44,304,562,44],"41777202",[777,770,44,304,778,44],"41777209","moritzruth",[780,770,44,304,409,44],"41777482",[782,770,44,304,783,44],"41777739","dtech",[785,770,44,304,562,44],"41777681",[787,770,44,304,788,44],"41780372","ragnese",[790,770,44,304,532,44],"41781367",[792,770,44,304,788,44],"41781724",[794,770,44,304,532,44],"41782039",[796,770,44,304,797,44],"41790035","cempaka",[799,770,44,304,532,44],"41792006",[801,770,44,304,778,44],"41785123",[803,770,44,304,788,44],"41787001",[805,770,44,304,806,44],"41779069","umanwizard",[808,770,44,304,788,44],"41777223",[810,770,44,304,811,44],"41777291","beeforpork",[813,770,44,814,815,44],"41777573","other\u002Fcritical\u002Fnone","g-b-r",[817,770,44,814,818,44],"41778733","speed_spread",[820,821,34,296,822,44],"41778930",45,"slt2021",[824,821,18,356,291,44],"41780108",[826,821,44,293,11,34],"41780513",[828,829,44,304,830,44],"41777243",46,"dlahoda",[],[833,838,842,846,850,855],{"id":834,"name":835,"points":836,"category":837},"41742278","One",506,"dev_tools",{"id":839,"name":840,"points":841,"category":837},"41780297","Player.style",392,{"id":843,"name":844,"points":845,"category":837},"41740568","Chebyshev approximation calculator",278,{"id":847,"name":848,"points":849,"category":837},"41764635","ARIA DevTools",272,{"id":851,"name":852,"points":853,"category":854},"41743327","LiveKit Agents",266,"ai",{"id":856,"name":857,"points":858,"category":859},"41780255","URL expander",213,"other",false,"v2",{"id":863,"name":5,"line":6,"ai":860,"cat":20,"year":13,"points":14,"comments":15,"rec":29,"s":864,"top":18,"kw":865,"maker":11,"domain":10,"tier":19,"attempts":44,"strip":866,"url":9,"mix":867,"praise":80,"objection":100,"sub":21},41776878,-0.14,[24,25,26,27,28],"5001110035333003243313312133533130010001",[32,33,34,35],1794036662602]