# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr from math import trunc from .utils import ceil, jwday, monthcalendarhelper from . import gregorian EPOCH = 1948320.5 WEEKDAYS = ("Doshanbeh", "Seshhanbeh", "Chaharshanbeh", "Panjshanbeh", "Jomeh", "Shanbeh", "Yekshanbeh") HAS_31_DAYS = (1, 2, 3, 4, 5, 6) HAS_30_DAYS = (7, 8, 9, 10, 11) def leap(year): '''Is a given year a leap year in the Persian calendar ?''' if year > 0: y = 474 else: y = 473 return ((((((year - y % 2820) + 474) + 38) * 682) % 2816) < 682) def to_jd(year, month, day): '''Determine Julian day from Persian date''' if year >= 0: y = 474 else: y = 473 epbase = year - y epyear = 474 + (epbase % 2820) if month <= 7: m = (month - 1) * 31 else: m = (month - 1) * 30 + 6 return day + m + trunc(((epyear * 682) - 110) / 2816) + (epyear - 1) * 365 + trunc(epbase / 2820) * 1029983 + (EPOCH - 1) def from_jd(jd): '''Calculate Persian date from Julian day''' jd = trunc(jd) + 0.5 depoch = jd - to_jd(475, 1, 1) cycle = trunc(depoch / 1029983) cyear = (depoch % 1029983) if cyear == 1029982: ycycle = 2820 else: aux1 = trunc(cyear / 366) aux2 = cyear % 366 ycycle = trunc(((2134 * aux1) + (2816 * aux2) + 2815) / 1028522) + aux1 + 1 year = ycycle + (2820 * cycle) + 474 if (year <= 0): year -= 1 yday = (jd - to_jd(year, 1, 1)) + 1 if yday <= 186: month = ceil(yday / 31) else: month = ceil((yday - 6) / 30) day = int(jd - to_jd(year, month, 1)) + 1 return (year, month, day) def from_gregorian(year, month, day): return from_jd(gregorian.to_jd(year, month, day)) def to_gregorian(year, month, day): return gregorian.from_jd(to_jd(year, month, day)) def month_length(year, month): if month in HAS_30_DAYS or (month == 12 and leap(year)): return 30 elif month in HAS_31_DAYS: return 31 return 29 def monthcalendar(year, month): start_weekday = jwday(to_jd(year, month, 1)) monthlen = month_length(year, month) return monthcalendarhelper(start_weekday, monthlen)