UNPKG

moneytostr

Version:

The utility class to convert amount to words in Russian/Ukrainian/English languages

794 lines (763 loc) 24.8 kB
# # * $Id$ # * # * Copyright 2014 Valentyn Kolesnikov # * # * Licensed under the Apache License, Version 2.0 (the "License"); # * you may not use this file except in compliance with the License. # * You may obtain a copy of the License at # * # * http://www.apache.org/licenses/LICENSE-2.0 # * # * Unless required by applicable law or agreed to in writing, software # * distributed under the License is distributed on an "AS IS" BASIS, # * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # * See the License for the specific language governing permissions and # * limitations under the License. # currencyList = CurrencyList: language: "-value": "UKR" UKR: item: [ { "-value": "0" "-text": "нуль" } { "-value": "1000_10" "-text": "тисяч,мільйонів,мільярдів,трильйонів" } { "-value": "1000_1" "-text": "тисяча,мільйон,мільярд,трильйон" } { "-value": "1000_234" "-text": "тисячі,мільйона,мільярда,трильйона" } { "-value": "1000_5" "-text": "тисяч,мільйонів,мільярдів,трильйонів" } { "-value": "10_19" "-text": "десять,одинадцять,дванадцять,тринадцять,чотирнадцять,п’ятнадцять,шiстнадцять,сiмнадцять,вiсiмнадцять,дев'ятнадцять" } { "-value": "1" "-text": "одна,один,один,одна" } { "-value": "2" "-text": "дві,два,два,дві" } { "-value": "3_9" "-text": "три,чотири,п’ять,шість,сім,вісім,дев’ять" } { "-value": "100_900" "-text": "сто ,двісті ,триста ,чотириста ,п’ятсот ,шістсот ,сімсот ,вісімсот ,дев’ятсот " } { "-value": "20_90" "-text": "двадцять ,тридцять ,сорок ,п’ятдесят ,шістдесят ,сімдесят ,вісімдесят ,дев’яносто " } { "-value": "pdv" "-text": "в т.ч. ПДВ " } { "-value": "pdv_value" "-text": "20" } ] RUS: item: [ { "-value": "0" "-text": "ноль" } { "-value": "1000_10" "-text": "тысяч,миллионов,миллиардов,триллионов" } { "-value": "1000_1" "-text": "тысяча,миллион,миллиард,триллион" } { "-value": "1000_234" "-text": "тысячи,миллиона,миллиарда,триллиона" } { "-value": "1000_5" "-text": "тысяч,миллионов,миллиардов,триллионов" } { "-value": "10_19" "-text": "десять,одиннадцать,двенадцать,тринадцать,четырнадцать,пятнадцать,шестнадцать,семнадцать,восемнадцать,девятнадцать" } { "-value": "1" "-text": "одна,один,один,одна" } { "-value": "2" "-text": "две,два,два,две" } { "-value": "3_9" "-text": "три,четыре,пять,шесть,семь,восемь,девять" } { "-value": "100_900" "-text": "сто ,двести ,триста ,четыреста ,пятьсот ,шестьсот ,семьсот ,восемьсот ,девятьсот " } { "-value": "20_90" "-text": "двадцать ,тридцать ,сорок ,пятьдесят ,шестьдесят ,семьдесят ,восемьдесят ,девяносто " } { "-value": "pdv" "-text": "в т.ч. НДС " } { "-value": "pdv_value" "-text": "18" } ] ENG: item: [ { "-value": "0" "-text": "zero" } { "-value": "1000_10" "-text": "thousand,million,billion,trillion" } { "-value": "1000_1" "-text": "thousand,million,billion,trillion" } { "-value": "1000_234" "-text": "thousand,million,billion,trillion" } { "-value": "1000_5" "-text": "thousand,million,billion,trillion" } { "-value": "10_19" "-text": "ten,eleven,twelve,thirteen,fourteen,fifteen,sixteen,seventeen,eighteen,nineteen" } { "-value": "1" "-text": "one,one,one,one" } { "-value": "2" "-text": "two,two,two,two" } { "-value": "3_9" "-text": "three,four,five,six,seven,eight,nine" } { "-value": "100_900" "-text": "one hundred ,two hundred ,three hundred ,four hundred ,five hundred ,six hundred ,seven hundred ,eight hundred ,nine hundred " } { "-value": "20_90" "-text": "twenty-,thirty-,forty-,fifty-,sixty-,seventy-,eighty-,ninety-" } { "-value": "pdv" "-text": "including VAT " } { "-value": "pdv_value" "-text": "10" } ] RUR: [ { "-CurrID": "810" "-CurrName": "Российские рубли" "-language": "RUS" "-RubOneUnit": "рубль" "-RubTwoUnit": "рубля" "-RubFiveUnit": "рублей" "-RubSex": "M" "-RubShortUnit": "руб." "-KopOneUnit": "копейка" "-KopTwoUnit": "копейки" "-KopFiveUnit": "копеек" "-KopSex": "F" } { "-CurrID": "810" "-CurrName": "Российские рубли" "-language": "UKR" "-RubOneUnit": "рубль" "-RubTwoUnit": "рублі" "-RubFiveUnit": "рублів" "-RubSex": "M" "-RubShortUnit": "руб." "-KopOneUnit": "копійка" "-KopTwoUnit": "копійки" "-KopFiveUnit": "копійок" "-KopSex": "F" } { "-CurrID": "810" "-CurrName": "Российские рубли" "-language": "ENG" "-RubOneUnit": "ruble" "-RubTwoUnit": "rubles" "-RubFiveUnit": "rubles" "-RubSex": "M" "-RubShortUnit": "RUR." "-KopOneUnit": "kopeck" "-KopTwoUnit": "kopecks" "-KopFiveUnit": "kopecks" "-KopSex": "M" } ] UAH: [ { "-CurrID": "980" "-CurrName": "Украинскі гривні" "-language": "RUS" "-RubOneUnit": "гривня" "-RubTwoUnit": "гривни" "-RubFiveUnit": "гривень" "-RubSex": "F" "-RubShortUnit": "грн." "-KopOneUnit": "копейка" "-KopTwoUnit": "копейки" "-KopFiveUnit": "копеек" "-KopSex": "F" } { "-CurrID": "980" "-CurrName": "Украинскі гривні" "-language": "UKR" "-RubOneUnit": "гривня" "-RubTwoUnit": "гривні" "-RubFiveUnit": "гривень" "-RubSex": "F" "-RubShortUnit": "грн." "-KopOneUnit": "копійка" "-KopTwoUnit": "копійки" "-KopFiveUnit": "копійок" "-KopSex": "F" } { "-CurrID": "980" "-CurrName": "Украинскі гривні" "-language": "ENG" "-RubOneUnit": "hryvnia" "-RubTwoUnit": "hryvnias" "-RubFiveUnit": "hryvnias" "-RubSex": "M" "-RubShortUnit": "UAH." "-KopOneUnit": "kopeck" "-KopTwoUnit": "kopecks" "-KopFiveUnit": "kopecks" "-KopSex": "M" } ] USD: [ { "-CurrID": "840" "-CurrName": "Долари США" "-language": "RUS" "-RubOneUnit": "доллар" "-RubTwoUnit": "доллара" "-RubFiveUnit": "долларов" "-RubSex": "M" "-RubShortUnit": "дол." "-KopOneUnit": "цент" "-KopTwoUnit": "цента" "-KopFiveUnit": "центов" "-KopSex": "M" } { "-CurrID": "840" "-CurrName": "Долари США" "-language": "UKR" "-RubOneUnit": "долар" "-RubTwoUnit": "долара" "-RubFiveUnit": "доларів" "-RubSex": "M" "-RubShortUnit": "дол." "-KopOneUnit": "цент" "-KopTwoUnit": "цента" "-KopFiveUnit": "центів" "-KopSex": "M" } { "-CurrID": "840" "-CurrName": "Долари США" "-language": "ENG" "-RubOneUnit": "dollar" "-RubTwoUnit": "dollars" "-RubFiveUnit": "dollars" "-RubSex": "M" "-RubShortUnit": "USD." "-KopOneUnit": "cent" "-KopTwoUnit": "cents" "-KopFiveUnit": "cents" "-KopSex": "M" } ] PER10: [ { "-CurrID": "556" "-CurrName": "Вiдсотки з десятими частинами" "-language": "RUS" "-RubOneUnit": "целая," "-RubTwoUnit": "целых," "-RubFiveUnit": "целых," "-RubSex": "F" "-KopOneUnit": "десятая процента" "-KopTwoUnit": "десятых процента" "-KopFiveUnit": "десятых процента" "-KopSex": "F" } { "-CurrID": "556" "-CurrName": "Вiдсотки з десятими частинами" "-language": "UKR" "-RubOneUnit": "ціла," "-RubTwoUnit": "цілих," "-RubFiveUnit": "цілих," "-RubSex": "F" "-KopOneUnit": "десята відсотка" "-KopTwoUnit": "десятих відсотка" "-KopFiveUnit": "десятих відсотка" "-KopSex": "F" } { "-CurrID": "560" "-CurrName": "Вiдсотки з десятими частинами" "-language": "ENG" "-RubOneUnit": "," "-RubTwoUnit": "integers," "-RubFiveUnit": "integers," "-RubSex": "F" "-KopOneUnit": "tenth of one percent" "-KopTwoUnit": "tenth of one percent" "-KopFiveUnit": "tenth of one percent" "-KopSex": "F" } ] PER100: [ { "-CurrID": "557" "-CurrName": "Вiдсотки з сотими частинами" "-language": "RUS" "-RubOneUnit": "целая," "-RubTwoUnit": "целых," "-RubFiveUnit": "целых," "-RubSex": "F" "-KopOneUnit": "сотая процента" "-KopTwoUnit": "сотых процента" "-KopFiveUnit": "сотых процента" "-KopSex": "F" } { "-CurrID": "557" "-CurrName": "Вiдсотки з сотими частинами" "-language": "UKR" "-RubOneUnit": "ціла," "-RubTwoUnit": "цілих," "-RubFiveUnit": "цілих," "-RubSex": "F" "-KopOneUnit": "сота відсотка" "-KopTwoUnit": "сотих відсотка" "-KopFiveUnit": "сотих відсотка" "-KopSex": "F" } { "-CurrID": "561" "-CurrName": "Вiдсотки з сотими частинами" "-language": "ENG" "-RubOneUnit": "," "-RubTwoUnit": "integers," "-RubFiveUnit": "integers," "-RubSex": "F" "-KopOneUnit": "hundred percent" "-KopTwoUnit": "hundredth of percent" "-KopFiveUnit": "hundredth of percent" "-KopSex": "F" } ] PER1000: [ { "-CurrID": "558" "-CurrName": "Вiдсотки з тисячними частинами" "-language": "RUS" "-RubOneUnit": "целая," "-RubTwoUnit": "целых," "-RubFiveUnit": "целых," "-RubSex": "F" "-KopOneUnit": "тысячная процента" "-KopTwoUnit": "тысячных процента" "-KopFiveUnit": "тысячных процента" "-KopSex": "F" } { "-CurrID": "558" "-CurrName": "Вiдсотки з тисячними частинами" "-language": "UKR" "-RubOneUnit": "ціла," "-RubTwoUnit": "цілих," "-RubFiveUnit": "цілих," "-RubSex": "F" "-KopOneUnit": "тисячна відсотка" "-KopTwoUnit": "тисячних відсотка" "-KopFiveUnit": "тисячних відсотка" "-KopSex": "F" } { "-CurrID": "562" "-CurrName": "Вiдсотки з тисячними частинами" "-language": "ENG" "-RubOneUnit": "," "-RubTwoUnit": "integers," "-RubFiveUnit": "integers," "-RubSex": "F" "-KopOneUnit": "thousandth of percent" "-KopTwoUnit": "thousandths of percent" "-KopFiveUnit": "thousandths of percent" "-KopSex": "F" } ] PER10000: [ { "-CurrID": "559" "-CurrName": "Вiдсотки з десяти тисячними частинами" "-language": "RUS" "-RubOneUnit": "целая," "-RubTwoUnit": "целых," "-RubFiveUnit": "целых," "-RubSex": "F" "-KopOneUnit": "десятитысячная процента" "-KopTwoUnit": "десятитысячные процента" "-KopFiveUnit": "десятитысячных процента" "-KopSex": "F" } { "-CurrID": "559" "-CurrName": "Вiдсотки з десяти тисячними частинами" "-language": "UKR" "-RubOneUnit": "ціла," "-RubTwoUnit": "цілих," "-RubFiveUnit": "цілих," "-RubSex": "F" "-KopOneUnit": "десятитисячна відсотка" "-KopTwoUnit": "десятитисячних відсотка" "-KopFiveUnit": "десятитисячних відсотка" "-KopSex": "M" } { "-CurrID": "563" "-CurrName": "Вiдсотки з десяти тисячними частинами" "-language": "ENG" "-RubOneUnit": "," "-RubTwoUnit": "integers," "-RubFiveUnit": "integers," "-RubSex": "F" "-KopOneUnit": "ten percent" "-KopTwoUnit": "ten-percent" "-KopFiveUnit": "ten-percent" "-KopSex": "F" } ] ###* Converts numbers to symbols. @author Valentyn Kolesnikov @version $Revision$ $Date$ ### ###* Currency. ### Currency = (-> Currency = -> Currency.UAH = "UAH" Currency.RUR = "RUR" Currency.USD = "USD" Currency.PER10 = "PER10" Currency.PER100 = "PER100" Currency.PER1000 = "PER1000" Currency.PER10000 = "PER10000" Currency )() ###* Language. ### Language = (-> Language = -> Language.RUS = "RUS" Language.UKR = "UKR" Language.ENG = "ENG" Language )() ###* Pennies. ### Pennies = (-> Pennies = -> Pennies.NUMBER = "NUMBER" Pennies.TEXT = "TEXT" Pennies )() StringBuilder = (-> StringBuilder = -> @_buffer = [] return StringBuilder::append = (text) -> @_buffer[@_buffer.length] = text this StringBuilder::insert = (index, text) -> @_buffer.splice index, 0, text this StringBuilder::length = -> @toString().length StringBuilder::deleteCharAt = (index) -> str = @toString() @_buffer = [] @append str.substring(0, index) this StringBuilder::toString = -> @_buffer.join "" StringBuilder )() MoneyToStr = (-> MoneyToStr = (currency, language, pennies) -> @currency = currency @language = language @pennies = pennies languageElement = language items = currencyList["CurrencyList"][languageElement]["item"] @messages = {} for index of items languageItem = items[index] @messages[languageItem["-value"]] = languageItem["-text"].split(",") if languageItem["-text"] currencyItem = currencyList["CurrencyList"][currency] theISOElement = null for index of currencyItem if currencyItem[index]["-language"] is language theISOElement = currencyItem[index] break throw new Error("Currency not found " + currency) unless theISOElement? @rubOneUnit = theISOElement["-RubOneUnit"] @rubTwoUnit = theISOElement["-RubTwoUnit"] @rubFiveUnit = theISOElement["-RubFiveUnit"] @kopOneUnit = theISOElement["-KopOneUnit"] @kopTwoUnit = theISOElement["-KopTwoUnit"] @kopFiveUnit = theISOElement["-KopFiveUnit"] @rubSex = theISOElement["-RubSex"] @kopSex = theISOElement["-KopSex"] @rubShortUnit = theISOElement["-RubShortUnit"] return MoneyToStr.NUM0 = 0 MoneyToStr.NUM1 = 1 MoneyToStr.NUM2 = 2 MoneyToStr.NUM3 = 3 MoneyToStr.NUM4 = 4 MoneyToStr.NUM5 = 5 MoneyToStr.NUM6 = 6 MoneyToStr.NUM7 = 7 MoneyToStr.NUM8 = 8 MoneyToStr.NUM9 = 9 MoneyToStr.NUM10 = 10 MoneyToStr.NUM11 = 11 MoneyToStr.NUM14 = 14 MoneyToStr.NUM100 = 100 MoneyToStr.NUM1000 = 1000 MoneyToStr.NUM10000 = 10000 MoneyToStr.INDEX_0 = 0 MoneyToStr.INDEX_1 = 1 MoneyToStr.INDEX_2 = 2 MoneyToStr.INDEX_3 = 3 MoneyToStr.percentToStr = (amount, lang) -> throw new Error("amount is null") unless amount? throw new Error("lang is null") unless lang? intPart = parseInt(amount) fractPart = 0 result = undefined if amount is parseInt(amount) result = new MoneyToStr(Currency.PER10, lang, Pennies.TEXT).convert(amount, 0) else if (amount * MoneyToStr.NUM10).toFixed(4) is parseInt(amount * MoneyToStr.NUM10).toFixed(4) fractPart = Math.round((amount - intPart) * MoneyToStr.NUM10) result = new MoneyToStr(Currency.PER10, lang, Pennies.TEXT).convert(intPart, fractPart) else if (amount * MoneyToStr.NUM100).toFixed(4) is parseInt(amount * MoneyToStr.NUM100).toFixed(4) fractPart = Math.round((amount - intPart) * MoneyToStr.NUM100) result = new MoneyToStr(Currency.PER100, lang, Pennies.TEXT).convert(intPart, fractPart) else if (amount * MoneyToStr.NUM1000).toFixed(4) is parseInt(amount * MoneyToStr.NUM1000).toFixed(4) fractPart = Math.round((amount - intPart) * MoneyToStr.NUM1000) result = new MoneyToStr(Currency.PER1000, lang, Pennies.TEXT).convert(intPart, fractPart) else fractPart = Math.round((amount - intPart) * MoneyToStr.NUM10000) result = new MoneyToStr(Currency.PER10000, lang, Pennies.TEXT).convert(intPart, fractPart) result ###* Converts double value to the text description. @param theMoney the amount of money in format major.minor @return the string description of money value ### MoneyToStr::convertValue = (theMoney) -> throw new Error("theMoney is null") if typeof theMoney is 'undefined' or not theMoney? intPart = parseInt(theMoney) fractPart = Math.round((theMoney - intPart) * MoneyToStr.NUM100) fractPart = Math.round((theMoney - intPart) * MoneyToStr.NUM1000) if @currency is Currency.PER1000 @convert intPart, fractPart ###* Converts number to currency. Usage: var moneyToStr = new MoneyToStr(Currency.UAH, Language.UKR, Pennies.NUMBER); var result = moneyToStr.convert(123, 0); Expected: result = сто двадцять три гривні 00 копійок @param theMoney the amount of money major currency @param theKopeiki the amount of money minor currency @return the string description of money value ### MoneyToStr::convert = (theMoney, theKopeiki) -> throw new Error("theMoney is null") if typeof theMoney is 'undefined' or not theMoney? throw new Error("theKopeiki is null") if typeof theKopeiki is 'undefined' or not theKopeiki? money2str = new StringBuilder() triadNum = 0 theTriad = 0 intPart = theMoney money2str.append @messages["0"][0] + " " if intPart is 0 loop theTriad = parseInt(intPart % MoneyToStr.NUM1000) money2str.insert 0, @triad2Word(theTriad, triadNum, @rubSex) if triadNum is 0 range10 = parseInt((theTriad % MoneyToStr.NUM100) / MoneyToStr.NUM10) range = parseInt(theTriad % MoneyToStr.NUM10) if range10 is MoneyToStr.NUM1 money2str.append @rubFiveUnit else switch range when MoneyToStr.NUM1 money2str.append @rubOneUnit when MoneyToStr.NUM2, MoneyToStr.NUM3, MoneyToStr.NUM4 money2str.append @rubTwoUnit else money2str.append @rubFiveUnit intPart = parseInt(intPart / MoneyToStr.NUM1000) triadNum++ break unless intPart > 0 if @pennies is Pennies.TEXT money2str.append((if @language is Language.ENG then " and " else " ")).append (if theKopeiki is 0 then @messages["0"][0] + " " else @triad2Word(theKopeiki, 0, @kopSex)) else money2str.append " " + ((if theKopeiki < 10 then "0" + theKopeiki else theKopeiki)) + " " if theKopeiki >= MoneyToStr.NUM11 and theKopeiki <= MoneyToStr.NUM14 money2str.append @kopFiveUnit else switch parseInt(theKopeiki % MoneyToStr.NUM10) when MoneyToStr.NUM1 money2str.append @kopOneUnit when MoneyToStr.NUM2, MoneyToStr.NUM3, MoneyToStr.NUM4 money2str.append @kopTwoUnit else money2str.append @kopFiveUnit money2str.toString().trim() MoneyToStr::triad2Word = (triad, triadNum, sex) -> triadWord = new StringBuilder() return "" if triad is 0 range = @check1(triad, triadWord) if @language is Language.ENG and triadWord.length() > 0 and triad % MoneyToStr.NUM10 is 0 triadWord.deleteCharAt triadWord.length() - 1 triadWord.append " " range10 = range range = parseInt(triad % MoneyToStr.NUM10) @check2 triadNum, sex, triadWord, triad, range10 switch triadNum when MoneyToStr.NUM0 break when MoneyToStr.NUM1, MoneyToStr.NUM2, MoneyToStr.NUM3, MoneyToStr.NUM4 if range10 is MoneyToStr.NUM1 triadWord.append @messages["1000_10"][triadNum - 1] + " " else switch range when MoneyToStr.NUM1 triadWord.append @messages["1000_1"][triadNum - 1] + " " break when MoneyToStr.NUM2, MoneyToStr.NUM3, MoneyToStr.NUM4 triadWord.append @messages["1000_234"][triadNum - 1] + " " break else triadWord.append @messages["1000_5"][triadNum - 1] + " " else triadWord.append "??? " triadWord.toString() ###* @param triadNum the triad num @param sex the sex @param triadWord the triad word @param triad the triad @param range10 the range 10 ### MoneyToStr::check2 = (triadNum, sex, triadWord, triad, range10) -> range = parseInt(triad % MoneyToStr.NUM10) if range10 is 1 triadWord.append @messages["10_19"][range] + " " else switch range when MoneyToStr.NUM1 if triadNum is MoneyToStr.NUM1 triadWord.append @messages["1"][MoneyToStr.INDEX_0] + " " else if triadNum is MoneyToStr.NUM2 or triadNum is MoneyToStr.NUM3 or triadNum is MoneyToStr.NUM4 triadWord.append @messages["1"][MoneyToStr.INDEX_1] + " " else if "M" is sex triadWord.append @messages["1"][MoneyToStr.INDEX_2] + " " else triadWord.append @messages["1"][MoneyToStr.INDEX_3] + " " if "F" is sex when MoneyToStr.NUM2 if triadNum is MoneyToStr.NUM1 triadWord.append @messages["2"][MoneyToStr.INDEX_0] + " " else if triadNum is MoneyToStr.NUM2 or triadNum is MoneyToStr.NUM3 or triadNum is MoneyToStr.NUM4 triadWord.append @messages["2"][MoneyToStr.INDEX_1] + " " else if "M" is sex triadWord.append @messages["2"][MoneyToStr.INDEX_2] + " " else triadWord.append @messages["2"][MoneyToStr.INDEX_3] + " " if "F" is sex when MoneyToStr.NUM3, MoneyToStr.NUM4, MoneyToStr.NUM5, MoneyToStr.NUM6, MoneyToStr.NUM7, MoneyToStr.NUM8, MoneyToStr.NUM9 triadWord.append [ "" "" "" ].concat(@messages["3_9"])[range] + " " else return ###* @param triad the triad @param triadWord the triad word @return the range ### MoneyToStr::check1 = (triad, triadWord) -> range = parseInt(triad / MoneyToStr.NUM100) triadWord.append [""].concat(@messages["100_900"])[range] range = parseInt((triad % MoneyToStr.NUM100) / MoneyToStr.NUM10) triadWord.append [ "" "" ].concat(@messages["20_90"])[range] range MoneyToStr::getMessages = -> @messages MoneyToStr::getRubShortUnit = -> @rubShortUnit MoneyToStr )() module.exports = MoneyToStr: MoneyToStr Currency: Currency Language: Language Pennies: Pennies