persiantools 5.2.0__tar.gz → 5.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- persiantools-5.2.1/PKG-INFO +352 -0
- persiantools-5.2.1/README.md +308 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/persiantools/__init__.py +1 -1
- persiantools-5.2.1/persiantools.egg-info/PKG-INFO +352 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/tests/test_jalalidate.py +1 -0
- persiantools-5.2.0/PKG-INFO +0 -211
- persiantools-5.2.0/README.md +0 -168
- persiantools-5.2.0/persiantools.egg-info/PKG-INFO +0 -211
- {persiantools-5.2.0 → persiantools-5.2.1}/LICENSE +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/MANIFEST.in +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/persiantools/characters.py +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/persiantools/digits.py +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/persiantools/jdatetime.py +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/persiantools/utils.py +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/persiantools.egg-info/SOURCES.txt +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/persiantools.egg-info/dependency_links.txt +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/persiantools.egg-info/not-zip-safe +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/persiantools.egg-info/requires.txt +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/persiantools.egg-info/top_level.txt +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/pyproject.toml +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/setup.cfg +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/setup.py +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/tests/test_characters.py +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/tests/test_digits.py +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/tests/test_jalalidatetime.py +0 -0
- {persiantools-5.2.0 → persiantools-5.2.1}/tests/test_utils.py +0 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: persiantools
|
|
3
|
+
Version: 5.2.1
|
|
4
|
+
Summary: Jalali date and datetime with other tools
|
|
5
|
+
Home-page: https://github.com/majiidd/persiantools
|
|
6
|
+
Author: Majid Hajiloo
|
|
7
|
+
Author-email: majid.hajiloo@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: jalali shamsi persian digits characters converter jalalidate jalalidatetime date datetime jdate jdatetime farsi
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Natural Language :: Persian
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
22
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
23
|
+
Classifier: Topic :: Software Development
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Topic :: Software Development :: Localization
|
|
27
|
+
Classifier: Topic :: Utilities
|
|
28
|
+
Requires-Python: >=3.9
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Requires-Dist: pytz
|
|
32
|
+
Dynamic: author
|
|
33
|
+
Dynamic: author-email
|
|
34
|
+
Dynamic: classifier
|
|
35
|
+
Dynamic: description
|
|
36
|
+
Dynamic: description-content-type
|
|
37
|
+
Dynamic: home-page
|
|
38
|
+
Dynamic: keywords
|
|
39
|
+
Dynamic: license
|
|
40
|
+
Dynamic: license-file
|
|
41
|
+
Dynamic: requires-dist
|
|
42
|
+
Dynamic: requires-python
|
|
43
|
+
Dynamic: summary
|
|
44
|
+
|
|
45
|
+
# PersianTools
|
|
46
|
+
|
|
47
|
+
[](https://pypi.org/project/persiantools/)
|
|
48
|
+

|
|
49
|
+
[](https://results.pre-commit.ci/latest/github/majiidd/persiantools/master)
|
|
50
|
+
[](https://codecov.io/gh/majiidd/persiantools)
|
|
51
|
+
[](https://pypi.org/project/persiantools/)
|
|
52
|
+
[](https://pypi.org/project/persiantools/)
|
|
53
|
+
|
|
54
|
+
`PersianTools` is a library written in Python for working with Jalali (Persian or Shamsi) dates and times, converting Persian and Arabic characters and digits, and converting numbers to Persian words.
|
|
55
|
+
|
|
56
|
+
## Key Features
|
|
57
|
+
|
|
58
|
+
- Conversion between Jalali and Gregorian dates/datetimes using Python's native datetime module.
|
|
59
|
+
- Full support for operations such as `+`, `-`, `==`, `>` and `>=`.
|
|
60
|
+
- Timezone-aware date and datetime handling.
|
|
61
|
+
- Conversion between Persian, Arabic, and English characters and digits.
|
|
62
|
+
- Conversion of numbers to their Persian word representation.
|
|
63
|
+
|
|
64
|
+
## Install Package
|
|
65
|
+
|
|
66
|
+
You can install the package using `pip` with the following command:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
python -m pip install persiantools
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Usage Guide
|
|
73
|
+
|
|
74
|
+
### Date Operations
|
|
75
|
+
|
|
76
|
+
The `JalaliDate` object represents a date in the Jalali calendar.
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
>>> from persiantools.jdatetime import JalaliDate
|
|
80
|
+
>>> import datetime
|
|
81
|
+
|
|
82
|
+
# Today's date
|
|
83
|
+
>>> JalaliDate.today()
|
|
84
|
+
JalaliDate(1404, 3, 16, Jomeh)
|
|
85
|
+
|
|
86
|
+
>>> JalaliDate(1367, 2, 14)
|
|
87
|
+
JalaliDate(1367, 2, 14, Chaharshanbeh)
|
|
88
|
+
|
|
89
|
+
# Convert Gregorian to Jalali
|
|
90
|
+
>>> JalaliDate(datetime.date(1988, 5, 4))
|
|
91
|
+
JalaliDate(1367, 2, 14, Chaharshanbeh)
|
|
92
|
+
|
|
93
|
+
# Convert from Gregorian to Jalali using method
|
|
94
|
+
>>> JalaliDate.to_jalali(2013, 9, 16)
|
|
95
|
+
JalaliDate(1392, 6, 25, Doshanbeh)
|
|
96
|
+
|
|
97
|
+
# Convert from Jalali to Gregorian
|
|
98
|
+
>>> JalaliDate(1392, 6, 25).to_gregorian()
|
|
99
|
+
datetime.date(2013, 9, 16)
|
|
100
|
+
|
|
101
|
+
# From ISO format
|
|
102
|
+
>>> JalaliDate.fromisoformat('1404-01-01')
|
|
103
|
+
JalaliDate(1404, 1, 1, Jomeh)
|
|
104
|
+
|
|
105
|
+
# Create a Jalali date from a Unix timestamp
|
|
106
|
+
>>> JalaliDate.fromtimestamp(578707200)
|
|
107
|
+
JalaliDate(1367, 2, 14, Chaharshanbeh)
|
|
108
|
+
|
|
109
|
+
# ISO format output
|
|
110
|
+
>>> JalaliDate(1367, 2, 14).isoformat()
|
|
111
|
+
'1367-02-14'
|
|
112
|
+
|
|
113
|
+
# Replace date parts
|
|
114
|
+
>>> JalaliDate(1400, 1, 1).replace(month=2, day=10)
|
|
115
|
+
JalaliDate(1400, 2, 10, Jomeh)
|
|
116
|
+
```
|
|
117
|
+
#### Attributes and Methods
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
>>> date_obj = JalaliDate(1367, 2, 14)
|
|
121
|
+
|
|
122
|
+
>>> date_obj.year
|
|
123
|
+
1367
|
|
124
|
+
>>> date_obj.month
|
|
125
|
+
2
|
|
126
|
+
>>> date_obj.day
|
|
127
|
+
14
|
|
128
|
+
|
|
129
|
+
# Weekday (Saturday is 0 and Friday is 6)
|
|
130
|
+
>>> date_obj.weekday() # 1367/2/14 is Chaharshanbeh (Wednesday)
|
|
131
|
+
4
|
|
132
|
+
|
|
133
|
+
# ISO Weekday (Monday is 1 and Sunday is 7)
|
|
134
|
+
>>> date_obj.isoweekday()
|
|
135
|
+
5
|
|
136
|
+
|
|
137
|
+
>>> date_obj.week_of_year()
|
|
138
|
+
7
|
|
139
|
+
|
|
140
|
+
# ISO Calendar (ISO year, ISO week number, ISO weekday)
|
|
141
|
+
>>> date_obj.isocalendar()
|
|
142
|
+
(1367, 7, 5)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Datetime Operations
|
|
146
|
+
|
|
147
|
+
The `JalaliDateTime` object represents a date and time in the Jalali calendar.
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
>>> from persiantools.jdatetime import JalaliDateTime
|
|
151
|
+
>>> import datetime, pytz
|
|
152
|
+
|
|
153
|
+
# Current Jalali datetime
|
|
154
|
+
>>> JalaliDateTime.now()
|
|
155
|
+
JalaliDateTime(1404, 3, 16, 2, 17, 14, 907909)
|
|
156
|
+
|
|
157
|
+
# Current Jalali datetime (timezone-aware)
|
|
158
|
+
>>> JalaliDateTime.now(pytz.timezone("Asia/Tehran"))
|
|
159
|
+
JalaliDateTime(1404, 3, 16, 2, 17, 14, 907909, tzinfo=<DstTzInfo 'Asia/Tehran' +0330+3:30:00 STD>)
|
|
160
|
+
|
|
161
|
+
# Current UTC Jalali datetime
|
|
162
|
+
>>> JalaliDateTime.utcnow()
|
|
163
|
+
JalaliDateTime(1404, 3, 15, 22, 56, 49, 892339, tzinfo=datetime.timezone.utc)
|
|
164
|
+
|
|
165
|
+
# Convert Jalali datetime to Gregorian
|
|
166
|
+
>>> JalaliDateTime.now().to_gregorian()
|
|
167
|
+
datetime.datetime(2025, 6, 6, 2, 17, 14, 907909)
|
|
168
|
+
|
|
169
|
+
# Convert Gregorian datetime to Jalali (From a datetime.datetime object)
|
|
170
|
+
>>> dt_gregorian = datetime.datetime(1988, 5, 4, 14, 30, 15)
|
|
171
|
+
>>> JalaliDateTime(dt_gregorian)
|
|
172
|
+
JalaliDateTime(1367, 2, 14, 14, 30, 15)
|
|
173
|
+
|
|
174
|
+
# Replace datetime parts
|
|
175
|
+
>>> JalaliDateTime(1400, 1, 1, 12, 0, 0).replace(hour=15, minute=30, microsecond=10)
|
|
176
|
+
JalaliDateTime(1400, 1, 1, 15, 30, 0, 10)
|
|
177
|
+
|
|
178
|
+
# Timezone conversion
|
|
179
|
+
>>> tehran_tz = pytz.timezone("Asia/Tehran")
|
|
180
|
+
>>> utc_tz = pytz.utc
|
|
181
|
+
>>> dt_utc = JalaliDateTime.now(utc_tz)
|
|
182
|
+
>>> dt_tehran = dt_utc.astimezone(tehran_tz)
|
|
183
|
+
>>> dt_utc
|
|
184
|
+
JalaliDateTime(1404, 3, 15, 22, 54, 8, 835877, tzinfo=<UTC>)
|
|
185
|
+
>>> dt_tehran
|
|
186
|
+
JalaliDateTime(1404, 3, 16, 2, 24, 8, 835877, tzinfo=<DstTzInfo 'Asia/Tehran' +0330+3:30:00 STD>)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### Attributes and Methods
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
>>> dt_obj = JalaliDateTime(1367, 2, 14, 14, 30, 15, 123, tzinfo=pytz.utc)
|
|
193
|
+
|
|
194
|
+
>>> dt_obj.year
|
|
195
|
+
1367
|
|
196
|
+
>>> dt_obj.month
|
|
197
|
+
2
|
|
198
|
+
>>> dt_obj.day
|
|
199
|
+
14
|
|
200
|
+
>>> dt_obj.hour
|
|
201
|
+
14
|
|
202
|
+
>>> dt_obj.minute
|
|
203
|
+
30
|
|
204
|
+
>>> dt_obj.second
|
|
205
|
+
15
|
|
206
|
+
>>> dt_obj.microsecond
|
|
207
|
+
123
|
|
208
|
+
>>> dt_obj.tzinfo
|
|
209
|
+
<UTC>
|
|
210
|
+
|
|
211
|
+
# Date part as datetime.date (Gregorian)
|
|
212
|
+
>>> dt_obj.date()
|
|
213
|
+
datetime.date(1988, 5, 4)
|
|
214
|
+
|
|
215
|
+
# JalaliDate object
|
|
216
|
+
>>> dt_obj.jdate()
|
|
217
|
+
JalaliDate(1367, 2, 14, Chaharshanbeh)
|
|
218
|
+
|
|
219
|
+
# Time part as datetime.time
|
|
220
|
+
>>> dt_obj.time()
|
|
221
|
+
datetime.time(14, 30, 15, 123)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Formatting
|
|
225
|
+
|
|
226
|
+
Based on python `strftime()` behavior
|
|
227
|
+
|
|
228
|
+
```python
|
|
229
|
+
>>> from persiantools.jdatetime import JalaliDateTime
|
|
230
|
+
>>> import pytz
|
|
231
|
+
|
|
232
|
+
>>> dt = JalaliDateTime(1367, 2, 14, 14, 30, 0, tzinfo=pytz.timezone("Asia/Tehran"))
|
|
233
|
+
|
|
234
|
+
>>> dt.strftime("%Y/%m/%d %H:%M:%S")
|
|
235
|
+
'1367/02/14 14:30:00'
|
|
236
|
+
|
|
237
|
+
>>> dt.strftime("%c", locale='fa')
|
|
238
|
+
'چهارشنبه ۱۴ اردیبهشت ۱۳۶۷ ۱۴:۳۰:۰۰'
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Digits and Character Conversion
|
|
242
|
+
|
|
243
|
+
This section covers converting between different numeral systems (Persian, Arabic, English) and converting numbers to their Persian word representations. It also includes utilities for converting between Persian and Arabic characters.
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
>>> from persiantools import digits
|
|
247
|
+
|
|
248
|
+
# Convert English digits to Persian
|
|
249
|
+
>>> digits.en_to_fa("0987654321")
|
|
250
|
+
'۰۹۸۷۶۵۴۳۲۱'
|
|
251
|
+
|
|
252
|
+
# Convert Arabic digits to Persian
|
|
253
|
+
>>> digits.ar_to_fa("٠٩٨٧٦٥٤٣٢١")
|
|
254
|
+
'۰۹۸۷۶۵۴۳۲۱'
|
|
255
|
+
|
|
256
|
+
# Convert Persian digits to English
|
|
257
|
+
>>> digits.fa_to_en("۰۹۸۷۶۵۴۳۲۱")
|
|
258
|
+
'0987654321'
|
|
259
|
+
|
|
260
|
+
# Convert Persian digits to Arabic
|
|
261
|
+
>>> digits.fa_to_ar("۰۹۸۷۶۵۴۳۲۱")
|
|
262
|
+
'٠٩٨٧٦٥٤٣٢١'
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### Numbers to Words
|
|
266
|
+
|
|
267
|
+
Convert numerical values (integers and floats) into Persian words.
|
|
268
|
+
|
|
269
|
+
```python
|
|
270
|
+
>>> from persiantools import digits
|
|
271
|
+
|
|
272
|
+
>>> digits.to_word(9512026)
|
|
273
|
+
'نه میلیون و پانصد و دوازده هزار و بیست و شش'
|
|
274
|
+
|
|
275
|
+
>>> digits.to_word(15.007)
|
|
276
|
+
'پانزده و هفت هزارم'
|
|
277
|
+
|
|
278
|
+
>>> digits.to_word(-123.45)
|
|
279
|
+
'منفی یکصد و بیست و سه و چهل و پنج صدم'
|
|
280
|
+
|
|
281
|
+
>>> digits.to_word(0)
|
|
282
|
+
'صفر'
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
#### Character Conversion
|
|
286
|
+
|
|
287
|
+
Functions for converting specific Arabic characters to their Persian equivalents and vice-versa. This is often needed due to differences in the Unicode representation of similar-looking characters (e.g., `ک` vs `ك`, `ی` vs `ي`).
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
>>> from persiantools import characters
|
|
291
|
+
|
|
292
|
+
>>> characters.ar_to_fa("كيك") # Input uses Arabic Kaf (U+0643) and Yeh (U+064A)
|
|
293
|
+
'کیک' # Output uses Persian Keh (U+06A9) and Yeh (U+06CC)
|
|
294
|
+
|
|
295
|
+
>>> characters.fa_to_ar("کیک")
|
|
296
|
+
'كيك'
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Operators
|
|
300
|
+
|
|
301
|
+
Both `JalaliDate` and `JalaliDateTime` objects support standard comparison operators (`<`, `<=`, `==`, `!=`, `>`, `>=`) and arithmetic operations (`+`, `-` with `datetime.timedelta` objects). They can also be compared with their Gregorian counterparts (`datetime.date` and `datetime.datetime`).
|
|
302
|
+
|
|
303
|
+
```python
|
|
304
|
+
>>> from persiantools.jdatetime import JalaliDate, JalaliDateTime
|
|
305
|
+
>>> import datetime
|
|
306
|
+
|
|
307
|
+
>>> JalaliDate(1367, 2, 14) == JalaliDate(datetime.date(1988, 5, 4))
|
|
308
|
+
True
|
|
309
|
+
|
|
310
|
+
>>> JalaliDateTime(1367, 2, 14, 4, 30) >= JalaliDateTime(1368, 2, 14, 1, 0)
|
|
311
|
+
False
|
|
312
|
+
|
|
313
|
+
>>> JalaliDate(1367, 2, 14) == datetime.date(1988, 5, 4)
|
|
314
|
+
True
|
|
315
|
+
|
|
316
|
+
>>> JalaliDate(1395, 2, 14) + datetime.timedelta(days=38)
|
|
317
|
+
JalaliDate(1395, 3, 21, Jomeh)
|
|
318
|
+
|
|
319
|
+
>>> JalaliDateTime(1395, 12, 30) - JalaliDateTime(1395, 1, 1)
|
|
320
|
+
datetime.timedelta(365)
|
|
321
|
+
|
|
322
|
+
>>> JalaliDateTime(1395, 2, 14, 12, 0, 0) + datetime.timedelta(hours=5, minutes=30)
|
|
323
|
+
JalaliDateTime(1395, 2, 14, 17, 30)
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Serializing and Deserializing
|
|
327
|
+
|
|
328
|
+
`JalaliDate` and `JalaliDateTime` objects can be serialized (pickled) and deserialized (unpickled) using Python's standard `pickle` module. This allows for storing these objects or transmitting them.
|
|
329
|
+
|
|
330
|
+
```python
|
|
331
|
+
>>> from persiantools.jdatetime import JalaliDate
|
|
332
|
+
>>> import pickle
|
|
333
|
+
|
|
334
|
+
# Serialize a Jalali date to a file
|
|
335
|
+
>>> with open("save.p", "wb") as file:
|
|
336
|
+
>>> pickle.dump(JalaliDate(1367, 2, 14), file)
|
|
337
|
+
|
|
338
|
+
# Deserialize from a file
|
|
339
|
+
>>> with open("save.p", "rb") as file:
|
|
340
|
+
>>> jalali = pickle.load(file)
|
|
341
|
+
>>> jalali
|
|
342
|
+
JalaliDate(1367, 2, 14, Chaharshanbeh)
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Support This Project
|
|
346
|
+
If you find this project helpful and would like to support its continued development, please consider donating.
|
|
347
|
+
|
|
348
|
+
* **Bitcoin (BTC):** `bc1qg5rp7ymznc98wmhltzvpwl2dvfuvjr33m4hy77`
|
|
349
|
+
* **Tron (TRX):** `TDd63bVWZDBHmwVNFgJ6T2WdWmk9z7PBLg`
|
|
350
|
+
* **Stellar (XLM):** `GDSFPPLY34QSAOTOP4DQDXAI2YDRNRIADZHTN3HCGMQXRLIGPYOEH7L5`
|
|
351
|
+
* **Solana (SOL):** `CXHKgCBqBYy1hbZKGqaSmMzQoTC4Wx2v8QfL9Z7JBo3A`
|
|
352
|
+
* **Dogecoin (DOGE):** `DRZ2QLuXfa5vV1AG83K3XHfYXAHj9b4h4V`
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# PersianTools
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/persiantools/)
|
|
4
|
+

|
|
5
|
+
[](https://results.pre-commit.ci/latest/github/majiidd/persiantools/master)
|
|
6
|
+
[](https://codecov.io/gh/majiidd/persiantools)
|
|
7
|
+
[](https://pypi.org/project/persiantools/)
|
|
8
|
+
[](https://pypi.org/project/persiantools/)
|
|
9
|
+
|
|
10
|
+
`PersianTools` is a library written in Python for working with Jalali (Persian or Shamsi) dates and times, converting Persian and Arabic characters and digits, and converting numbers to Persian words.
|
|
11
|
+
|
|
12
|
+
## Key Features
|
|
13
|
+
|
|
14
|
+
- Conversion between Jalali and Gregorian dates/datetimes using Python's native datetime module.
|
|
15
|
+
- Full support for operations such as `+`, `-`, `==`, `>` and `>=`.
|
|
16
|
+
- Timezone-aware date and datetime handling.
|
|
17
|
+
- Conversion between Persian, Arabic, and English characters and digits.
|
|
18
|
+
- Conversion of numbers to their Persian word representation.
|
|
19
|
+
|
|
20
|
+
## Install Package
|
|
21
|
+
|
|
22
|
+
You can install the package using `pip` with the following command:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
python -m pip install persiantools
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Usage Guide
|
|
29
|
+
|
|
30
|
+
### Date Operations
|
|
31
|
+
|
|
32
|
+
The `JalaliDate` object represents a date in the Jalali calendar.
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
>>> from persiantools.jdatetime import JalaliDate
|
|
36
|
+
>>> import datetime
|
|
37
|
+
|
|
38
|
+
# Today's date
|
|
39
|
+
>>> JalaliDate.today()
|
|
40
|
+
JalaliDate(1404, 3, 16, Jomeh)
|
|
41
|
+
|
|
42
|
+
>>> JalaliDate(1367, 2, 14)
|
|
43
|
+
JalaliDate(1367, 2, 14, Chaharshanbeh)
|
|
44
|
+
|
|
45
|
+
# Convert Gregorian to Jalali
|
|
46
|
+
>>> JalaliDate(datetime.date(1988, 5, 4))
|
|
47
|
+
JalaliDate(1367, 2, 14, Chaharshanbeh)
|
|
48
|
+
|
|
49
|
+
# Convert from Gregorian to Jalali using method
|
|
50
|
+
>>> JalaliDate.to_jalali(2013, 9, 16)
|
|
51
|
+
JalaliDate(1392, 6, 25, Doshanbeh)
|
|
52
|
+
|
|
53
|
+
# Convert from Jalali to Gregorian
|
|
54
|
+
>>> JalaliDate(1392, 6, 25).to_gregorian()
|
|
55
|
+
datetime.date(2013, 9, 16)
|
|
56
|
+
|
|
57
|
+
# From ISO format
|
|
58
|
+
>>> JalaliDate.fromisoformat('1404-01-01')
|
|
59
|
+
JalaliDate(1404, 1, 1, Jomeh)
|
|
60
|
+
|
|
61
|
+
# Create a Jalali date from a Unix timestamp
|
|
62
|
+
>>> JalaliDate.fromtimestamp(578707200)
|
|
63
|
+
JalaliDate(1367, 2, 14, Chaharshanbeh)
|
|
64
|
+
|
|
65
|
+
# ISO format output
|
|
66
|
+
>>> JalaliDate(1367, 2, 14).isoformat()
|
|
67
|
+
'1367-02-14'
|
|
68
|
+
|
|
69
|
+
# Replace date parts
|
|
70
|
+
>>> JalaliDate(1400, 1, 1).replace(month=2, day=10)
|
|
71
|
+
JalaliDate(1400, 2, 10, Jomeh)
|
|
72
|
+
```
|
|
73
|
+
#### Attributes and Methods
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
>>> date_obj = JalaliDate(1367, 2, 14)
|
|
77
|
+
|
|
78
|
+
>>> date_obj.year
|
|
79
|
+
1367
|
|
80
|
+
>>> date_obj.month
|
|
81
|
+
2
|
|
82
|
+
>>> date_obj.day
|
|
83
|
+
14
|
|
84
|
+
|
|
85
|
+
# Weekday (Saturday is 0 and Friday is 6)
|
|
86
|
+
>>> date_obj.weekday() # 1367/2/14 is Chaharshanbeh (Wednesday)
|
|
87
|
+
4
|
|
88
|
+
|
|
89
|
+
# ISO Weekday (Monday is 1 and Sunday is 7)
|
|
90
|
+
>>> date_obj.isoweekday()
|
|
91
|
+
5
|
|
92
|
+
|
|
93
|
+
>>> date_obj.week_of_year()
|
|
94
|
+
7
|
|
95
|
+
|
|
96
|
+
# ISO Calendar (ISO year, ISO week number, ISO weekday)
|
|
97
|
+
>>> date_obj.isocalendar()
|
|
98
|
+
(1367, 7, 5)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Datetime Operations
|
|
102
|
+
|
|
103
|
+
The `JalaliDateTime` object represents a date and time in the Jalali calendar.
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
>>> from persiantools.jdatetime import JalaliDateTime
|
|
107
|
+
>>> import datetime, pytz
|
|
108
|
+
|
|
109
|
+
# Current Jalali datetime
|
|
110
|
+
>>> JalaliDateTime.now()
|
|
111
|
+
JalaliDateTime(1404, 3, 16, 2, 17, 14, 907909)
|
|
112
|
+
|
|
113
|
+
# Current Jalali datetime (timezone-aware)
|
|
114
|
+
>>> JalaliDateTime.now(pytz.timezone("Asia/Tehran"))
|
|
115
|
+
JalaliDateTime(1404, 3, 16, 2, 17, 14, 907909, tzinfo=<DstTzInfo 'Asia/Tehran' +0330+3:30:00 STD>)
|
|
116
|
+
|
|
117
|
+
# Current UTC Jalali datetime
|
|
118
|
+
>>> JalaliDateTime.utcnow()
|
|
119
|
+
JalaliDateTime(1404, 3, 15, 22, 56, 49, 892339, tzinfo=datetime.timezone.utc)
|
|
120
|
+
|
|
121
|
+
# Convert Jalali datetime to Gregorian
|
|
122
|
+
>>> JalaliDateTime.now().to_gregorian()
|
|
123
|
+
datetime.datetime(2025, 6, 6, 2, 17, 14, 907909)
|
|
124
|
+
|
|
125
|
+
# Convert Gregorian datetime to Jalali (From a datetime.datetime object)
|
|
126
|
+
>>> dt_gregorian = datetime.datetime(1988, 5, 4, 14, 30, 15)
|
|
127
|
+
>>> JalaliDateTime(dt_gregorian)
|
|
128
|
+
JalaliDateTime(1367, 2, 14, 14, 30, 15)
|
|
129
|
+
|
|
130
|
+
# Replace datetime parts
|
|
131
|
+
>>> JalaliDateTime(1400, 1, 1, 12, 0, 0).replace(hour=15, minute=30, microsecond=10)
|
|
132
|
+
JalaliDateTime(1400, 1, 1, 15, 30, 0, 10)
|
|
133
|
+
|
|
134
|
+
# Timezone conversion
|
|
135
|
+
>>> tehran_tz = pytz.timezone("Asia/Tehran")
|
|
136
|
+
>>> utc_tz = pytz.utc
|
|
137
|
+
>>> dt_utc = JalaliDateTime.now(utc_tz)
|
|
138
|
+
>>> dt_tehran = dt_utc.astimezone(tehran_tz)
|
|
139
|
+
>>> dt_utc
|
|
140
|
+
JalaliDateTime(1404, 3, 15, 22, 54, 8, 835877, tzinfo=<UTC>)
|
|
141
|
+
>>> dt_tehran
|
|
142
|
+
JalaliDateTime(1404, 3, 16, 2, 24, 8, 835877, tzinfo=<DstTzInfo 'Asia/Tehran' +0330+3:30:00 STD>)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
#### Attributes and Methods
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
>>> dt_obj = JalaliDateTime(1367, 2, 14, 14, 30, 15, 123, tzinfo=pytz.utc)
|
|
149
|
+
|
|
150
|
+
>>> dt_obj.year
|
|
151
|
+
1367
|
|
152
|
+
>>> dt_obj.month
|
|
153
|
+
2
|
|
154
|
+
>>> dt_obj.day
|
|
155
|
+
14
|
|
156
|
+
>>> dt_obj.hour
|
|
157
|
+
14
|
|
158
|
+
>>> dt_obj.minute
|
|
159
|
+
30
|
|
160
|
+
>>> dt_obj.second
|
|
161
|
+
15
|
|
162
|
+
>>> dt_obj.microsecond
|
|
163
|
+
123
|
|
164
|
+
>>> dt_obj.tzinfo
|
|
165
|
+
<UTC>
|
|
166
|
+
|
|
167
|
+
# Date part as datetime.date (Gregorian)
|
|
168
|
+
>>> dt_obj.date()
|
|
169
|
+
datetime.date(1988, 5, 4)
|
|
170
|
+
|
|
171
|
+
# JalaliDate object
|
|
172
|
+
>>> dt_obj.jdate()
|
|
173
|
+
JalaliDate(1367, 2, 14, Chaharshanbeh)
|
|
174
|
+
|
|
175
|
+
# Time part as datetime.time
|
|
176
|
+
>>> dt_obj.time()
|
|
177
|
+
datetime.time(14, 30, 15, 123)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Formatting
|
|
181
|
+
|
|
182
|
+
Based on python `strftime()` behavior
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
>>> from persiantools.jdatetime import JalaliDateTime
|
|
186
|
+
>>> import pytz
|
|
187
|
+
|
|
188
|
+
>>> dt = JalaliDateTime(1367, 2, 14, 14, 30, 0, tzinfo=pytz.timezone("Asia/Tehran"))
|
|
189
|
+
|
|
190
|
+
>>> dt.strftime("%Y/%m/%d %H:%M:%S")
|
|
191
|
+
'1367/02/14 14:30:00'
|
|
192
|
+
|
|
193
|
+
>>> dt.strftime("%c", locale='fa')
|
|
194
|
+
'چهارشنبه ۱۴ اردیبهشت ۱۳۶۷ ۱۴:۳۰:۰۰'
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Digits and Character Conversion
|
|
198
|
+
|
|
199
|
+
This section covers converting between different numeral systems (Persian, Arabic, English) and converting numbers to their Persian word representations. It also includes utilities for converting between Persian and Arabic characters.
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
>>> from persiantools import digits
|
|
203
|
+
|
|
204
|
+
# Convert English digits to Persian
|
|
205
|
+
>>> digits.en_to_fa("0987654321")
|
|
206
|
+
'۰۹۸۷۶۵۴۳۲۱'
|
|
207
|
+
|
|
208
|
+
# Convert Arabic digits to Persian
|
|
209
|
+
>>> digits.ar_to_fa("٠٩٨٧٦٥٤٣٢١")
|
|
210
|
+
'۰۹۸۷۶۵۴۳۲۱'
|
|
211
|
+
|
|
212
|
+
# Convert Persian digits to English
|
|
213
|
+
>>> digits.fa_to_en("۰۹۸۷۶۵۴۳۲۱")
|
|
214
|
+
'0987654321'
|
|
215
|
+
|
|
216
|
+
# Convert Persian digits to Arabic
|
|
217
|
+
>>> digits.fa_to_ar("۰۹۸۷۶۵۴۳۲۱")
|
|
218
|
+
'٠٩٨٧٦٥٤٣٢١'
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### Numbers to Words
|
|
222
|
+
|
|
223
|
+
Convert numerical values (integers and floats) into Persian words.
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
>>> from persiantools import digits
|
|
227
|
+
|
|
228
|
+
>>> digits.to_word(9512026)
|
|
229
|
+
'نه میلیون و پانصد و دوازده هزار و بیست و شش'
|
|
230
|
+
|
|
231
|
+
>>> digits.to_word(15.007)
|
|
232
|
+
'پانزده و هفت هزارم'
|
|
233
|
+
|
|
234
|
+
>>> digits.to_word(-123.45)
|
|
235
|
+
'منفی یکصد و بیست و سه و چهل و پنج صدم'
|
|
236
|
+
|
|
237
|
+
>>> digits.to_word(0)
|
|
238
|
+
'صفر'
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
#### Character Conversion
|
|
242
|
+
|
|
243
|
+
Functions for converting specific Arabic characters to their Persian equivalents and vice-versa. This is often needed due to differences in the Unicode representation of similar-looking characters (e.g., `ک` vs `ك`, `ی` vs `ي`).
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
>>> from persiantools import characters
|
|
247
|
+
|
|
248
|
+
>>> characters.ar_to_fa("كيك") # Input uses Arabic Kaf (U+0643) and Yeh (U+064A)
|
|
249
|
+
'کیک' # Output uses Persian Keh (U+06A9) and Yeh (U+06CC)
|
|
250
|
+
|
|
251
|
+
>>> characters.fa_to_ar("کیک")
|
|
252
|
+
'كيك'
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Operators
|
|
256
|
+
|
|
257
|
+
Both `JalaliDate` and `JalaliDateTime` objects support standard comparison operators (`<`, `<=`, `==`, `!=`, `>`, `>=`) and arithmetic operations (`+`, `-` with `datetime.timedelta` objects). They can also be compared with their Gregorian counterparts (`datetime.date` and `datetime.datetime`).
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
>>> from persiantools.jdatetime import JalaliDate, JalaliDateTime
|
|
261
|
+
>>> import datetime
|
|
262
|
+
|
|
263
|
+
>>> JalaliDate(1367, 2, 14) == JalaliDate(datetime.date(1988, 5, 4))
|
|
264
|
+
True
|
|
265
|
+
|
|
266
|
+
>>> JalaliDateTime(1367, 2, 14, 4, 30) >= JalaliDateTime(1368, 2, 14, 1, 0)
|
|
267
|
+
False
|
|
268
|
+
|
|
269
|
+
>>> JalaliDate(1367, 2, 14) == datetime.date(1988, 5, 4)
|
|
270
|
+
True
|
|
271
|
+
|
|
272
|
+
>>> JalaliDate(1395, 2, 14) + datetime.timedelta(days=38)
|
|
273
|
+
JalaliDate(1395, 3, 21, Jomeh)
|
|
274
|
+
|
|
275
|
+
>>> JalaliDateTime(1395, 12, 30) - JalaliDateTime(1395, 1, 1)
|
|
276
|
+
datetime.timedelta(365)
|
|
277
|
+
|
|
278
|
+
>>> JalaliDateTime(1395, 2, 14, 12, 0, 0) + datetime.timedelta(hours=5, minutes=30)
|
|
279
|
+
JalaliDateTime(1395, 2, 14, 17, 30)
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Serializing and Deserializing
|
|
283
|
+
|
|
284
|
+
`JalaliDate` and `JalaliDateTime` objects can be serialized (pickled) and deserialized (unpickled) using Python's standard `pickle` module. This allows for storing these objects or transmitting them.
|
|
285
|
+
|
|
286
|
+
```python
|
|
287
|
+
>>> from persiantools.jdatetime import JalaliDate
|
|
288
|
+
>>> import pickle
|
|
289
|
+
|
|
290
|
+
# Serialize a Jalali date to a file
|
|
291
|
+
>>> with open("save.p", "wb") as file:
|
|
292
|
+
>>> pickle.dump(JalaliDate(1367, 2, 14), file)
|
|
293
|
+
|
|
294
|
+
# Deserialize from a file
|
|
295
|
+
>>> with open("save.p", "rb") as file:
|
|
296
|
+
>>> jalali = pickle.load(file)
|
|
297
|
+
>>> jalali
|
|
298
|
+
JalaliDate(1367, 2, 14, Chaharshanbeh)
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Support This Project
|
|
302
|
+
If you find this project helpful and would like to support its continued development, please consider donating.
|
|
303
|
+
|
|
304
|
+
* **Bitcoin (BTC):** `bc1qg5rp7ymznc98wmhltzvpwl2dvfuvjr33m4hy77`
|
|
305
|
+
* **Tron (TRX):** `TDd63bVWZDBHmwVNFgJ6T2WdWmk9z7PBLg`
|
|
306
|
+
* **Stellar (XLM):** `GDSFPPLY34QSAOTOP4DQDXAI2YDRNRIADZHTN3HCGMQXRLIGPYOEH7L5`
|
|
307
|
+
* **Solana (SOL):** `CXHKgCBqBYy1hbZKGqaSmMzQoTC4Wx2v8QfL9Z7JBo3A`
|
|
308
|
+
* **Dogecoin (DOGE):** `DRZ2QLuXfa5vV1AG83K3XHfYXAHj9b4h4V`
|