slashmili / python-jalali

Jalali calendar binding for Python based on Python's datetime module
http://pypi.python.org/pypi/jdatetime/
Other
335 stars 46 forks source link

The problem of 2124/03/20 #152

Closed eshahrvand closed 3 months ago

eshahrvand commented 3 months ago

Please include your runtime information

Problem: The Gregorian date 2124/03/20 must be 1503/01/01 in the Jalali calendar but this lib returns 1502/12/30.

Checks: The Gregorian date 2025/03/20 must be 1403/12/30 in the Jalali calendar which currently is correct but must be rechecked after fixing the reported problem.

slashmili commented 3 months ago

Thanks for reporting the issue!

>>> import jdatetime
>>> import datetime
>>> date = datetime.date(2124, 3, 20)
>>> jdatetime.date.fromgregorian(date=date)
jdatetime.date(1502, 12, 30)

Just part of the technicality, we are in a process of separating the date conversion to another package jalali-core I'll create another issue on jalali-core as well.

slashmili commented 3 months ago

So it's hard for me to know the real date in far future, I tried it on time.ir and return the same result. It could be that both are wrong!

Screenshot 2024-03-25 at 14 22 05

However if I try using jcal:

jdate --jalali=2124/03/20
Dos Far 01 00:00:00 CET 1503
roozbehp commented 3 months ago

jcal seems to be using the 2820-year cycle which should return incorrect results for as soon as the end of 1403 AP (this year). What does it return for 2025-03-20?

slashmili commented 3 months ago

Thanks @roozbehp for looking into that, you are correct:

so this lib returns:

>>> date = datetime.date(2025, 3, 20)
>>> jdatetime.date.fromgregorian(date=date)
jdatetime.date(1403, 12, 30)

and jcal:

date --jalali=2025/03/20
Pan Far 01 00:00:00 CET 1404

@eshahrvand what was your rationale behind thinking that 2124-03-20 must be 1503-01-01 in the Hejri Shamis calendar?

roozbehp commented 3 months ago

what was your rationale behind thinking that 2124-03-20 must be 1503-01-01 in the Hejri Shamis calendar?

That would be my tweet here (check the thread): https://twitter.com/roozbehp/status/1771093304450416797

If you want actual astronomical calculations, here is the Python code to do that, which returns the best known estimate of the actual Persian calendar used in Iran. It's not written for production environments though, which makes it relatively slow: https://github.com/roozbehp/persiancalendar

I have some long term plans to convert the output of this code to tables and implement a fast version usable in production, but I don't have any estimates for when that might happen.

roozbehp commented 3 months ago

(Edited my comment above. I had misunderstood the question originally.)

roozbehp commented 3 months ago

I have just implemented a fast Python version that works correctly from 1187 to 3000 AP (Hejri Shamsi). You can probably replace jalali-core with it easily. Here's the code (licensed under Apache 2.0 license, which is much less restrictive than LGPL): https://github.com/roozbehp/persiancalendar/blob/main/persiancalendar_fast.py

If you want to convert between Gregorian and Persian calendars, you can copy the methods fixed_from_gregorian() and gregorian_from_fixed() from persiancalendar.py in the same project, but you can avoid all that hassle by using Python's datetime.date.toordinal() and datetime.date.fromordinal() instead.

I can help in adapting the code and reviewing changes.

5j9 commented 3 months ago

In case anyone else is curious, I did some performance comparisons on a minorly modified version of persiancalendar and my results were as follows:

P.S.

roozbehp commented 3 months ago

Thanks. I've definitely not tried to optimize the code for speed yet. It's mostly optimized for readability. There are many speed optimizations I can think of. The name "fast" is chosen for comparison to the astronomical implementation, which is quite slow.

slashmili commented 3 months ago

I'll close this ticket and continue discussing persiancalendar_fast in jalali-core repo

@eshahrvand since I have not received any feedback from I'll close this ticket.