UNPKG

moneytostr

Version:

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

743 lines (721 loc) 25.3 kB
/* * $Id$ * * Copyright 2012-2015 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. */ var 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": "двадцять ,тридцять ,сорок ,п’ятдесят ,шістдесят ,сімдесят ,вісімдесят ,дев’яносто " } ] }, "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": "двадцать ,тридцать ,сорок ,пятьдесят ,шестьдесят ,семьдесят ,восемьдесят ,девяносто " } ] }, "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-" } ] }, "RUR": [ { "-CurrID": "810", "-CurrName": "Российские рубли", "-language": "RUS", "-RubOneUnit": "рубль", "-RubTwoUnit": "рубля", "-RubFiveUnit": "рублей", "-RubSex": "M", "-KopOneUnit": "копейка", "-KopTwoUnit": "копейки", "-KopFiveUnit": "копеек", "-KopSex": "F" }, { "-CurrID": "810", "-CurrName": "Российские рубли", "-language": "UKR", "-RubOneUnit": "рубль", "-RubTwoUnit": "рубля", "-RubFiveUnit": "рублей", "-RubSex": "M", "-KopOneUnit": "копейка", "-KopTwoUnit": "копейки", "-KopFiveUnit": "копеек", "-KopSex": "F" } ], "UAH": [ { "-CurrID": "980", "-CurrName": "Украинскі гривні", "-language": "RUS", "-RubOneUnit": "гривня", "-RubTwoUnit": "гривни", "-RubFiveUnit": "гривень", "-RubSex": "F", "-KopOneUnit": "копейка", "-KopTwoUnit": "копейки", "-KopFiveUnit": "копеек", "-KopSex": "F" }, { "-CurrID": "980", "-CurrName": "Украинскі гривні", "-language": "UKR", "-RubOneUnit": "гривня", "-RubTwoUnit": "гривні", "-RubFiveUnit": "гривень", "-RubSex": "F", "-KopOneUnit": "копійка", "-KopTwoUnit": "копійки", "-KopFiveUnit": "копійок", "-KopSex": "F" } ], "USD": [ { "-CurrID": "840", "-CurrName": "Долари США", "-language": "RUS", "-RubOneUnit": "долар", "-RubTwoUnit": "долара", "-RubFiveUnit": "доларів", "-RubSex": "M", "-KopOneUnit": "цент", "-KopTwoUnit": "цента", "-KopFiveUnit": "центов", "-KopSex": "M" }, { "-CurrID": "840", "-CurrName": "Долари США", "-language": "UKR", "-RubOneUnit": "долар", "-RubTwoUnit": "долара", "-RubFiveUnit": "доларів", "-RubSex": "M", "-KopOneUnit": "цент", "-KopTwoUnit": "цента", "-KopFiveUnit": "центів", "-KopSex": "M" }, { "-CurrID": "840", "-CurrName": "Долари США", "-language": "ENG", "-RubOneUnit": "dollar", "-RubTwoUnit": "dollars", "-RubFiveUnit": "dollars", "-RubSex": "M", "-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" } ], "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" } ], "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" } ], "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" } ] } }; /** * Converts numbers to symbols. * * @author Valentyn Kolesnikov * @version $Revision$ $Date$ */ /** Currency. */ enum Currency { UAH, RUR, USD, PER10, PER100, PER1000, PER10000 }; /** Language. */ enum Language { RUS, UKR, ENG }; /** Pennies. */ enum Pennies { NUMBER, TEXT }; class StringBuilder { private _buffer; constructor() { this._buffer = []; } append(text) { this._buffer[this._buffer.length] = text; return this; } insert(index, text) { this._buffer.splice(index, 0, text); return this; } length() { return this.toString().length; } deleteCharAt(index) { var str = this.toString(); this._buffer = []; this.append(str.substring(0, index)); return this; } toString() { return this._buffer.join(""); } }; class MoneyToStr { static NUM0 = 0; static NUM1 = 1; static NUM2 = 2; static NUM3 = 3; static NUM4 = 4; static NUM5 = 5; static NUM6 = 6; static NUM7 = 7; static NUM8 = 8; static NUM9 = 9; static NUM10 = 10; static NUM11 = 11; static NUM14 = 14; static NUM100 = 100; static NUM1000 = 1000; static NUM10000 = 10000; static INDEX_0 = 0; static INDEX_1 = 1; static INDEX_2 = 2; static INDEX_3 = 3; private rubOneUnit; private rubTwoUnit; private rubFiveUnit; private kopOneUnit; private kopTwoUnit; private kopFiveUnit; private rubSex; private kopSex; private currency : Currency; private language : Language; private pennies : Pennies; private messages; static percentToStr(amount, lang : Language) { if (amount == null) { throw new Error("amount is null"); } if (lang == null) { throw new Error("Language is null"); } var intPart = parseInt(amount); var fractPart = 0; var result; if (amount == amount.toInt()) { result = new MoneyToStr(Currency.PER10, lang, Pennies.TEXT).convert(amount, 0); } else if ((amount * MoneyToStr.NUM10).toFixed(4) == 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) == 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) == 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); } return result; } constructor(currency : Currency, language : Language, pennies : Pennies) { this.currency = currency; this.language = language; this.pennies = pennies; var languageElement = Language[language]; var items = currencyList['CurrencyList'][languageElement]['item']; this.messages = {}; for (var index in items) { var languageItem = items[index]; if (languageItem["-text"]) { this.messages[languageItem["-value"]] = languageItem["-text"].split(","); } } var currencyItem = currencyList['CurrencyList'][Currency[currency]] var theISOElement = null; for (var index in currencyItem) { if (currencyItem[index]["-language"] === languageElement) { theISOElement = currencyItem[index]; break; } } if (theISOElement == null) { throw new Error("Currency not found " + Currency[currency]); } this.rubOneUnit = theISOElement["-RubOneUnit"]; this.rubTwoUnit = theISOElement["-RubTwoUnit"]; this.rubFiveUnit = theISOElement["-RubFiveUnit"]; this.kopOneUnit = theISOElement["-KopOneUnit"]; this.kopTwoUnit = theISOElement["-KopTwoUnit"]; this.kopFiveUnit = theISOElement["-KopFiveUnit"]; this.rubSex = theISOElement["-RubSex"]; this.kopSex = theISOElement["-KopSex"]; } /** * Converts double value to the text description. * * @param theMoney * the amount of money in format major.minor * @return the string description of money value */ convertValue(theMoney) { if (typeof theMoney === undefined || theMoney == null) { throw new Error("theMoney is null"); } var intPart = parseInt(theMoney); var fractPart = Math.round((theMoney - intPart) * MoneyToStr.NUM100); if (this.currency == Currency.PER1000) { fractPart = Math.round((theMoney - intPart) * MoneyToStr.NUM1000); } return this.convert(intPart, fractPart); } /** * Converts number to currency. Usage: MoneyToStr moneyToStr = new MoneyToStr("UAH"); String result = * moneyToStr.convert(123D); 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 */ convert(theMoney, theKopeiki) { if (typeof theMoney === undefined || theMoney == null) { throw new Error("theMoney is null"); } if (typeof theKopeiki === undefined || theKopeiki == null) { throw new Error("theKopeiki is null"); } var money2str = new StringBuilder(); var triadNum = 0; var theTriad = 0; var intPart = theMoney; if (intPart == 0) { money2str.append(this.messages["0"][0] + " "); } do { theTriad = parseInt("" + intPart % MoneyToStr.NUM1000); money2str.insert(0, this.triad2Word(theTriad, triadNum, this.rubSex)); if (triadNum == 0) { var range10 = parseInt("" + (theTriad % MoneyToStr.NUM100) / MoneyToStr.NUM10); var range = parseInt("" + theTriad % MoneyToStr.NUM10); if (range10 == MoneyToStr.NUM1) { money2str.append(this.rubFiveUnit); } else { switch (range) { case MoneyToStr.NUM1: money2str.append(this.rubOneUnit); break; case MoneyToStr.NUM2: case MoneyToStr.NUM3: case MoneyToStr.NUM4: money2str.append(this.rubTwoUnit); break; default: money2str.append(this.rubFiveUnit); break; } } } intPart = parseInt("" + intPart / MoneyToStr.NUM1000); triadNum++; } while (intPart > 0); if (this.pennies == Pennies.TEXT) { money2str.append(this.language == Language.ENG ? " and " : " ").append(theKopeiki == 0 ? this.messages["0"][0] + " " : this.triad2Word(theKopeiki, 0, this.kopSex)); } else { money2str.append(" " + (theKopeiki < 10 ? "0" + theKopeiki : theKopeiki) + " "); } if (theKopeiki >= MoneyToStr.NUM11 && theKopeiki <= MoneyToStr.NUM14) { money2str.append(this.kopFiveUnit); } else { switch (parseInt("" + theKopeiki % MoneyToStr.NUM10)) { case MoneyToStr.NUM1: money2str.append(this.kopOneUnit); break; case MoneyToStr.NUM2: case MoneyToStr.NUM3: case MoneyToStr.NUM4: money2str.append(this.kopTwoUnit); break; default: money2str.append(this.kopFiveUnit); break; } } return money2str.toString().trim(); } triad2Word(triad, triadNum, sex) { var triadWord = new StringBuilder(); if (triad == 0) { return ""; } var range = this.check1(triad, triadWord); if (this.language == Language.ENG && triadWord.length() > 0 && triad % MoneyToStr.NUM10 == 0) { triadWord.deleteCharAt(triadWord.length() - 1); triadWord.append(" "); } var range10 = range; range = parseInt("" + triad % MoneyToStr.NUM10); this.check2(triadNum, sex, triadWord, triad, range10); switch (triadNum) { case MoneyToStr.NUM0: break; case MoneyToStr.NUM1: case MoneyToStr.NUM2: case MoneyToStr.NUM3: case MoneyToStr.NUM4: if (range10 == MoneyToStr.NUM1) { triadWord.append(this.messages["1000_10"][triadNum - 1] + " "); } else { switch (range) { case MoneyToStr.NUM1: triadWord.append(this.messages["1000_1"][triadNum - 1] + " "); break; case MoneyToStr.NUM2: case MoneyToStr.NUM3: case MoneyToStr.NUM4: triadWord.append(this.messages["1000_234"][triadNum - 1] + " "); break; default: triadWord.append(this.messages["1000_5"][triadNum - 1] + " "); break; } } break; default: triadWord.append("??? "); break; } return 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 */ check2(triadNum, sex, triadWord, triad, range10) { var range = parseInt("" + triad % MoneyToStr.NUM10); if (range10 == 1) { triadWord.append(this.messages["10_19"][range] + " "); } else { switch (range) { case MoneyToStr.NUM1: if (triadNum == MoneyToStr.NUM1) { triadWord.append(this.messages["1"][MoneyToStr.INDEX_0] + " "); } else if (triadNum == MoneyToStr.NUM2 || triadNum == MoneyToStr.NUM3 || triadNum == MoneyToStr.NUM4) { triadWord.append(this.messages["1"][MoneyToStr.INDEX_1] + " "); } else if ("M" == sex) { triadWord.append(this.messages["1"][MoneyToStr.INDEX_2] + " "); } else if ("F" == sex) { triadWord.append(this.messages["1"][MoneyToStr.INDEX_3] + " "); } break; case MoneyToStr.NUM2: if (triadNum == MoneyToStr.NUM1) { triadWord.append(this.messages["2"][MoneyToStr.INDEX_0] + " "); } else if (triadNum == MoneyToStr.NUM2 || triadNum == MoneyToStr.NUM3 || triadNum == MoneyToStr.NUM4) { triadWord.append(this.messages["2"][MoneyToStr.INDEX_1] + " "); } else if ("M" == sex) { triadWord.append(this.messages["2"][MoneyToStr.INDEX_2] + " "); } else if ("F" == sex) { triadWord.append(this.messages["2"][MoneyToStr.INDEX_3] + " "); } break; case MoneyToStr.NUM3: case MoneyToStr.NUM4: case MoneyToStr.NUM5: case MoneyToStr.NUM6: case MoneyToStr.NUM7: case MoneyToStr.NUM8: case MoneyToStr.NUM9: triadWord.append(["", "", ""].concat(this.messages["3_9"])[range] + " "); break; default: break; } } } /** * @param triad the triad * @param triadWord the triad word * @return the range */ check1(triad, triadWord) { var range = parseInt("" + triad / MoneyToStr.NUM100); triadWord.append([""].concat(this.messages["100_900"])[range]); range = parseInt("" + (triad % MoneyToStr.NUM100) / MoneyToStr.NUM10); triadWord.append(["", ""].concat(this.messages["20_90"])[range]); return range; } }