تحري هلال شهر رمضان، ودالة التحويل إلى الهجري

بعد كتابة دالتي التحويل إلى الهجري وإلى الميلادي في عام 2009 كُنت أترقب دائماً شهر رمضان، واﻷعياد، وأحياناً تكون نتيجة الدالة صحيحة بأن يكون يوم الصيام هو نفس نتيجة دالة التحويل، وأحياناً يختلف يوم واحد فقط. لكن هذه المرة ظهر أن اﻹختلاف يمكن أن يكون يومين، حيث ظهر في برنامج التحويل أن أمس 18 يوليو هو يوم 29 شعبان، وأن اليوم 19 يوليو هو أول أيام رمضان، فإذا لم يثبت رمضان غداً فإن دالة التحويل تكون قد أخطأت يومين، وهذه أول مرة تحصل. فجلست أفكر عن سبب المشكلة، ووجدت أن الفرق هو أن هذه السنة كبيسة، وهي أول سنة كبيسة تمر على هذا البرنامج، حيث أن السنة الكبيسة الماضية كانت عام 2008 ودالة التحويل كتبتها في عام 2009. قمت بإنقاص يوم قبل التحويل في الدالة إلى الهجري في حال أن السنة كبيسة، وذلك لأن السنة الميلادية هي 365 يوم وربع، حيث لدواعي دالة التحويل للهجري يجب زيادة السنة الميلادية ربع يوم، أي 6 ساعات كل سنة، بدلاً من زيادتها يوماً كاملاً كل 4 سنوات، مما يجعل الدالة تزيد يوم هجري بالخطأ.

قُمت برفع التعديل في الموقع، وسوف أتابع الشهور الهجرية لهذه السنة، وسوف أتكلم عنه لاحقاً بعد عدة سنين إن شاء الله لنعرف نتيجة هذا التعديل.

بعد التعديل ظهر في البرنامج أن اليوم 19 يوليو هو 29 شعبان، وغداً أول رمضان، فإذا لم يثبت رمضان غداً كان الفرق هو يوماً واحداً فقط، وهو مقبول بالنسبة لدوال التحويل إلى الهجري.

تحديث..

بعد مراجعة التعديل مرة أخرى، وجدت خطأ آخر، وهو عند إنقاص التاريخ الميلادي يوم واحد عند بداية السنة الميلادية الكبيسة، فإن التاريخ الهجري لأول يوم في السنة الميلادية سوف يساوي التاريخ الهجري لآخر يوم من السنة الميلادية الماضية:

1-1-2012  =  6.صفر.1433
31-12-2011  =  6.صفر.1433

procedure DateToHejri(ADateTime: TDateTime; var Year, Month, Day: Word);
var
  HejriY: Double;
  Days: Double;
  HejriMonth: Double;
  RDay: Double;
  Y, M, D: Word;
begin
  DecodeDate(ADateTime, Y, M, D);
  if (Y mod 4 = 0) then
    ADateTime:= ADateTime - 1;
  HejriY:= ((Trunc(ADateTime) - HejriStart - 1) / HejriYearDays);
  Days:= Frac(HejriY);
  Year:= Trunc(HejriY) + 1;
  HejriMonth:= ((Days * HejriYearDays) / HejriMonthDays);
  Month:= Trunc(HejriMonth) + 1;
  RDay:= (Frac(HejriMonth) * HejriMonthDays) + 1;
  Day:= Trunc(RDay);
end;

تحديث…
قمت بعمل تعديل، وذلك بإضافة الساعات (ربع يوم، نصف يوم، ثلاث أرباع اليوم):


procedure DateToHejri(ADateTime: TDateTime; var Year, Month, Day: Word);
var
  HejriY: Double;
  Days: Double;
  HejriMonth: Double;
  RDay: Double;
  Y, M, D: Word;
begin
  DecodeDate(ADateTime, Y, M, D);
  case Y mod 4 of
    0: ADateTime:= ADateTime + 0;
    1: ADateTime:= ADateTime + 0.25;
    2: ADateTime:= ADateTime + 0.50;
    3: ADateTime:= ADateTime + 0.75;
  end;
  HejriY:= ((Trunc(ADateTime) - HejriStart - 1.5) / HejriYearDays);
  Days:= Frac(HejriY);
  Year:= Trunc(HejriY) + 1;
  HejriMonth:= ((Days * HejriYearDays) / HejriMonthDays);
  Month:= Trunc(HejriMonth) + 1;
  RDay:= (Frac(HejriMonth) * HejriMonthDays) + 1;
  Day:= Trunc(RDay);
end;

ونتيجة الدالة هذه المرة هو أن اليوم هو 30 شعبان، وغداً اﻷول من رمضان. وقد قُمت بمقارنتها مع الأعوام السابقة وكانت النتيجة مرضية، لكن تحتاج لعدة سنوات أخرى للتأكد من هذا التعديل.

تم إعلان أن يوم غد الجمعة هو اﻷول من رمضان في السعودية وقطر.

نهنيء المسلمين برمضان ونسأل الله أن يرزقنا صيامه وقيامه

 

Advertisements

30 فكرة على ”تحري هلال شهر رمضان، ودالة التحويل إلى الهجري

  1. عمل ممتاز اخي معتز ولكني لم اعرف مع اي دولة تقارن صحة الحساب لبرنامجك؟ فكما تعلم ان الدول مختلفة في اثبات بدايات الشهور القمرية.

  2. اليوم السعودية أخذت بشهادة الشهود الذين زعموا أنهم رأو الهلال وبناء عليه قررت أن غدا أول ايام شهر رمضان المبارك رغم أن رؤية الهلال كانت مستحيلة في جميع الدول العربية بإجماع علماء الفلك في العالم قاطبة مسلمهم وكافرهم لسبب بسيط هو أن القمر قد غاب قبل الشمس في بعض الدول ومعها في البعض الآخر،ترى ماهي معايير قبول الشهادة وهل يمكن أن تتغير وتضبط أكثر بتراكم المعرفة العلمية ذات الصلة؟

  3. المقارنة بسيطة، وهي أن لا يكون الفرق أكثر من يوم. خلال الثلاث أو اﻷربع سنوات الماضية لم يزد اﻹختلاف عن يوم واحد فقط، وإذا اختلف في بداية الشهر غالباً يُطابق نهاية الشهر.
    يمكن تحسين الخوارزمية لتكون أكثر مطابقة وبطريقة أكثر علمية، هذا مجرد تطبيق بسيط لعدد اﻷيام في السنة القمرية وعدد اﻷيام في الشهر الهجري، ثم يحصل تقريب ويكون الفارق هو يوم واحد فقط أو يكون مطابق

  4. صحيح، لان الخطا كان باحتساب عدد الايام الفرق بين ADateTime و HejriStart و هذا الرقم خطأ لانو هنالك سنوات كبيسة ميلادية.
    لذلك حاول استخدام DaysBetween لاحتساب الفرق بينهما

    HejriY:= ((Trunc(ADateTime) – HejriStart – 1) / HejriYearDays);
    ->
    HejriY:= (((DaysBetween(ADateTime), HejriStart) – 1) / HejriYearDays);

  5. لا يمكنني تجربته إذا لم أفهمه. الحل اﻷول كان فهمه بسيط وهو يعتمد على حساب اﻷيام التي مضت من أول يوم في الهجرة، ثم تحويلها إلي سنين بقسمتها على السنة الهجرية وهو 354.367056 يوم، فالناتج الصحيح يعطينا السنة الهجرية الحالية أما الجزء الكسري فهو يُمثل الشهور واﻷيام في السنة الحالية التي لم تتم.

  6. هذا ما افكر فيه، ما علاقة السنة الكبيسة بالموضوع؟
    لانك تقسم على عدد الأيام المخزن في متحول التاريخ وهو عدد الأيام ليس في السنة بل منذ التارخ الصفري، مأخوذ بعين الاعتبار السنة الكبيسة اصلا عند التحويل من النص إلى هذه القيمة.
    إذا كان هنالك خطأ فهو في عدد الأيام في السنة الهجرية، ولكن ربما هو صحيح، و الخطأ هو عدم مراعاة السنة الكبيسة الهجرية وهي تحدث كل 30 سنة.
    راجع Remarks في
    http://msdn.microsoft.com/en-us/library/system.globalization.hijricalendar%28v=vs.80%29.aspx

  7. نعم صحيح، السنة الكبيسة ربما ليس لديها دخل بما أن الحسابات تتم على اﻷيام فقط. وإذا رجعنا إلى الدالة القديمة قبل التعديل فهي تحسب أن اليوم هو الثاني من رمضان، أي بفارق يوم، وهذا يعني أن الدالة مازالت صحيحة إلى اﻵن.
    بالنسبة للسنة الكبيسة في التاريخ الهجري فلا أعتقد أنه إعتقاد صحيح، حيث أن السنة الميلادية لا تحسب الكسر 0.25 في كل سنة، فيقوموا بتحديثها كل أربع سنين فيمايعرف بالسنة الكبيسة، والشهور في السنة الميلادية محددة، ماعدا شهر 2 يختلف حسب أن السنة كبيسة أم لا.
    أما بالنسبة للتاريخ الهجري فالجدول المكتوب في الصفحة التي أشرت إليها لا يُمكن إعتمادها، مثلاً شهر رمضان عندهم 30 يوم، وهذا غير صحيح، ولا أظن أن هُناك شهر في التاريخ الهجري محدد، فهو معتمد على القمر، إي يحدث تحديث تلقائي للشهور وبالتالي السنين دائماً وهذا يعني أن الشهور القمرية والسنوات القمرية تأخذ في اﻹعتبار الكسور في كل عام، لذلك لا أعتقد أننا نحتاج لحساب سنوات كبيسة في التاريخ الهجري.

    السنة الميلادية الكبيسة لها علاقة بمئات السنين وليس فقط كل أربع سنين، كان لدي برنامج سابق كُنت قد استخدمت فيه سنة كبيسة يتم إختبارها بقابلية القسمة على أربعة ومائة أو أربعمائة، لكن لا أذكر هذا التفصيل، ربما السنة الميلادية ليست 365.25 بل تحتاج لدقة أكثر في الجزء العشري.

  8. دقة اﻷيام في السنة الهجرية مشكلة للحساب، لكنها تجعل التاريخ الهجري يكون دائماً دقيق، حيث نستخدم القمر لعمل معايرة للحساب إن صح التعبير. لكن كيف تتم معايرة التاريخ الميلادي، هل يوجد ربط بين أيام السنة والوضع الفعلي للأرض حول الشمس أم لا.
    وأيضاً توجد دقة عشرية في عدد اﻷيام في الشهر القمري، وهو 29.530588 يوم للشهر.

  9. ضمن المعادلة لا يوجد شي اسمه التاريخ الميلادي، لديك فقط “عدد الأيام” و هي مساقلة عن أي تاريخ.
    لذلك مجرد دخول شي اسمه تاريخ ميلادي هو خطأ

    إن 29.530588 هو عبارة عن 354.367056 مقسمة على 12
    لذلك انا ثم ببعض التعديلات عندي و استغنيت عنه نهائيا

  10. تأثير السنة الميلادية الكبيسة يكمن في اﻵتي:
    الفرق بين يوم 20-7-2011 إلى يوم 20-7-2012 هو 366 يوم
    أما الفرق بين 20-7-2010 إلى يوم 20-7-2011 هو 365 يوم

    لذلك فإن السنة الكبيسة فيها يوم زائد يؤثر على تحويل اﻷيام إلى الهجرية
    والله اعلم

  11. هذا اليوم اصلا داخل في المعادلة التي تحول التاريخ من نص إلى قيمة عددية التي تمثل عدد الأيام، ليس من المنطق إعادة ادخالها مرة اخرى، راجع تعليقي السابق.

  12. التاريخ الميلادي يدخل في التحويل، بحيث أن بداية التاريخ الهجري منسوبة إلى التاريخ الميلادي، واليوم الذي نريد معرفته بالهجري هو تاريخ ميلادي، والفرق بين هذين التاريخين الميلاديين يتأثر بالسنة الكبيسة، لكن المتوسط يكون 365 يوم وربع اليوم، أما السنة اﻷخيرة فلاتدخل في المتوسط لذلك وجب إضافة الساعات الناقصة:
    متوسط أربع سنوات ميلادية = 365.25 يوم
    متوسط خمس سنوات ميلادية لايساوي 365.25 ، لذلك يجب عمل إضافة للجزء الكسري

  13. لا، لا يدخل
    >بداية التاريخ الهجري منسوبة إلى التاريخ الميلادي
    1 – و منه اصبح لديك تاريخ البداية في الهجري و هي نقطة بدء إذا كان فيها خطأ فيتم تصحيحها عند احتساب تاريخ البدء وهو قيمة ثابتة.
    >واليوم الذي نريد معرفته بالهجري هو تاريخ ميلادي
    لا، القيمة المررة للتابع هي عبارة عدد الأيام فقط (تحوي الساعات بالجزء الكسري نتجاهله بالـ trunc)

    بقية الحسابات تم استعمالها مسبقا عندما قمت التحويل من التاريخ الميلادي النصي إلى عدد الأيام ذلك.
    لا وجود لعنصر التاريخ الميلادي في المعادلة لكي يستخدم السنة الكبيسة الميلادية، و إذا اعطاء ذلك نتيجة فذلك من قبيل الصدفة.

    3 – افرض انني اعطيتك عددا من الايام مثلا 1000 و قلت لك قل لي كم سنة هجرية بالشهر و اليوم، ثم انت عند الاحتساب أدخلت السنة الكبيسة الميلادية، ساستغرب ذلك، لانني استخرجت عدد الأيام ذلك من التاريخ الصيني، لماذا لم تستعمل السنة الكبسة الصينية في معادلتك؟

  14. نعم كلامك صحيح، معالجة السنة الكبيسة ليس لها أثر
    يوجد شيء لم أنتبه له، وهو استخدام الدالة Trunc وهي تقوم بقطع الجزء الكسري الذي أضفناه في الـ Case، قمت بحذف الجزء المتعلق بالسنة الكبيسة، ولم يتغير شيء في النسخة الأخيرة، أهم شيء غير الدالة هو طرح 1.5 بدلاً من يوم واحد في المعادلة:

      HejriY:= ((Trunc(ADateTime) - HejriStart - 1.5) / HejriYearDays);
    

    سنة صينية 🙂

  15. إذن هنالك خطأ في HejriStart قم بتعديل الثابت باضافة 1.5 يوم

    الواحد: لان التاريخ الهجري يبدأ من 1/1/1
    أما الـ 0.5 فله قصة و غالبا صحيح، لان هنالك قد يكون فرق نصف يوم بين تواريخ البداية ناتج عن إما السنة الكبيسة الهجرية أو الميلادية الذي تم الاستناد إليه.

  16. برنامجك هذا يا معتز ذكرني بأيام جميلة في منتصف الثمانينات ، بداية ذكرياتي مع البرمجة بلغة بيزك بواسطة كمبيوتر صخر المنزلي ،حيث كان به برنامج تقويم يمكن بواسطته تحديد بداية رمضان والأعياد ، حيث كان الأهل والمعارف والأصدقاء يلجئون الي عند اقتراب تلك المناسبات لأحدد لهم بداية رمضان والأعياد بواسطة الكمبيوتر، وكم كانت فرحتي كبيرة ولا توصف عندما وجدت قبل فترة برنامج محاكاة لهذا الكمبيوتر العتيق ومعه جميع البرامج والألعاب التي كنت اشتريها على شكل كارتردج غالي الثمن جدا، او على اشرطة كاست رخيصة وغير عملية، ذلك الكمبيوتر كان في ذلك الوقت معجزة حقيقية حيث يوجد له برنامج القرآن الكريم من شركة العالمية الذي يحتوي على القرآن كاملا مع تفسير المفردات وبرنامج تحفيظ وبحث موضوعي وفهرس بكتب التفسير واسباب النزول ، وسوف تعلم انه فعلا معجزة عندما اخبرك ان ذاكرته كانت فقط 64 كيلو بايت و لايحتوي على هارد ديسك ويعمل بالمعالج z80 ذو السرعة 2.6 MHZ ولا يوجد خطأ في كتابة الأرقام
    http://www.bluemsx.com/

  17. كان عندي نفس الجهاز صخر MSX 2، في عام 1987، عندما كُنت في بداية المتوسطة، وكان من أهم الكارتريدج التي اشتريتها له هو لعبة اختبر ذكائك، إختبر معلوماتك، والشاطر حسن، ومغناطيسية، وبرنامج القرآن الكريم وكان غالي جداً، حيث بدأ سعره ب 500 ريال، ثم انخفض بعد عدة سنوات إلى 230 ريال على ما أذكر.

    بعد فترة اشتريت مسجل كاسيت لتسجيل البرامج، وكان التسجيل والتحميل للبرامج والملفات متعبة جداً، ومازلت أحتفظ بشرط من نوع 90 دقيقة، كان قد امتلاء منه الوجه اﻷول وبدأت أسجل في الوجه الثاني، إلى أن اشتريت جهاز كمبيوتر به محرك أقراص مرنة 3.5 بوصة عند دخولي للجامعة.

    كانت شركة صخر ناجحة جداً ليس فقط على صعيد اللغة العربية، لكن على صعيد البرمجة عموماً كان يُمكن أن تُقاس بشركة ميكروسوفت في ذلك الوقت. لكن لا أدري ماذا حدث لها بعد ذلك.

  18. يبدو أن تاريخنا في العلاقة بالكمبيوتر متشابه ، انا ايضا بدأت في تلك الفترة واشتريت برنامج القرآن ب 300 ريال وكنا نحل به مسابقات رمضان في السعودية بغاية البساطة وجهاز الكمبيوتر كان ب 700 ريال واول برنامج اشتريته كان برنامج اختبر معلوماتك واعتقد انه كان ب120 ريال ، وكنت اشتري الألعاب مسجلة على شريط كاسيت ب 20 ريال ولكن العمل مع الكاسيت كان مملا جدا فكنت انتظر احيانا لمدة نصف ساعة لتحميل لعبة لأكتشف انها مملة هذا اذا لم يظهر لك الكمبيوتر في الدقيقة الثلاثين رسالة تفيد انه قد فشل في تحميل اللعبة،ولكن اجمل مغامرات لي مع هذا الجهاز كانت بعد ان تعلمت كيف ابرمجه بلغة الآلة وكان عملا مرهقا جدا ولكنه ينطوي على الكثير من المتعة والتحدي والخطأ فيه مكلف الى آخر درجة، حيث انك تظل تكتب الساعات الطوال في ارقام لا معنى لها للقيام بعملية بسيطة جدا ، وكثيرا ما يحدث ان اكون قد كتبت رقما خطا صفرا جعلته واحدا او واحدا جعلته صفرا لتكون النتيجة ببساطة أن الكمبيوتر لا يرجع لك مرة اخرى ويعلق بكل بساطة ويكون كل مجهودك قد ضاع ادراج الرياح!!كانت بدايات ذلك في المدرسة المتوسطة، اجمل برنامج قمت بكتابته كان ينتمي الى نوع برامج الذكاء الصناعي حسب ما علمت بعد ذلك،حيث كان يحلل السؤال الذي تسأله اياه وذلك بمعرفة ادوات الإستفهام في السؤال ومن ثم يجيب عليك بإجابة طريفة صياغتها صحيحة ولكنها غير منطقية،عندما سأله احد اصدقائي اين تقع دولة السودان ،أجاب الكمبيوتر ،تقع دولة السودان داخل علبة الصلصة!!!،معليش الحديث عن هذا الأمر بالنسبة لي ذو شجون،وربما ان هذا ليس مكانه،،دائما ما اتساءل اين ذهبت تلك الشركة الناجحة صخر وما الذي حدث لها؟؟؟هل مازلت تحتفظ بهذا الكمبيوتر يا ابو اياس؟

  19. للأسف لا أحتفظ بهذه بالأجهزة القديمة، كان لدي جهاز أتاري ،جهازين صخر، واحد 64 كيلو، وواحد 128 كيلو اشتريته في السودان بعد دخول الجامعة.
    عندما إنتهيت من الثانوية اشريت كتاب لصناعة الألعاب، كنت أكتب اللعبة ثم أقوم بتعديلها، بعد ذلك اصبحت أكتب برامج متواصلة إلى أن دخلت الجامعة، وكان من أهم الألعاب والبرامج التي قمت بتصميمها هي: لعبة سباق السيارات، لعبة عناكب، لعبة بنك المعلومات، مطارحة شعرية، ثم لعبة تنس لكن لم أنتهي منها.
    شريط الكاسيت كنت مستمتع به جداً، لدرجة أني كنت أعرف نهاية الملف، وكان التسجيل في شكل Blocks في ملف تسلسلي، وكان هناك فاصل صوتي بين كل block، وكنت أعرف صوت نهاية الملف، حتى مرة كان هناك ملف به مشكلة في نهايته، فإضطررت إلى أن أقوم بتمرير الملف الذي بعده حتى أقوم بتحميل نهاية الملف الثاني في الملف الأول لأتمكن من قراءة الأول. لذلك كانت تجربة العمل على الملفات فيها شيء من الوضوح والوجود الفيزيائي، وأصبحت مستعد لفهم الملفات العشوائية قبل حصولي على قرص مرن، وهذا كان له أثر كبير جداً في فهمي للملفات بأنواعها، بل اصبحت أعشق التعامل مع ملفات البيانات، حتى أن واحد ممن قراء كتاب Start programming using Object Pascal قال أنه لم يجد كتاب يتكلم عن الملفات مثل هذا الكتاب.
    الآن توجد مشكلة حقيقية للناشئة في تعلم البرمجة أو الكمبيوتر عموماً، حيث أن الكمبيوتر أصبح معقد والبرامج أكثر تعقيداً والألعاب كثيرة كلها تشغل الإنسان من أن يصنع شيء بيده مفيد في الحاسوب

  20. على ذكر الملفات ، ذكرتني تجربة ممتعة قمت بها تلك الأيام حيث استطعت أن انقل ملف كامل بين كمبيوتري صخر لاسلكيا ولم يكن هناك شبكات لاسلكية او على الأقل لم اسمع بها ،حيث وصلت الجهاز المرسل الى مرسل مايك FM من مخرج الكمبيوتر ذو اللون الأحمر ليتم استقبالها عن بعد لاسلكيا الى الكمبيوتر الآخر عن طريق جهاز راديو عادي موصل مخرج السماعة منه الى الكمبيوتر ذو المدخل الأبيض، ونفذت أنا في الكمبيوتر المرسل أمر save “abc” , وقام صديقي على الطرف الآخر بتنفيذ الأمر load “abc” في نفس الوقت وتم نقل الملف بنجاح.
    اعظم اكتشاف لي في كمبيوتر صخر كان هو الأمر motor on and motor off
    حيث يقوم بتشغيل وايقاف المسجل بفتح وقفل الدائرة في المخرج المكتوب عليه remote
    فقمت بإستعماله للتحكم بدوائر الكترونية خارجية ، وقمت بإستقبال التغذية العكسية عن طريق مدخل عصا التحكم joystick
    فحصلت بذلك على طريقة للتحكم بأجهزة ميكينيكية خارجية مع مراقبة وضعها عن طريق مدخل عصا التحكم،كان ذلك الكمبيوتر عزيزا جدا على ولكن للأسف اضاعه قريب لي عندما سلفته اياه ، ولكني كنت مسرورا جدا عندما وجدت واحدا قبل ستة أشهر في سوق الدلالة بأمدرمان واشتريته بعشرين الف جنيه سوداني ، اي ستة دولارات فقط!!!!، ولو علم البائع بقيمة هذا الجهاز عندي لما باعه لي بأقل من مليون جنيه ولأشتريته دون تردد!!

  21. فعلا انا آسف فقد اخرجتكم عن موضوع النقاش الأصلي، فهذا يحتاج الى مدونة خاصة، سوف اقرأ عن تجربتك أخ زاهر على مدونتك، واقترح على الأخ أبوإياس ان يفرد جزء من مدونته للحديث ذو الشجون،واترككم لمواصلة النقاش

اترك رد

إملأ الحقول أدناه بالمعلومات المناسبة أو إضغط على إحدى الأيقونات لتسجيل الدخول:

WordPress.com Logo

أنت تعلق بإستخدام حساب WordPress.com. تسجيل خروج   / تغيير )

صورة تويتر

أنت تعلق بإستخدام حساب Twitter. تسجيل خروج   / تغيير )

Facebook photo

أنت تعلق بإستخدام حساب Facebook. تسجيل خروج   / تغيير )

Google+ photo

أنت تعلق بإستخدام حساب Google+. تسجيل خروج   / تغيير )

Connecting to %s