moneytostr
Version:
The utility class to convert amount to words in Russian/Ukrainian/English languages
743 lines (721 loc) • 25.3 kB
text/typescript
/*
* $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;
}
}