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