Skip to content

Commit

Permalink
fix: amountToHangul이 소수점, 숫자도 대응할 수 있도록 수정 (#144)
Browse files Browse the repository at this point in the history
* fix: amountToHangul이 소수점, 숫자도 대응할 수 있도록 수정

* docs: amountToHangul의 영어 문서 작성

* Create famous-cheetahs-sneeze.md

* Update famous-cheetahs-sneeze.md

---------

Co-authored-by: 박찬혁 <[email protected]>
  • Loading branch information
Collection50 and okinawaa authored Jun 30, 2024
1 parent f782ec2 commit b114897
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 37 deletions.
5 changes: 5 additions & 0 deletions .changeset/famous-cheetahs-sneeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"es-hangul": minor
---

fix: amountToHangul이 소수점, 숫자도 대응할 수 있도록 수정
12 changes: 5 additions & 7 deletions docs/src/pages/docs/api/amountToHangul.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ Converts numeric amounts to the Korean reading of the [National Institute of Kor
For detailed examples, see below.

```typescript
function amountToHangul(
// A string of numeric amounts
str: string
): string;
function amountToHangul(amount: string | number): string;
```

## Examples

```tsx
amountToHangul('15,201,100'); // '일천오백이십만천백';
amountToHangul('120,030원'); // '일십이만삼십' - Ignore non-numeric characters
amountToHangul('392.24'); // '삼백구십이' - Ignore decimals
amountToHangul('15,201,100'); // '일천오백이십만천백'
amountToHangul('120,030원'); // '일십이만삼십'
amountToHangul('12345.6789'); // '일만이천삼백사십오점육칠팔구'
amountToHangul(15_201_100); // '일천오백이십만천백''
```
14 changes: 6 additions & 8 deletions docs/src/pages/docs/api/amountToHangul.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,19 @@ title: amountToHangul

# amountToHangul

숫자로 된 금액을 [국립국어원](https://ko.dict.naver.com/#/correct/korean/info?seq=602) 규칙의 한글 읽기로 변환합니다.
숫자나 문자를 [국립국어원](https://ko.dict.naver.com/#/correct/korean/info?seq=602) 규칙의 한글 읽기 문자열로 변환합니다.

자세한 예시는 아래 Example을 참고하세요.

```typescript
function amountToHangul(
// 숫자로 된 금액 문자열
str: string
): string;
function amountToHangul(amount: string | number): string;
```

## Examples

```tsx
amountToHangul('15,201,100'); // '일천오백이십만천백';
amountToHangul('120,030원'); // '일십이만삼십' - 숫자 외 문자 무시
amountToHangul('392.24'); // '삼백구십이' - 소수점 무시
amountToHangul('15,201,100'); // '일천오백이십만천백'
amountToHangul('120,030원'); // '일십이만삼십'
amountToHangul('12345.6789'); // '일만이천삼백사십오점육칠팔구'
amountToHangul(15_201_100); // '일천오백이십만천백''
```
19 changes: 16 additions & 3 deletions src/amountToHangul.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import { amountToHangul } from './amountToHangul';

describe('amountToHangul', () => {
it('숫자로 된 금액을 한글로 표기', () => {
it('금액 문자열을 한글로 표기', () => {
expect(amountToHangul('15,201,100')).toEqual('일천오백이십만천백');
expect(amountToHangul('120,030원')).toEqual('일십이만삼십'); // 숫자 외 문자 무시
expect(amountToHangul('392.24')).toEqual('삼백구십이'); // 소수점 무시
expect(amountToHangul('100000000')).toEqual('일억');
expect(amountToHangul('100000100')).toEqual('일억백');
});

it('숫자 외 문자를 무시하여 반환', () => {
expect(amountToHangul('120,030원')).toEqual('일십이만삼십');
});

it('소수점이 있는 경우도 표기', () => {
expect(amountToHangul('392.24')).toEqual('삼백구십이점이사');
expect(amountToHangul('12345.6789')).toEqual('일만이천삼백사십오점육칠팔구');
});

it('금액 숫자를 한글로 표기', () => {
expect(amountToHangul(15_201_100)).toEqual('일천오백이십만천백');
expect(amountToHangul(100000100)).toEqual('일억백');
expect(amountToHangul(392.24)).toEqual('삼백구십이점이사');
});
});
74 changes: 55 additions & 19 deletions src/amountToHangul.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,71 @@
export const HANGUL_DIGITS = ['', '만', '억', '조', '경', '해', '자', '양', '구', '간', '정', '재', '극', '항하사', '아승기', '나유타', '불가사의', '무량대수', '겁', '업'];
export const HANGUL_DIGITS = [
'',
'만',
'억',
'조',
'경',
'해',
'자',
'양',
'구',
'간',
'정',
'재',
'극',
'항하사',
'아승기',
'나유타',
'불가사의',
'무량대수',
'겁',
'업',
];
export const HANGUL_DIGITS_MAX = HANGUL_DIGITS.length * 4;
export const HANGUL_NUMBERS = ['', '일', '이', '삼', '사', '오', '육', '칠', '팔', '구'];
export const HANGUL_CARDINAL = ['', '십', '백', '천'];

// https://ko.dict.naver.com/#/correct/korean/info?seq=602
// https://github.com/crucifyer/koreanCardinalOrdinal
export function amountToHangul(str: string) {
str = str.replace(/\..*$/, '') // 소수점 지원 안함
.replace(/[^\d]+/g, ''); // , 표기 등 오류내지 않음
if(str.length > HANGUL_DIGITS_MAX) {
throw new Error('convert range exceeded : ' + str);
export function amountToHangul(amount: string | number) {
const [integerPart, decimalPart] = String(amount)
.replace(/[^\d.]+/g, '')
.split('.');

if (integerPart.length > HANGUL_DIGITS_MAX) {
throw new Error(`convert range exceeded : ${amount}`);
}

const result = [];
let pronunDigits = true;
for(let i = 0; i < str.length - 1; i ++) {
const d = str.length - i - 1;
if(str[i] > '1' || d % 4 === 0 || i === 0) {
const tnum = HANGUL_NUMBERS[parseInt(str[i])];
if(tnum) {
result.push(tnum);

for (let i = 0; i < integerPart.length - 1; i++) {
const digit = integerPart.length - i - 1;

if (integerPart[i] > '1' || digit % 4 === 0 || i === 0) {
const hangulNumber = HANGUL_NUMBERS[Number(integerPart[i])];

if (hangulNumber) {
result.push(hangulNumber);
pronunDigits = true;
}
}
if(pronunDigits && d % 4 === 0) {
result.push(HANGUL_DIGITS[d / 4]);

if (pronunDigits && digit % 4 === 0) {
result.push(HANGUL_DIGITS[digit / 4]);
pronunDigits = false;
}
if(str[i] !== '0') {
result.push(HANGUL_CARDINAL[d % 4]);

if (integerPart[i] !== '0') {
result.push(HANGUL_CARDINAL[digit % 4]);
}
}
result.push(HANGUL_NUMBERS[Number(integerPart[integerPart.length - 1])]);

if (decimalPart) {
result.push('점');

for (let i = 0; i < decimalPart.length; i++) {
result.push(HANGUL_NUMBERS[Number(decimalPart[i])]);
}
}
result.push(HANGUL_NUMBERS[parseInt(str[str.length - 1])]);

return result.join('');
}

0 comments on commit b114897

Please sign in to comment.