Skip to content

Commit 723b569

Browse files
committed
feat: add date and time conversion support with new tests
- Implemented `convertDateToWords` method for converting both Jalali and Gregorian dates into Persian words. - Added `convertTimeToWords` method to convert digital time strings ("HH:mm") to Persian words. - Introduced `customTimePrefix` option for customizing the time prefix (default "ساعت"). - Updated tests to cover new date and time conversion functionalities. - Updated documentation and usage examples in the README.
1 parent db795ba commit 723b569

4 files changed

Lines changed: 201 additions & 37 deletions

File tree

README.md

Lines changed: 101 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
11

2-
3-
# Harfizer - Number to Persian Words
4-
**تبدیل عدد به حروف فارسی با TypeScript**
2+
# Harfizer - Number, Date & Time to Persian Words
3+
**تبدیل عدد، تاریخ و زمان به حروف فارسی با TypeScript**
54

65
📘 English & فارسی Documentation
76

87
---
98

109
## 📦 Overview | نمای کلی
1110

12-
**Harfizer** is a modern, TypeScript-native package for converting numbers into their **Persian word** representation. It supports integers, decimals, and negative numbers, with rich customization options including separators, lexicons, and decimal suffixes.
13-
14-
**Harfizer** یک پکیج تایپ‌اسکریپتی مدرن برای تبدیل اعداد به **حروف فارسی** است. این پکیج از اعداد صحیح، اعشاری و منفی پشتیبانی می‌کند و با ارائه گزینه‌های متنوع، امکان سفارشی‌سازی کامل خروجی را فراهم می‌سازد.
15-
16-
---
11+
**Harfizer** is a modern, TypeScript-native package for converting numbers into their **Persian word** representation.
12+
It supports integers, decimals, and negative numbers with rich customization options (such as separators, lexicons, and decimal suffixes).
1713

18-
## 🙏 Acknowledgements | قدردانی
14+
In addition to number conversion, Harfizer now supports converting dates and digital time strings into Persian words.
15+
This means you can now convert both dates (Solar/Jalali or Gregorian) and digital time (HH:mm) to their Persian word equivalents.
1916

20-
We extend our sincere thanks to the creators of the [num2persian](https://www.npmjs.com/package/num2persian) package — an excellent JavaScript utility that made number-to-Persian-word conversion accessible years ago. Inspired by their work, we created **Harfizer** to provide a fully typed, flexible, and extensible solution for modern TypeScript-based applications.
17+
**Harfizer** یک پکیج تایپ‌اسکریپتی مدرن برای تبدیل اعداد به **حروف فارسی** است.
18+
این پکیج از اعداد صحیح، اعشاری و منفی پشتیبانی می‌کند و با ارائه گزینه‌های متنوع، امکان سفارشی‌سازی کامل خروجی (مانند جداکننده‌ها، واژگان و پسوندهای اعشاری) را فراهم می‌سازد.
2119

22-
ما صمیمانه از تیم پکیج [num2persian](https://www.npmjs.com/package/num2persian) تشکر می‌کنیم؛ ابزاری ارزشمند که سال‌ها پیش امکان تبدیل اعداد به حروف فارسی را در جاوااسکریپت فراهم کرد. به عنوان یک برنامه‌نویس که درگیر توسعه‌ی نرم‌افزارهای فارسی‌زبان هستم، وظیفه خود دانستم تا نسخه‌ای مدرن، امن و قابل گسترش برای TypeScript توسعه دهم و آن را با جامعه به اشتراک بگذارم.
20+
همچنین، Harfizer از تبدیل تاریخ‌ها و زمان دیجیتال به حروف فارسی پشتیبانی می‌کند.
21+
این بدان معناست که اکنون می‌توانید تاریخ (شمسی/میلادی) و زمان (به فرمت HH:mm) را به معادل حروف فارسی آن‌ها تبدیل کنید.
2322

2423
---
2524

@@ -33,6 +32,8 @@ npm install harfizer
3332

3433
## 🚀 Basic Usage | استفاده ساده
3534

35+
### Converting Numbers | تبدیل عدد
36+
3637
```ts
3738
import { HarfizerConverter } from 'harfizer';
3839

@@ -45,6 +46,36 @@ console.log(HarfizerConverter.toWords("10500.25"));
4546
// Output: "ده هزار و پانصد ممیز بیست و پنج صدم"
4647
```
4748

49+
### Converting Dates | تبدیل تاریخ
50+
51+
```ts
52+
import { HarfizerConverter } from 'harfizer';
53+
54+
const converter = new HarfizerConverter();
55+
56+
// Convert a Jalali (Solar) date:
57+
console.log(converter.convertDateToWords("1404-03-24"));
58+
// Expected Output: "بیست و چهار خرداد یک هزار و چهارصد و چهار"
59+
60+
// Convert a Gregorian date:
61+
console.log(converter.convertDateToWords("2023-04-05", "gregorian"));
62+
// Expected Output: "پنج آوریل دو هزار و بیست و سه"
63+
```
64+
65+
### Converting Time | تبدیل زمان
66+
67+
```ts
68+
import { HarfizerConverter } from 'harfizer';
69+
70+
const converter = new HarfizerConverter();
71+
72+
console.log(converter.convertTimeToWords("09:05"));
73+
// Expected Output: "ساعت نه و پنج دقیقه"
74+
75+
console.log(converter.convertTimeToWords("18:00"));
76+
// Expected Output: "ساعت هجده"
77+
```
78+
4879
---
4980

5081
## ➖ Negative Numbers | اعداد منفی
@@ -63,16 +94,17 @@ console.log(HarfizerConverter.toWords("-0.01"));
6394

6495
## ⚙️ Custom Options | تنظیمات سفارشی
6596

66-
شما می‌توانید خروجی Harfizer را با گزینه‌های دلخواه تغییر دهید:
97+
You can customize the output of Harfizer using the following options:
6798

68-
| Option | Type | Default | توضیح فارسی |
69-
|--------|------|---------|-------------|
70-
| `useNegativeWord` | `boolean` | `true` | استفاده از کلمه "منفی" |
71-
| `customSeparator` | `string` | `" و "` | جداکننده بین بخش‌ها |
72-
| `customLexicon` | `Lexicon` | پیش‌فرض فارسی | واژگان سفارشی |
73-
| `customDecimalSuffixes` | `string[]` | پیش‌فرض فارسی | پسوندهای اعشاری |
74-
| `customNegativeWord` | `string` | `"منفی "` | واژه منفی دلخواه |
75-
| `customZeroWord` | `string` | `"صفر"` | معادل صفر دلخواه |
99+
| Option | Type | Default | توضیح فارسی |
100+
|------------------------|--------------|--------------|----------------------------------------|
101+
| `useNegativeWord` | `boolean` | `true` | استفاده از کلمه "منفی" |
102+
| `customSeparator` | `string` | `" و "` | جداکننده بین بخش‌ها |
103+
| `customLexicon` | `Lexicon` | پیش‌فرض فارسی | واژگان سفارشی |
104+
| `customDecimalSuffixes`| `string[]` | پیش‌فرض فارسی | پسوندهای اعشاری |
105+
| `customNegativeWord` | `string` | `"منفی "` | واژه منفی دلخواه |
106+
| `customZeroWord` | `string` | `"صفر"` | معادل صفر دلخواه |
107+
| `customTimePrefix` | `string` | `"ساعت"` | پیشوند زمان برای تبدیل زمان |
76108

77109
### Examples | مثال‌ها
78110

@@ -116,12 +148,24 @@ HarfizerConverter.toWords("0.04", {
116148
#### `customLexicon`
117149

118150
```ts
119-
const funnyLexicon = [...]; // your own words
151+
const funnyLexicon = [...]; // واژگان سفارشی خودتان
120152

121153
HarfizerConverter.toWords(12, { customLexicon: funnyLexicon });
122154
// خروجی: بر اساس واژگان سفارشی
123155
```
124156

157+
#### `customTimePrefix` (برای تبدیل زمان)
158+
159+
```ts
160+
import { HarfizerConverter, ConversionOptions } from 'harfizer';
161+
162+
const options: ConversionOptions = { customTimePrefix: "زمان" };
163+
const customConverter = new HarfizerConverter(options);
164+
165+
console.log(customConverter.convertTimeToWords("09:05"));
166+
// خروجی مورد انتظار: "زمان نه و پنج دقیقه"
167+
```
168+
125169
---
126170

127171
## 🧱 Lexicon Structure | ساختار واژگان
@@ -132,7 +176,7 @@ type Lexicon = [
132176
tenToTwenty[], // ده تا بیست
133177
tens[], // بیست تا نود
134178
hundreds[], // یکصد تا نهصد
135-
scales[], // هزار، میلیون، میلیارد و ...
179+
scales[] // هزار، میلیون، میلیارد و ...
136180
];
137181
```
138182

@@ -145,32 +189,32 @@ type Lexicon = [
145189
```ts
146190
const converter = new HarfizerConverter({ customZeroWord: "هیچ" });
147191

148-
converter.convert("0.75");
192+
console.log(converter.convert("0.75"));
149193
// خروجی: "هفتاد و پنج صدم"
150194
```
151195

152-
### Convert triple digits only:
196+
### Convert Triple Digits Only | تبدیل تنها ارقام سه رقمی
153197

154198
```ts
155-
converter.convertTripleToWords(215);
199+
console.log(converter.convertTripleToWords(215));
156200
// خروجی: "دویست و پانزده"
157201
```
158202

159203
---
160-
## 📆 Date Conversion | تبدیل تاریخ
161-
162-
Harfizer now supports converting dates to their Persian word representation using the `convertDateToWords` method. This method accepts a date string in either `YYYY/MM/DD` or `YYYY-MM-DD` format, along with an optional calendar type (`"jalali"` for Solar dates or `"gregorian"` for Gregorian dates, default is `"jalali"`).
163204

164-
Harfizer اکنون از تبدیل تاریخ به حروف فارسی پشتیبانی می‌کند. با استفاده از متد `convertDateToWords` می‌توانید تاریخ‌ها را به رشته‌ای از حروف تبدیل کنید. این متد یک رشته تاریخ به فرمت `YYYY/MM/DD` یا `YYYY-MM-DD` و یک پارامتر تقویم اختیاری (`"jalali"` برای تاریخ شمسی یا `"gregorian"` برای تاریخ میلادی، پیش‌فرض `"jalali"`) را دریافت می‌کند.
205+
## 📆 Date Conversion | تبدیل تاریخ
165206

166-
### Example | مثال
207+
Harfizer supports converting dates to their Persian word representation using the `convertDateToWords` method.
208+
This method accepts a date string in either `YYYY/MM/DD` or `YYYY-MM-DD` format and an optional calendar type:
209+
- `"jalali"` for Solar dates (default)
210+
- `"gregorian"` for Gregorian dates
167211

168212
```ts
169213
import { HarfizerConverter } from 'harfizer';
170214

171215
const converter = new HarfizerConverter();
172216

173-
// Convert a Jalali (Solar) date using dash format:
217+
// Convert a Jalali (Solar) date:
174218
console.log(converter.convertDateToWords("1404-03-24"));
175219
// Expected Output: "بیست و چهار خرداد یک هزار و چهارصد و چهار"
176220

@@ -179,17 +223,39 @@ console.log(converter.convertDateToWords("2023-04-05", "gregorian"));
179223
// Expected Output: "پنج آوریل دو هزار و بیست و سه"
180224
```
181225

226+
---
227+
228+
## ⏰ Time Conversion | تبدیل زمان
229+
230+
Harfizer also converts digital time strings to Persian words using the `convertTimeToWords` method.
231+
It accepts a time string in the format `"HH:mm"` and returns its Persian word representation.
232+
A custom time prefix can be provided via `customTimePrefix` (default is `"ساعت"`).
233+
234+
```ts
235+
import { HarfizerConverter } from 'harfizer';
236+
237+
const converter = new HarfizerConverter();
238+
239+
console.log(converter.convertTimeToWords("09:05"));
240+
// Expected Output: "ساعت نه و پنج دقیقه"
241+
242+
console.log(converter.convertTimeToWords("18:00"));
243+
// Expected Output: "ساعت هجده"
244+
```
245+
246+
---
182247

183248
## 📏 Limitations | محدودیت‌ها
184249

185-
- حداکثر عدد ورودی: 66 رقم (برای اعداد صحیح)
186-
- پشتیبانی از حداکثر 11 رقم اعشار
187-
- ورودی فقط باید عددی باشد (مقدارهای غیرعددی پشتیبانی نمی‌شوند)
250+
- **عدد:** حداکثر عدد ورودی 66 رقم (برای اعداد صحیح)
251+
- **اعشار:** پشتیبانی از حداکثر 11 رقم اعشار
252+
- **تاریخ:** فرمت‌های پشتیبانی شده `YYYY/MM/DD` و `YYYY-MM-DD`
253+
- **زمان:** فرمت پشتیبانی شده برای زمان تنها `"HH:mm"` است.
254+
- ورودی فقط باید عددی (برای تبدیل عدد) یا رشته‌های معتبر برای تاریخ و زمان باشد.
188255

189256
---
190257

191258
## 📚 License | مجوز
192259

193260
**MIT License**
194261
کاملاً متن‌باز و رایگان برای استفاده تجاری و شخصی.
195-

package.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,23 @@
88
"build": "tsc",
99
"test": "jest"
1010
},
11-
"keywords": [
11+
"keywords": [
1212
"persian-numbers",
1313
"number-to-words",
1414
"persian-words",
1515
"harfizer",
1616
"num2persian",
17-
"typescript"
17+
"typescript",
18+
"date-to-words",
19+
"time-to-words",
20+
"persian-date",
21+
"persian-time",
22+
"jalali-date",
23+
"gregorian-date",
24+
"date-conversion",
25+
"time-conversion",
26+
"persian-datetime",
27+
"datetime-to-words"
1828
],
1929
"repository": {
2030
"type": "git",

src/harfizer.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,39 @@ describe("HarfizerConverter", () => {
136136
expect(result).toBe("پنج آوریل دو هزار و بیست و سه");
137137
});
138138
});
139+
140+
describe("convertTimeToWords", () => {
141+
let converter: HarfizerConverter;
142+
143+
beforeEach(() => {
144+
converter = new HarfizerConverter();
145+
});
146+
147+
test("should convert time '09:05' with default prefix", () => {
148+
const result = converter.convertTimeToWords("09:05");
149+
// Expected conversion: "ساعت نه و پنج دقیقه"
150+
expect(result).toBe("ساعت نه و پنج دقیقه");
151+
});
152+
153+
test("should convert time '18:00' with default prefix", () => {
154+
const result = converter.convertTimeToWords("18:00");
155+
// Expected conversion: "ساعت هجده"
156+
expect(result).toBe("ساعت هجده");
157+
});
158+
159+
test("should convert time with custom time prefix", () => {
160+
const customConverter = new HarfizerConverter({
161+
customTimePrefix: "زمان",
162+
});
163+
const result = customConverter.convertTimeToWords("09:05");
164+
// Expected conversion with custom prefix: "زمان نه و پنج دقیقه"
165+
expect(result).toBe("زمان نه و پنج دقیقه");
166+
});
167+
168+
test("should throw error for invalid time format", () => {
169+
expect(() => converter.convertTimeToWords("9-05")).toThrow(
170+
"Invalid time format. Expected format 'HH:mm'."
171+
);
172+
});
173+
});
139174
});

src/harfizer.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export type Lexicon = string[][];
1717
* @property {string[]} [customDecimalSuffixes] - Custom array of suffixes for the fractional part.
1818
* @property {string} [customNegativeWord] - Custom word to denote negative numbers.
1919
* @property {string} [customZeroWord] - Custom word to represent zero.
20+
* @property {string} [customTimePrefix] - Custom prefix for time conversion (e.g. "ساعت" or any other text).
2021
*/
2122
export interface ConversionOptions {
2223
useNegativeWord?: boolean;
@@ -25,6 +26,7 @@ export interface ConversionOptions {
2526
customDecimalSuffixes?: string[];
2627
customNegativeWord?: string;
2728
customZeroWord?: string;
29+
customTimePrefix?: string;
2830
}
2931

3032
/**
@@ -428,6 +430,57 @@ export class HarfizerConverter implements IConverter {
428430
return `${dayWords} ${monthName} ${yearWords}`;
429431
}
430432

433+
/**
434+
* Converts a digital time string (HH:mm) to its Persian word representation.
435+
*
436+
* @param {string} timeStr - The time string in "HH:mm" format.
437+
* @returns {string} The word representation of the time.
438+
* @throws {Error} Throws an error if the time format is invalid or if time values are out of range.
439+
*/
440+
public convertTimeToWords(timeStr: string): string {
441+
// Split the time string using colon (":") as the separator.
442+
const parts = timeStr.split(":");
443+
if (parts.length !== 2) {
444+
throw new Error("Invalid time format. Expected format 'HH:mm'.");
445+
}
446+
const [hourStr, minuteStr] = parts;
447+
448+
// Parse hours and minutes.
449+
const hour = parseInt(hourStr, 10);
450+
const minute = parseInt(minuteStr, 10);
451+
452+
if (isNaN(hour) || isNaN(minute)) {
453+
throw new Error(
454+
"Invalid time format. Hours and minutes should be numbers."
455+
);
456+
}
457+
458+
// Validate hour and minute ranges.
459+
if (hour < 0 || hour > 23) {
460+
throw new Error("Invalid hour value. Hour should be between 0 and 23.");
461+
}
462+
if (minute < 0 || minute > 59) {
463+
throw new Error(
464+
"Invalid minute value. Minute should be between 0 and 59."
465+
);
466+
}
467+
468+
// Retrieve the custom time prefix from configuration or use the default "ساعت".
469+
const timePrefix = this.config.customTimePrefix ?? "ساعت";
470+
471+
// Convert the hour and minute values to their word representations.
472+
const hourWords = this.convert(hour);
473+
const minuteWords = this.convert(minute);
474+
475+
// Construct the final time string in words.
476+
// If minutes are zero, return only the hour part.
477+
if (minute === 0) {
478+
return `${timePrefix} ${hourWords}`;
479+
} else {
480+
return `${timePrefix} ${hourWords} و ${minuteWords} دقیقه`;
481+
}
482+
}
483+
431484
/**
432485
* Returns the default separator from the configuration or default constant.
433486
*

0 commit comments

Comments
 (0)