اذهب إلى المحتوى

السؤال

نشر

لقد حصلت على كو د جافا سكربت لعمل تاريخ هجري، ولكنني لم افهم اي شي من الكود. 

اتمى احد يقوم بشرح الكود بالتفصيل لنستفيد جميعا 

الكود

<script language="JavaScript">
  var fixd;
function isGregLeapYear(year)
{
  return year%4 == 0 && year%100 != 0 || year%400 == 0;
}

function gregToFixed(year, month, day)
{
  var a = Math.floor((year - 1) / 4);
  var b = Math.floor((year - 1) / 100);
  var c = Math.floor((year - 1) / 400);
  var d = Math.floor((367 * month - 362) / 12);
  if (month <= 2)
    e = 0;
  else if (month > 2 && isGregLeapYear(year))
    e = -1;
  else
    e = -2;
  return 1 - 1 + 365 * (year - 1) + a - b + c + d + e + day;
}
function Hijri(year, month, day)
{
  this.year = year;
  this.month = month;
  this.day = day;
  this.toFixed = hijriToFixed;
  this.toString = hijriToString;
}
function hijriToFixed()
{
  return this.day + Math.ceil(29.5 * (this.month - 1)) + (this.year - 1) * 354 +
    Math.floor((3 + 11 * this.year) / 30) + 227015 - 1;
}
function hijriToString()
{
  var months = new Array("محرم","صفر","ربيع أول","ربيع ثانى","جمادى أول","جمادى ثانى","رجب","شعبان","رمضان","شوال","ذو القعدة","ذو الحجة");
  return this.day + " " + months[this.month - 1]+ " " + this.year;
}
function fixedToHijri(f)
{
  var i=new Hijri(1100, 1, 1);
  i.year = Math.floor((30 * (f - 227015) + 10646) / 10631);
  var i2=new Hijri(i.year, 1, 1);
  var m = Math.ceil((f - 29 - i2.toFixed()) / 29.5) + 1;
  i.month = Math.min(m, 12);
  i2.year = i.year;
  i2.month = i.month;
  i2.day = 1;
  i.day = f - i2.toFixed() + 1;
  return i;
}
var tod=new Date();
var weekday=new Array("الأحد","الإثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت");
var monthname=new Array("1","2","4","3","5","6","7","8","سبتمبر","12","11","10");
var y = tod.getFullYear();
var m = tod.getMonth();
var d = tod.getDate();
var dow = tod.getDay();
document.write(weekday[dow] + " " + d + " " + monthname[m] + " " + y);
m++;
fixd=gregToFixed(y, m, d);
var h=new Hijri(1421, 11, 28) ;
h = fixedToHijri(fixd);
document.write(" م || " + h.toString() + "هـ");
</script>

 

Recommended Posts

  • 1
نشر

هذا الكود يقوم بتحويل التواريخ من التقويم الميلادي إلى التقويم الهجري وعرضها على الصفحة. سأشرح الكود بالتفصيل من خلال تقسيمه الي وظائف (دوال) :

isGregLeapYear(year): هذه الوظيفة تستخدم للتحقق مما إذا كان العام الميلادي هو سنة كبيسة أم لا. إذا كانت السنة كبيسة، ستعيد true وإلا ستعيد false.

gregToFixed(year, month, day): هذه الوظيفة تقوم بتحويل تاريخ ميلادي إلى عدد ثابت يُمثل اليوم في التقويم الميلادي. تستند الوظيفة إلى مجموعة من الحسابات والتحويلات المعينة.

Hijri(year, month, day): هذه الوظيفة تعرف كائن هجري جديد وتعبئه بالسنة والشهر واليوم المحدد.

hijriToFixed(): هذه الوظيفة تقوم بتحويل تاريخ هجري إلى عدد ثابت يُمثل اليوم في التقويم الهجري.

hijriToString(): هذه الوظيفة تقوم بإعادة تاريخ هجري بصيغة نصية، حيث يتم استخدام مصفوفة months لتمثيل أسماء الشهور.

fixedToHijri(f): هذه الوظيفة تقوم بتحويل العدد الثابت إلى تاريخ هجري.

يتم إنشاء كائن tod من نوع Date للحصول على التاريخ الحالي.

تُعرف مصفوفتين weekday و monthname لتمثيل أسماء أيام الأسبوع وأشهر السنة.

يتم الحصول على العام والشهر واليوم الحالي من كائن tod.

يتم استدعاء الوظيفة gregToFixed لتحويل التاريخ الميلادي إلى عدد ثابت وتخزين النتيجة في متغير fixd.

يتم إنشاء كائن h من نوع Hijri بتاريخ هجري ثابت (1421, 11, 28)، ثم يتم استدعاء الوظيفة fixedToHijri لتحويل العدد الثابت fixd إلى تاريخ هجري وتخزين النتيجة في المتغير h.

يتم عرض التاريخ الميلادي المحدد مع أسماء اليوم والشهر والعام على الصفحة.

يتم عرض التاريخ الهجري المحدد على الصفحة مع "م" (ميلادي) و"هـ" (هجري).

  • 0
نشر

الكود يحوّل تاريخ اليوم الميلادي إلى التاريخ الهجري بطريقة حسابية، وفكرته أن يحوّل التاريخ إلى رقم يوم ثابت ثم يحوّل هذا الرقم إلى تاريخ هجري. إليك الشرح خطوة بخطوة، ثم ملاحظات مهمة قبل استخدامه.

١. رقم اليوم الثابت (gregToFixed)

الفكرة أن نعطي كل يوم رقماً واحداً متسلسلاً: اليوم رقم 1 هو 1 يناير من السنة 1 ميلادياً، ثم نعدّ الأيام. هكذا يصبح التحويل بين التقاويم عدّاً بسيطاً. الدالة تجمع:

  • 365 * (year - 1): أيام السنوات الكاملة السابقة.
  • a - b + c: عدد السنوات الكبيسة السابقة (كل 4 سنوات، ما عدا كل 100، إلا كل 400).
  • Math.floor((367 * month - 362) / 12): عدد أيام الشهور السابقة من السنة الحالية، محسوباً كأن فبراير 30 يوماً، ثم يصحّح المتغير e الناتج للشهور التي بعد فبراير: يطرح يوماً في السنة الكبيسة ويومين في غيرها.
  • day: اليوم نفسه.

٢. من الهجري إلى رقم ثابت (hijriToFixed)

  • 227015: رقم اليوم الثابت لأول محرم سنة 1 هـ في هذا الحساب، وهو 16 يوليو 622م بالتقويم اليولياني، ويوافق 19 يوليو 622م بالتقويم الميلادي (الغريغوري) الذي تستخدمه gregToFixed. وتحققت من ذلك: new Hijri(1, 1, 1).toFixed() وgregToFixed(622, 7, 19) يعطيان كلاهما 227015.
  • Math.ceil(29.5 * (month - 1)): أيام الشهور السابقة، على افتراض أن الشهور تتناوب 30 ثم 29 يوماً.
  • (year - 1) * 354: أيام السنوات الكاملة السابقة، على أساس 354 يوماً لكل سنة.
  • Math.floor((3 + 11 * year) / 30): عدد السنوات الكبيسة (355 يوماً) السابقة لهذه السنة، أي الأيام الزائدة المتراكمة قبل بدايتها، فكل دورة من 30 سنة فيها 11 سنة كبيسة، وهي في هذا الكود السنوات 2 و5 و7 و10 و13 و16 و18 و21 و24 و26 و29 من الدورة.

٣. العكس: من رقم ثابت إلى هجري (fixedToHijri)

  • السنة: Math.floor((30 * (f - 227015) + 10646) / 10631)، و10631 هو عدد أيام الدورة الكاملة (30 × 354 + 11)، فالمعادلة تقدّر عدد الدورات وأجزائها التي مضت منذ بداية التقويم، وتحوّلها إلى رقم السنة.
  • الشهر: Math.ceil((f - 29 - i2.toFixed()) / 29.5) + 1، أي يأخذ عدد الأيام منذ أول السنة، ويطرح منه 29، ثم يقسم الناتج على 29.5 (متوسط طول الشهر) ويقرّبه إلى الأعلى ويضيف 1، مع حدّ أقصى 12.
  • اليوم: الفرق بين الرقم الثابت وأول الشهر، زائد 1.

٤. العرض

الجزء الأخير يأخذ تاريخ اليوم من new Date()، ويكتب اسم اليوم والتاريخ الميلادي ثم الهجري بـ document.write.

ملاحظات مهمة قبل استخدامه

  • هذا تقويم حسابي، لا تقويم أم القرى. شغّلت الدوال كما هي وقارنتها بتقويم أم القرى لكل يوم من 2020 إلى 2035: اختلف التاريخ في 2,677 يوماً من 5,844 (نحو 46%)، وفي أغلبها بيوم واحد. مثلاً 13 أكتوبر 2026 يكتبه الكود «1 جمادى أول 1448»، وفي أم القرى هو 2 جمادى الأولى. و9 مارس 2027 يكتبه «30 رمضان 1448»، وفي أم القرى هو 1 شوال. فإن كان موقعك يحتاج إلى تقويم أم القرى المستخدم في السعودية، فلا تعتمد على هذا الكود؛ لأنه يستخدم تقويماً هجرياً حسابياً مختلفاً.
  • مصفوفة الشهور الميلادية monthname ترتيبها خاطئ: يظهر مارس «4»، وأبريل «3»، وأكتوبر «12»، وديسمبر «10»، ويظهر سبتمبر بالاسم «سبتمبر» بدل الرقم 9.
  • المتغير e غير معرَّف في gregToFixed (لا var ولا let)، فيصبح متغيراً عاماً في الوضع غير الصارم، أما في الوضع الصارم أو داخل وحدة JavaScript (module) فيسبب إسناد قيمة إليه خطأ ReferenceError.
  • الصيغ الأفصح لأسماء الشهور الهجرية: «ربيع الأول» و«ربيع الآخر» و«جمادى الأولى» و«جمادى الآخرة».
  • document.write أسلوب قديم، والأفضل وضع النص في عنصر بـ textContent.

البديل الحديث دون مكتبة

المتصفحات الحديثة تدعم تقويم أم القرى عبر Intl، فيكفي:

const hijri = new Intl.DateTimeFormat('ar-SA-u-ca-islamic-umalqura-nu-latn', {
  weekday: 'long', day: 'numeric', month: 'long', year: 'numeric',
});

const el = document.getElementById('hijri-date');

// قد يتجاهل المتصفح التقويم المطلوب ويستخدم تقويماً آخر، لذا نتحقق من التقويم المستخدم فعلاً
if (el) {
  el.textContent = hijri.resolvedOptions().calendar === 'islamic-umalqura'
    ? hijri.format(new Date())
    : 'تقويم أم القرى غير مدعوم في هذا المتصفح';
}

بشرط وجود عنصر مثل <span id="hijri-date"></span> في الصفحة، والتاريخ هنا بحسب المنطقة الزمنية لجهاز الزائر. وتذكّر أن بداية الشهور مثل رمضان وشوال تُعلن برؤية الهلال، فقد يختلف التاريخ المعلن عن المحسوب.

للإفصاح: قارنت النتائج أعلاه أيضاً بجدول أم القرى في مكتبة مفتوحة المصدر أعمل عليها، فتطابقت مع نتائج Intl.

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...