Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 21 additions & 34 deletions jdatetime/jalali.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,45 +25,40 @@ def __gregorianToJalali(self):
g_m: gregorian month
g_d: gregorian day
"""
global g_days_in_month, j_days_in_month

gy = self.gyear - 1600
gm = self.gmonth - 1
gd = self.gday - 1

g_day_no = 365 * gy + (gy + 3) // 4 - (gy + 99) // 100 + (gy + 399) // 400
j_day_no = (
365 * gy + (gy + 3) // 4 - (gy + 99) // 100
+ (gy + 399) // 400 + self.gday - 1 - 79
)

for i in range(gm):
g_day_no += g_days_in_month[i]
j_day_no += g_days_in_month[i]
if gm > 1 and ((gy % 4 == 0 and gy % 100 != 0) or (gy % 400 == 0)):
# leap and after Feb
g_day_no += 1
g_day_no += gd

j_day_no = g_day_no - 79
j_day_no += 1

j_np = j_day_no // 12053
j_day_no %= 12053
jy = 979 + 33 * j_np + 4 * int(j_day_no // 1461)
jy = 979 + 33 * j_np + 4 * (j_day_no // 1461)

j_day_no %= 1461

if j_day_no >= 366:
jy += (j_day_no - 1) // 365
j_day_no = (j_day_no - 1) % 365
j_day_no -= 1
jy += j_day_no // 365
j_day_no %= 365

for i in range(11):
if not j_day_no >= j_days_in_month[i]:
i -= 1
break
j_day_no -= j_days_in_month[i]

jm = i + 2
jd = j_day_no + 1

self.jyear = jy
self.jmonth = jm
self.jday = jd
self.jmonth = i + 2
self.jday = j_day_no + 1


class JalaliToGregorian:
Expand All @@ -80,41 +75,33 @@ def getGregorianList(self):
return (self.gyear, self.gmonth, self.gday)

def __jalaliToGregorian(self):
global g_days_in_month, j_days_in_month
jy = self.jyear - 979
jm = self.jmonth - 1
jd = self.jday - 1

j_day_no = 365 * jy + int(jy // 33) * 8 + (jy % 33 + 3) // 4
for i in range(jm):
j_day_no += j_days_in_month[i]

j_day_no += jd

g_day_no = j_day_no + 79
g_day_no = 365 * jy + (jy // 33) * 8 + (jy % 33 + 3) // 4 + self.jday - 1 + 79
for i in range(self.jmonth - 1):
g_day_no += j_days_in_month[i]

gy = 1600 + 400 * int(g_day_no // 146097) # 146097 = 365*400 + 400/4 - 400/100 + 400/400
g_day_no = g_day_no % 146097
gy = 1600 + 400 * (g_day_no // 146097) # 146097 = 365*400 + 400/4 - 400/100 + 400/400
g_day_no %= 146097

leap = 1
if g_day_no >= 36525: # 36525 = 365*100 + 100/4
g_day_no -= 1
gy += 100 * int(g_day_no // 36524) # 36524 = 365*100 + 100/4 - 100/100
g_day_no = g_day_no % 36524
gy += 100 * (g_day_no // 36524) # 36524 = 365*100 + 100/4 - 100/100
g_day_no %= 36524

if g_day_no >= 365:
g_day_no += 1
else:
leap = 0

gy += 4 * int(g_day_no // 1461) # 1461 = 365*4 + 4/4
gy += 4 * (g_day_no // 1461) # 1461 = 365*4 + 4/4
g_day_no %= 1461

if g_day_no >= 366:
leap = 0
g_day_no -= 1
gy += g_day_no // 365
g_day_no = g_day_no % 365
g_day_no %= 365

i = 0
while g_day_no >= g_days_in_month[i] + (i == 1 and leap):
Expand Down
14 changes: 14 additions & 0 deletions tests/test_jdate.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ def test_fromgregorian_accepts_locale_keyword_arg_when_int_passed(self):
j_today = jdatetime.date.fromgregorian(day=15, month=7, year=2018, locale='nl_NL')
self.assertEqual(j_today.locale, 'nl_NL')

def test_togregorian_leap(self):
self.assertEqual(
jdatetime.date(1402, 12, 9).togregorian(),
datetime.date(2024, 2, 28),
)
self.assertEqual(
jdatetime.date(1402, 12, 10).togregorian(),
datetime.date(2024, 2, 29),
)
self.assertEqual(
jdatetime.date(1402, 12, 11).togregorian(),
datetime.date(2024, 3, 1),
)

def test_replace_keeps_the_locale_of_source_date(self):
date = jdatetime.date(1397, 4, 22, locale='nl_NL')
other_date = date.replace(day=20)
Expand Down