You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
14 KiB
14 KiB
راهنمای جامع تقویم دابودبی و محاسبه اوقات شرعی
این مستند برای آشنایی همکاران فنی (مانند تیم فلاتر) و غیر فنی با سازوکار تقویم پروژه «امام جواد» و همچنین منطق محاسبه اوقات شرعی تهیه شده است. مطالب شامل معرفی ساختار دیتای تقویم، توضیح کامل API تنظیمات قمری (adjustemnts)، نحوه بهرهگیری در سناریوهای واقعی و نمونهکدهای کاربردی است.
نمای کلی سیستم تقویم
- ماژول:
apps/dobodbi_calendar - مدل اصلی:
CalendarOccasions- فیلدهای کلیدی:
titleعنوان مناسبت،occasion_typeنوع تاریخ (میلادی یا قمری)،datesلیست تاریخها،event_typeدستهبندی (ملی، مذهبی و ...)،is_yearlyتکرار سالانه، تایماستمپهایcreated_atوupdated_at.
- فیلدهای کلیدی:
- سریالایزر:
CalendarSerializerکه تاریخها را به ساختار قابل مصرف برای کلاینت تبدیل میکند و نوع مناسبت را در فیلدtypeقرار میدهد. - نمای لیستی:
CalendarListبا مسیر/api/calendar/occasions/که بدون صفحهبندی پاسخ میدهد و آخرین زمان بهروزرسانی را برمیگرداند تا همگامسازی کلاینت راحتتر انجام شود. - تنظیمات پویا: با استفاده از
dynamic_preferencesو کلیدcalendar__Adjustmentذخیره میشود. مقدار خام این تنظیمات در پایگاه داده نگهداری شده و از طریق پنل ادمین قابل ویرایش است.
API تنظیمات قمری (Adjustemnts)
- مسیر:
GET /api/calendar/adjustemnts/ - منبع داده: ترجمهٔ مقدار ذخیره شده در
dynamic_preferencesبرای کلیدcalendar__Adjustment. - کارکرد کلی: ارائهٔ سناریوهای از پیش تعریفشده برای تطبیق تقویم قمری با واقعیت رؤیت هلال یا تقویم رسمی کشورها.
ساختار پاسخ نمونه
[
{
"adjust": 0,
"current": 0,
"map": {
"1444": [354, 30, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 29],
"1445": [354, 30, 30, 30, 29, 30, 29, 29, 30, 29, 30, 29, 29],
"1446": [355, 30, 30, 30, 29, 30, 30, 29, 30, 29, 29, 29, 30],
"1447": [355, 29, 30, 30, 29, 30, 30, 29, 30, 29, 29, 30, 29]
}
},
{
"adjust": -1,
"current": 0,
"map": { "...": "..." }
},
{
"adjust": 1,
"current": 0,
"map": { "...": "..." }
}
]
معنی فیلدها
| فیلد | توضیح |
|---|---|
adjust |
مقدار جبرانی: -1 یک روز کم میکند، 0 حالت مرجع، +1 یک روز اضافه میکند. |
current |
وضعیت فعال که میتواند توسط کلاینت یا پنل ادمین برای علامتگذاری حالت انتخابی استفاده شود (در نمونه فعلی صفر است). |
map |
دیکشنری سال قمری ↦ آرایه شامل ۱ + ۱۲ مقدار: عدد اول تعداد روزهای سال (۳۵۴ یا ۳۵۵)، ۱۲ عدد بعدی طول هر ماه قمری. |
انتخاب حالت مناسب با مثال
| حالت | زمان استفاده پیشنهادی | مثال عملی |
|---|---|---|
adjust = 0 |
حالت مرجع و عمومی | نمایش تقویم در سامانه آموزشی بدون نیاز به تصحیح محلی. |
adjust = -1 |
مناطقی که شروع ماه قمری را یک روز زودتر اعلام میکنند یا پس از رصد مشخص میشود هلال یک روز زودتر دیده شده | اگر در ایران رمضان ۲۹ روز اعلام شود اما محاسبهگر ۳۰ روزه باشد، با -1 آخرین روز حذف میشود. |
adjust = +1 |
مناطقی که آغاز ماه را دیرتر اعلام میکنند یا برای همگامسازی با تقویم رسمی نیاز به افزودن روز دارند | زمانی که کشوری عید قربان را یک روز دیرتر میگیرد؛ با +1 روز اضافه میشود. |
سناریوی قدمبهقدم: تعیین تاریخ عید فطر
- دریافت داده:
configs = GET /api/calendar/adjustemnts/. - انتخاب حالت:
defaultConfig = configs.find(c => c.adjust === 0). - استخراج سال هدف:
ramadanProfile = defaultConfig.map['1445']. - محاسبه طول رمضان: مقدار شاخص ۹ (ماه نهم). اگر ۲۹ بود → عید فطر روز ۲۹ رمضان، اگر ۳۰ بود → روز ۳۰.
- در صورت اختلاف رسمی، کافی است پیکربندی دیگری را انتخاب کنید (مثلاً
adjust = +1) تا روز اضافه لحاظ شود.
سناریوی همگامسازی تقویم در اپلیکیشن
- در اولین اجرا، هرسه پیکربندی را ذخیره کنید.
- متناسب با موقعیت کاربر (یا انتخاب کاربر)،
adjustمناسب را فعال نگه دارید. مقدار انتخابی را میتوانید در کلاینت یا سرور ذخیره کنید. - برای تبدیل «روز سال قمری» به روز میلادی:
- اختلاف روز تا ابتدای سال قمری را با جمع ۱۲ ماه محاسبه کنید.
- با استفاده از تاریخ میلادی مرجع (مثلاً شروع سال قمری در تقویم رسمی)، اختلاف را اعمال کنید تا تاریخ میلادی بهدست آید.
- اگر دادههای
CalendarOccasionsنوعlunarداشتند، از نقشه انتخابشده برای محاسبه تاریخ معادل استفاده کنید و مقدار نهایی را به رابط کاربری نمایش دهید.
راهنمای محاسبه اوقات شرعی
مبنای پروژه فایل prayer_times_calculation_guide.html است که مراحل استفاده از الگوریتم PrayTimes را تشریح کرده است. خلاصه فرآیند:
- ورودیها: تاریخ میلادی، مختصات (عرض/طول جغرافیایی، ارتفاع)، روش محاسبه (مثلاً Tehran، MWL)، روش جبران عرضهای بالا و فرمت خروجی (۱۲ یا ۲۴ ساعته).
- محاسبه تاریخ ژولیَن (Julian Date):
jdate = julian(year, month, day) - longitude / (15 × 24). - موقعیت خورشید: با تابعی مشابه
sunPosition(jdate)زاویه میل خورشید (declination) و معادله زمان (equation of time) بهدست میآید. - محاسبه اوقات پایه:
- فجر، طلوع، مغرب، عشا: با
sunAngleTimeو زاویههای مخصوص هر روش محاسبه میشوند. - ظهر: با
midDay. - عصر: با
asrTimeو فاکتور مربوط به مذهب (1 برای شافعی/جعفری، 2 برای حنفی).
- فجر، طلوع، مغرب، عشا: با
- تنظیم اختلاف طول جغرافیایی و منطقه زمانی:
offset = timezoneHours - longitude / 15- جمع این مقدار با همه زمانهای محاسبهشده.
- جبران عرضهای جغرافیایی بالا: در صورت انتخاب روشهایی مثل
NightMiddleیاAngleBased، طول شب محاسبه و زمانهای فجر/عشا تعدیل میشوند. - تبدیل خروجی اعشاری به ساعت:
- ساعت = بخش صحیح عدد.
- دقیقه =
(عدد - ساعت) × 60. - در صورت نیاز به فرمت ۱۲ ساعته، AM/PM مطابق قواعد اضافه میشود.
چه ابزاری برای محاسبه استفاده کنیم؟
- بکاند (Python/Django): در صورت نیاز به محاسبه سمت سرور میتوانید از پیادهسازی استاندارد PrayTimes یا کتابخانههای معتبری مانند
praytimes(نسخه پایتونی) بهره ببرید. نتیجه را میتوان کش کرد و فقط در صورت تغییر مختصات یا تاریخ دوباره محاسبه نمود. - کلاینت فلاتر: استفاده از کلاس سفارشی پروژه یا پکیجهای آماده نظیر
adhan_dartبرای محاسبات سریع و دقیق توصیه میشود. - وب/جاوااسکریپت: کتابخانههایی مثل
adhanیا نسخهٔ رسمی PrayTimes.js بهخوبی نیاز را پوشش میدهند.
نمونه کد فلاتر
دریافت و استفاده از تنظیمات قمری
import 'dart:convert';
import 'package:http/http.dart' as http;
class LunarAdjustConfig {
final int adjust;
final Map<String, List<int>> map;
LunarAdjustConfig({required this.adjust, required this.map});
factory LunarAdjustConfig.fromJson(Map<String, dynamic> json) {
return LunarAdjustConfig(
adjust: json['adjust'] as int,
map: (json['map'] as Map<String, dynamic>).map(
(key, value) => MapEntry(key, List<int>.from(value)),
),
);
}
}
Future<List<LunarAdjustConfig>> fetchAdjustments() async {
final res = await http.get(Uri.parse('https://example.com/api/calendar/adjustemnts/'));
final data = jsonDecode(res.body) as List<dynamic>;
return data.map((item) => LunarAdjustConfig.fromJson(item)).toList();
}
DateTime applyLunarOffset({
required DateTime hijriYearStart,
required LunarAdjustConfig config,
required String hijriYear,
required int hijriMonthIndex,
required int hijriDay,
}) {
final months = config.map[hijriYear] ?? [];
if (months.length != 13) {
throw ArgumentError('ساختار سال قمری نامعتبر است');
}
final daysFromYearStart = months
.sublist(1, hijriMonthIndex)
.fold<int>(0, (acc, value) => acc + value);
final totalOffset = daysFromYearStart + (hijriDay - 1) + config.adjust;
return hijriYearStart.add(Duration(days: totalOffset));
}
محاسبه اوقات شرعی با adhan_dart
import 'package:adhan_dart/adhan_dart.dart';
PrayerTimes calculatePrayerTimes({
required DateTime date,
required Coordinates coordinates,
}) {
final params = CalculationMethod.tehran();
params.madhab = Madhab.shafi;
final times = PrayerTimes(coordinates, date, params);
return times;
}
void main() async {
final configs = await fetchAdjustments();
final defaultConfig = configs.firstWhere((c) => c.adjust == 0, orElse: () => configs.first);
final hijriStart = DateTime(2023, 7, 19); // تاریخ میلادی شروع سال 1445 به تقویم رسمی
final eidDate = applyLunarOffset(
hijriYearStart: hijriStart,
config: defaultConfig,
hijriYear: '1445',
hijriMonthIndex: 10, // ماه شوال (پس از رمضان)
hijriDay: 1,
);
final times = calculatePrayerTimes(
date: eidDate,
coordinates: Coordinates(35.6892, 51.3890),
);
print('اذان صبح: ${times.fajrTime}');
print('اذان مغرب: ${times.maghribTime}');
}
نمونه کد جاوااسکریپت (وب یا Node.js)
دریافت تنظیمات و محاسبه تاریخ قمری
import fetch from 'node-fetch';
async function fetchAdjustments() {
const res = await fetch('https://example.com/api/calendar/adjustemnts/');
return res.json();
}
function applyLunarOffset({ hijriYearStart, config, hijriYear, hijriMonthIndex, hijriDay }) {
const months = config.map[hijriYear];
if (!months || months.length !== 13) {
throw new Error('ساختار سال قمری نامعتبر است');
}
const daysBeforeMonth = months.slice(1, hijriMonthIndex).reduce((sum, value) => sum + value, 0);
const totalOffset = daysBeforeMonth + (hijriDay - 1) + config.adjust;
const result = new Date(hijriYearStart);
result.setDate(result.getDate() + totalOffset);
return result;
}
// مثال استفاده
const configs = await fetchAdjustments();
const preferred = configs.find((c) => c.adjust === 1) ?? configs[0];
const eidAlAdha = applyLunarOffset({
hijriYearStart: new Date('2024-06-08'), // شروع سال 1446 در تقویم رسمی منطقه هدف
config: preferred,
hijriYear: '1446',
hijriMonthIndex: 12, // ذیالحجه
hijriDay: 10,
});
console.log('تاریخ میلادی عید قربان:', eidAlAdha.toISOString().slice(0, 10));
محاسبه اوقات شرعی با کتابخانه adhan
import { PrayerTimes, Coordinates, CalculationMethod } from 'adhan';
function calculatePrayerTimes(date, lat, lng) {
const params = CalculationMethod.Tehran();
const coordinates = new Coordinates(lat, lng);
const times = new PrayerTimes(coordinates, date, params);
return {
fajr: times.fajr.toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' }),
sunrise: times.sunrise.toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' }),
dhuhr: times.dhuhr.toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' }),
asr: times.asr.toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' }),
maghrib: times.maghrib.toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' }),
isha: times.isha.toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' }),
};
}
const todayTimes = calculatePrayerTimes(new Date(), 35.6892, 51.3890);
console.log(todayTimes);
جمعبندی
- تقویم پروژه از ترکیب مدل
CalendarOccasionsو تنظیمات پویاcalendar__Adjustmentتشکیل شده و API ویژهٔadjustemntsسه سناریوی جبران قمری را ارائه میکند. - برای محاسبهٔ اوقات شرعی میتوان از الگوریتم مبتنی بر
PrayTimesاستفاده کرد که با ورودیهای تاریخ، مختصات و روش محاسبه، زمانهای اذان را بازمیگرداند. - نمونه کدهای فلاتر و جاوااسکریپت نشان میدهند چگونه میتوان در کلاینت هم تاریخهای قمری را به میلادی تبدیل کرد و هم اوقات شرعی را بهصورت محلی محاسبه نمود.