Metadata-Version: 2.4
Name: omani-hijri
Version: 0.1.0
Summary: Omani Hijri Calendar - التقويم الهجري العماني - Accurate Gregorian to Omani Hijri date conversion using astronomical crescent visibility criteria
Author: Omani Hijri Project
License: MIT
Project-URL: Homepage, https://github.com/omani-hijri/omani-hijri
Project-URL: Documentation, https://github.com/omani-hijri/omani-hijri#readme
Project-URL: Repository, https://github.com/omani-hijri/omani-hijri
Project-URL: Issues, https://github.com/omani-hijri/omani-hijri/issues
Keywords: hijri,omani,oman,islamic-calendar,hilal,crescent,moon-sighting,lunar-calendar,astronomical,هلال,هجري,عماني,تقويم,التقويم الهجري,عمان
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Astronomy
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: skyfield>=1.49
Provides-Extra: api
Requires-Dist: fastapi>=0.110; extra == "api"
Requires-Dist: uvicorn[standard]>=0.29; extra == "api"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Requires-Dist: ruff>=0.4; extra == "dev"
Requires-Dist: mypy>=1.10; extra == "dev"
Dynamic: license-file

<div dir="rtl" align="right">

# omani-hijri — التقويم الهجري العماني

**مكتبة دقيقة لتحويل التاريخ الميلادي إلى التاريخ الهجري العماني باستخدام معايير الرؤية الفلكية للهلال.**

[![Python Versions](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)](https://pypi.org/project/omani-hijri/)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
[![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
[![Checked with mypy](https://img.shields.io/badge/mypy-checked-blue)](https://mypy.readthedocs.io/en/stable/)

`omani-hijri` هي مكتبة بايثون وواجهة برمجة تطبيقات (REST API) صُممت خصيصاً لـ **سلطنة عمان**. على عكس محولات التاريخ الهجري القياسية التي تعتمد على تقويم أم القرى السعودي المجدول (والذي قد يختلف بمقدار يوم أو يومين في عُمان)، تستخدم هذه المكتبة المحرك الفلكي **Skyfield** لتقييم المعايير الفلكية الأربعة الدقيقة لرؤية الهلال والمعتمدة من قبل وزارة الأوقاف والشؤون الدينية (MARA).

## المميزات

- **المحرك الفلكي:** تقييم عالي الدقة لأوقات غروب الشمس، وغروب القمر، والاقتران، والاستطالة باستخدام بيانات التقويم الفلكي من وكالة ناسا (NASA JPL).
- **معايير سلطنة عمان الأربعة:** حساب أطوال الأشهر بناءً على الاقتران، وعمر القمر (15 ساعة)، والاستطالة (7.5 درجات)، والمكث (20 دقيقة).
- **نظام التعديلات الرسمية:** آلية مدمجة بتنسيق JSON لتصحيح التواريخ يدويًا عندما تختلف الإعلانات الرسمية للوزارة عن التوقعات الفلكية (مثلاً بسبب الغيوم). مزودة مسبقاً بالتواريخ التاريخية.
- **تحويل ثنائي الاتجاه:** تحويل التاريخ الميلادي إلى هجري، والهجري إلى ميلادي.
- **الأحداث الإسلامية:** الإشارة تلقائياً للتواريخ بالأحداث البارزة (العيد، رمضان، إلخ).
- **مقارنات غنية:** يدعم العمليات الحسابية للتواريخ والمقارنات الغنية (`<`, `>`, `==`).
- **واجهة REST API مرفقة:** خادم FastAPI خلفي جاهز للاستخدام كتبعية اختيارية (`[api]`).

## لماذا لا نستخدم `hijridate`؟
تطبق مكتبة `hijridate` الشهيرة تقويم أم القرى السعودي. ورغم كونها ممتازة، إلا أن تقويم أم القرى يُحسب بشكل مجدول وقد يختلف بمقدار يوم أو يومين عن التقويم العماني الرسمي، الذي يعتمد على معايير الرؤية الفعلية للهلال. مكتبة `omani-hijri` تحاكي تحديداً المعايير المستخدمة في وزارة الأوقاف والشؤون الدينية العمانية.

---

## 🚀 البدء السريع (مكتبة بايثون)

### التثبيت

<div dir="ltr" align="left">

```bash
pip install omani-hijri

# إذا كنت ترغب أيضاً في استخدام واجهة REST API:
pip install "omani-hijri[api]"
```

</div>

### الاستخدام الأساسي

<div dir="ltr" align="left">

```python
from datetime import date, timedelta
from omani_hijri import get_omani_hijri_date, get_gregorian_date

# 1. تحويل التاريخ الميلادي إلى الهجري العماني
hijri_date = get_omani_hijri_date(date(2024, 7, 7))

print(hijri_date)
# المخرجات: 1 Muharram 1446 AH (2024-07-07)

print(f"Day: {hijri_date.day}, Month: {hijri_date.month_name_ar}")
print(f"Events: {hijri_date.to_dict()['events']}") # ['Islamic New Year']

# 2. تحويل التاريخ الهجري العماني إلى الميلادي
greg_date = get_gregorian_date(hijri_year=1446, hijri_month=9, hijri_day=1)
print(greg_date) # 2025-03-01

# 3. العمليات الحسابية والمقارنات
tomorrow = hijri_date + timedelta(days=1)
print(tomorrow > hijri_date) # True
```

</div>

---

## 🌐 البدء السريع (خادم FastAPI REST)

بدء تشغيل خادم API المدمج:

<div dir="ltr" align="left">

```bash
python run_api.py
```

</div>

### نقاط النهاية (API Endpoints)

| المسار (Endpoint) | الطريقة (Method) | مثال |
|--------|----------|---------|
| `GET` | `/api/v1/hijri?date=YYYY-MM-DD` | تحويل تاريخ محدد |
| `GET` | `/api/v1/gregorian?year=Y&month=M&day=D` | تحويل التاريخ الهجري إلى ميلادي |
| `GET` | `/api/v1/hijri/today` | الحصول على تاريخ اليوم الهجري |
| `GET` | `/api/v1/hijri/month?year=1446&month=1` | الحصول على تقويم شهر كامل |
| `GET` | `/api/v1/overrides` | عرض التعديلات الرسمية |
| `POST` | `/api/v1/overrides` | إضافة تعديل (يتطلب مفتاح API) |

### مثال لطلب API

<div dir="ltr" align="left">

```bash
curl "http://localhost:8000/api/v1/hijri?date=2024-07-06&details=true"
```

```json
{
  "status": "success",
  "data": {
    "gregorian": {
      "date": "2024-07-06",
      "day": 6,
      "month": 7,
      "year": 2024,
      "day_name": "Saturday"
    },
    "hijri": {
      "date": "30-12-1445",
      "day": 30,
      "month": 12,
      "year": 1445,
      "month_name_en": "Dhul Hijjah",
      "month_name_ar": "ذو الحجة",
      "month_length": 30,
      "source": "astronomical_calculation"
    },
    "astronomical_details": {
      "moon_age_hours": 16.0,
      "elongation_degrees": 8.5,
      "lag_minutes": 42.7,
      "all_criteria_met": true
    }
  }
}
```

</div>

---

## 🔭 كيف تعمل المكتبة (المعايير الأربعة)

يعتمد البداية الرسمية لشهر هجري جديد في عُمان على الرؤية الفعلية للهلال. تحسب هذه المكتبة الاحتمالية الفلكية للرؤية عند غروب الشمس في **مسقط** في اليوم التاسع والعشرين من الشهر الحالي.

لكي يُعتبر الهلال مرئياً، يجب أن تتحقق **جميع** المعايير الأربعة التالية:

1. **الاقتران (Conjunction):** يجب أن يحدث القمر الجديد الفلكي *قبل* غروب الشمس.
2. **عمر القمر (Moon Age):** يجب أن يكون الوقت المنقضي من الاقتران حتى غروب الشمس **≥ 15.0 ساعة**.
3. **الاستطالة (Elongation):** يجب أن يكون الانفصال الزاوي بين الشمس والقمر **≥ 7.5 درجة**.
4. **المكث (Lag Time):** يجب أن يغيب القمر **≥ 20 دقيقة** بعد غروب الشمس.

إذا تحققت جميع المعايير، ينتهي الشهر الحالي عند 29 يوماً. وإذا لم يتحقق أي منها، يكمل الشهر 30 يوماً.

---

## 🛠️ إدارة التعديلات الرسمية (Overrides)

في بعض الأحيان، حتى لو أشار الحساب الفلكي إلى أن الهلال *يجب* أن يكون مرئياً، فقد تمنع الظروف الجوية الغائمة اللجنة الرسمية من رؤيته. في عُمان، الإعلان الرسمي من وزارة الأوقاف هو المرجعية النهائية.

تتضمن هذه المكتبة **نظام تعديلات** (Overrides) للتعامل مع هذا الأمر.

### متى يتم إضافة تعديل
إذا أعلنت الوزارة تاريخاً يختلف عن حساب المكتبة، يمكنك (كمطور) إضافة إدخال واحد إلى ملف `overrides.json`. ستبدأ المكتبة على الفور في استخدام هذا التاريخ الرسمي.

### كيفية إضافة تعديل

**عبر بايثون:**

<div dir="ltr" align="left">

```python
from datetime import date
from omani_hijri.overrides import add_override

add_override(
    hijri_year=1445,
    hijri_month=9,
    month_name_en="Ramadan",
    official_start_gregorian=date(2024, 3, 12),
    month_length=30,
    reason="Crescent not sighted due to clouds",
    source="MARA announcement"
)
```

</div>

**عبر API:**

<div dir="ltr" align="left">

```bash
curl -X POST "http://localhost:8000/api/v1/overrides" \
     -H "Content-Type: application/json" \
     -H "X-API-Key: your_api_key_here" \
     -d '{
           "hijri_year": 1445,
           "hijri_month": 9,
           "month_name_en": "Ramadan",
           "official_start_gregorian": "2024-03-12",
           "month_length": 30
         }'
```

</div>

---

## 🤝 المساهمة

المساهمات مرحب بها! إذا لاحظت أن إعلاناً رسمياً من وزارة الأوقاف يختلف عن حساب المكتبة، يرجى فتح issue أو تقديم pull request لإضافة التعديل إلى `data/overrides.json`.

يرجى الاطلاع على [CONTRIBUTING.md](CONTRIBUTING.md) لمزيد من التفاصيل.

---

## 📝 الترخيص

هذا المشروع مرخص بموجب ترخيص MIT - انظر ملف LICENSE لمزيد من التفاصيل.

</div>

<br><br><hr><br><br>

<div dir="ltr" align="left">

# omani-hijri — التقويم الهجري العماني

**Accurate Gregorian to Omani Hijri date conversion using astronomical crescent visibility criteria.**

[![Python Versions](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)](https://pypi.org/project/omani-hijri/)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
[![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
[![Checked with mypy](https://img.shields.io/badge/mypy-checked-blue)](https://mypy.readthedocs.io/en/stable/)

`omani-hijri` is a Python library and REST API specifically built for the **Sultanate of Oman**. Unlike standard Hijri converters that rely on the Saudi Umm al-Qura tabular calendar (which can be off by 1-2 days in Oman), this library uses the **Skyfield** astronomical engine to evaluate the exact four crescent visibility criteria used by the Ministry of Awqaf and Religious Affairs (MARA).

## Features

- **Astronomical Engine:** High-precision evaluation of sunset, moonset, conjunction, and elongation using NASA JPL ephemeris data.
- **Oman's 4 Criteria:** Calculates month lengths based on Conjunction, Moon Age (15h), Elongation (7.5°), and Lag Time (20m).
- **Official Overrides System:** Built-in JSON override mechanism to manually correct dates when official MARA announcements differ from astronomical predictions (e.g., due to cloud cover). Pre-seeded with historical dates.
- **Bidirectional Conversion:** Convert Gregorian to Hijri and Hijri to Gregorian.
- **Islamic Events:** Automatically tags dates with notable events (Eid, Ramadan, etc.).
- **Rich Comparisons:** Supports datetime-like arithmetic and rich comparisons (`<`, `>`, `==`).
- **REST API included:** Ready-to-use FastAPI backend as an optional dependency (`[api]`).

## Why not `hijridate`?
The popular `hijridate` library implements the Saudi Umm al-Qura calendar. While excellent, the Umm al-Qura calendar is calculated tabularly and can differ by 1-2 days from the official Omani calendar, which relies on actual physical moon sighting criteria. `omani-hijri` specifically models the criteria used by Oman's MARA.

---

## 🚀 Quick Start (Python Library)

### Installation

```bash
pip install omani-hijri

# If you also want the REST API:
pip install "omani-hijri[api]"
```

### Basic Usage

```python
from datetime import date, timedelta
from omani_hijri import get_omani_hijri_date, get_gregorian_date

# 1. Convert Gregorian to Omani Hijri
hijri_date = get_omani_hijri_date(date(2024, 7, 7))

print(hijri_date)
# Output: 1 Muharram 1446 AH (2024-07-07)

print(f"Day: {hijri_date.day}, Month: {hijri_date.month_name_ar}")
print(f"Events: {hijri_date.to_dict()['events']}") # ['Islamic New Year']

# 2. Convert Omani Hijri to Gregorian
greg_date = get_gregorian_date(hijri_year=1446, hijri_month=9, hijri_day=1)
print(greg_date) # 2025-03-01

# 3. Arithmetic and Comparisons
tomorrow = hijri_date + timedelta(days=1)
print(tomorrow > hijri_date) # True
```

---

## 🌐 Quick Start (FastAPI REST Server)

Start the built-in API server:

```bash
python run_api.py
```

### API Endpoints

| Method | Endpoint | Example |
|--------|----------|---------|
| `GET` | `/api/v1/hijri?date=YYYY-MM-DD` | Convert a specific date |
| `GET` | `/api/v1/gregorian?year=Y&month=M&day=D` | Convert Hijri to Gregorian |
| `GET` | `/api/v1/hijri/today` | Get today's Hijri date |
| `GET` | `/api/v1/hijri/month?year=1446&month=1` | Get full month calendar |
| `GET` | `/api/v1/overrides` | List official corrections |
| `POST` | `/api/v1/overrides` | Add correction (requires API Key) |

### Example API Request

```bash
curl "http://localhost:8000/api/v1/hijri?date=2024-07-06&details=true"
```

```json
{
  "status": "success",
  "data": {
    "gregorian": {
      "date": "2024-07-06",
      "day": 6,
      "month": 7,
      "year": 2024,
      "day_name": "Saturday"
    },
    "hijri": {
      "date": "30-12-1445",
      "day": 30,
      "month": 12,
      "year": 1445,
      "month_name_en": "Dhul Hijjah",
      "month_name_ar": "ذو الحجة",
      "month_length": 30,
      "source": "astronomical_calculation"
    },
    "astronomical_details": {
      "moon_age_hours": 16.0,
      "elongation_degrees": 8.5,
      "lag_minutes": 42.7,
      "all_criteria_met": true
    }
  }
}
```

---

## 🔭 How It Works (The 4 Criteria)

The official start of a new Hijri month in Oman relies on the actual sighting of the crescent moon (*Hilal*). This library calculates the astronomical probability of a sighting at sunset in **Muscat** on the 29th day of the current month.

For the moon to be considered visible, **all four** of the following criteria must be met:

1. **Conjunction:** The astronomical new moon must have occurred *before* sunset.
2. **Moon Age:** The time elapsed from conjunction to sunset must be **≥ 15.0 hours**.
3. **Elongation:** The angular separation between the Sun and Moon must be **≥ 7.5 degrees**.
4. **Lag Time:** The moon must set **≥ 20 minutes** after the sun sets.

If all criteria pass, the current month ends at 29 days. If any fail, the month completes 30 days.

---

## 🛠️ Managing Official Overrides

Sometimes, even if the astronomical calculation says the moon *should* be visible, cloudy weather may prevent the official committee from seeing it. In Oman, the official announcement from MARA is the final authority.

This library includes an **Override System** to handle this.

### When to add an override
If MARA announces a date that differs from the library's calculation, you (the developer) add one entry to the `overrides.json` file. The library will immediately start using this official date.

### How to add an override

**Via Python:**
```python
from datetime import date
from omani_hijri.overrides import add_override

add_override(
    hijri_year=1445,
    hijri_month=9,
    month_name_en="Ramadan",
    official_start_gregorian=date(2024, 3, 12),
    month_length=30,
    reason="Crescent not sighted due to clouds",
    source="MARA announcement"
)
```

**Via API:**
```bash
curl -X POST "http://localhost:8000/api/v1/overrides" \
     -H "Content-Type: application/json" \
     -H "X-API-Key: your_api_key_here" \
     -d '{
           "hijri_year": 1445,
           "hijri_month": 9,
           "month_name_en": "Ramadan",
           "official_start_gregorian": "2024-03-12",
           "month_length": 30
         }'
```

---

## 🤝 Contributing

Contributions are welcome! If you notice that an official MARA announcement differs from the library's calculation, please submit an issue or pull request to add the override to `data/overrides.json`. 

Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.

---

## 📝 License

This project is licensed under the MIT License - see the LICENSE file for details.

</div>
