1# -*- coding: utf-8 -*- 2 3# This file is part of convertdate. 4# http://github.com/fitnr/convertdate 5 6# Licensed under the MIT license: 7# http://opensource.org/licenses/MIT 8# Copyright (c) 2016, fitnr <fitnr@fakeisthenewreal> 9from math import trunc 10from .utils import ceil, jwday, monthcalendarhelper 11from . import gregorian 12 13EPOCH = 1948439.5 14WEEKDAYS = ("al-'ahad", "al-'ithnayn", 15 "ath-thalatha'", "al-'arb`a'", 16 "al-khamis", "al-jum`a", "as-sabt") 17 18HAS_29_DAYS = (2, 4, 6, 8, 10) 19HAS_30_DAYS = (1, 3, 5, 7, 9, 11) 20 21 22def leap(year): 23 '''Is a given year a leap year in the Islamic calendar''' 24 return (((year * 11) + 14) % 30) < 11 25 26 27def to_jd(year, month, day): 28 '''Determine Julian day count from Islamic date''' 29 return (day + ceil(29.5 * (month - 1)) + (year - 1) * 354 + trunc((3 + (11 * year)) / 30) + EPOCH) - 1 30 31 32def from_jd(jd): 33 '''Calculate Islamic date from Julian day''' 34 35 jd = trunc(jd) + 0.5 36 year = trunc(((30 * (jd - EPOCH)) + 10646) / 10631) 37 month = min(12, ceil((jd - (29 + to_jd(year, 1, 1))) / 29.5) + 1) 38 day = int(jd - to_jd(year, month, 1)) + 1 39 return (year, month, day) 40 41 42def from_gregorian(year, month, day): 43 return from_jd(gregorian.to_jd(year, month, day)) 44 45 46def to_gregorian(year, month, day): 47 return gregorian.from_jd(to_jd(year, month, day)) 48 49 50def month_length(year, month): 51 if month in HAS_30_DAYS or (month == 12 and leap(year)): 52 return 30 53 54 return 29 55 56 57def monthcalendar(year, month): 58 start_weekday = jwday(to_jd(year, month, 1)) 59 monthlen = month_length(year, month) 60 return monthcalendarhelper(start_weekday, monthlen) 61