jalaali / jalaali-js

JavaScript functions for converting Jalaali and Gregorian calendar systems to each other
MIT License
307 stars 36 forks source link

نکته‌ی نام‌گذاری + کارایی انواع الگوریتم #19

Closed SCR-IR closed 2 years ago

SCR-IR commented 4 years ago

الگوریتمی که شما برای تبدیل تاریخ استفاده نموده‌اید، کبیسه‌بندی‌ها را طبق لحظه‌ی اعتدال بهاری محاسبه می‌کند. پس بهتر است نام پروژه را «تاریخ جلالی» نگذارید.

الگوریتم جلالی، از فرمول ۳۳ ساله‌ی ثابت استفاده می‌کند (نمونه)؛ امّا الگوریتم شما، از نتایج محاسبات نجومی برای محاسبه‌ی لحظه‌ی اعتدال بهاری بهره می‌گیرد و داده‌های var breaks = [ -61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210, 1635, 2060, 2097, 2192, 2262, 2324, 2394, 2456, 3178 ] را برای کبیسه‌بندی اِعمال می‌کند. پس بهتر است نام آن را «جلالی» نگذارید. شاید همان نام «هجری شمسی» مناسب‌تر باشد.

البته قابل‌ذکر است که الگوریتم‌های جلالی و اعتدالی، هر دو در بازه‌ی زمانی بین سال‌های ۱۱۷۸ تا ۱۶۳۳ هجری‌شمسی، نتایج دقیقاً برابر دارند. امّا در خارج از این محدوده، امکان عدم تطابق در بعضی سال‌ها وجود دارد.

SCR-IR commented 4 years ago
// کبیسه‌بندی جلالی
function isLeap1(year) {
    return ((((year + 12) % 33) % 4) === 1);
}

// کبیسه‌بندی اعتدالی
function isLeap2(jy) {
    var breaks = [-61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210
        , 1635, 2060, 2097, 2192, 2262, 2324, 2394, 2456, 3178];
    var bl = breaks.length
        , jp = breaks[0]
        , jm
        , jump
        , leap
        , n
        , i

    if (jy < jp || jy >= breaks[bl - 1])
        throw new Error('Invalid Jalaali year ' + jy)

    for (i = 1; i < bl; i += 1) {
        jm = breaks[i]
        jump = jm - jp
        if (jy < jm)
            break
        jp = jm
    }
    n = jy - jp

    if (jump - n < 6)
        n = n - jump + div(jump + 4, 33) * 33
    leap = mod(mod(n + 1, 33) - 1, 4)
    if (leap === -1) {
        leap = 4
    }

    return (leap === 0);
}
behrang commented 4 years ago

درست میفرمایید ولی قبلا هم در این مورد گفتگویی داشتیم که در نهایت تصمیم گرفتیم نام را تغییر ندهیم.

این جا را بخوانید: https://github.com/jalaali/moment-jalaali/issues/20

SCR-IR commented 4 years ago

بله، متأسفانه این مشکل برای ما وجود دارد که اکثر برنامه‌نویسان ایرانی، با ماهیت گاهشماری‌ها آشنایی ندارند و صرفاً کلمه‌ی «جلالی» را جستجو می‌کنند.

خب چاره‌ای نیست. امّا اگر بتوانیم در متون راهنما، قدری درمورد تفاوت کبیسه‌بندی‌ها برایشان توضیح دهیم تا سطح آگاهی‌شان افزایش بیابد، خیلی عالی می‌شود.

الگوریتم اعتدالی شما درواقع بسیار سنگین‌تر از این کدهاست. امّا بخش اعظمی از محاسبات، به‌دلیل اینکه یک نتیجه‌ی ثابت را در خروجی داشته‌اند، حذف شده و فقط همین آرایه‌ی کوتاه

    [-61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210
        , 1635, 2060, 2097, 2192, 2262, 2324, 2394, 2456, 3178]

را جایگزین آن کرده‌اند. لذا اگر می‌خواستیم روش محاسبه‌ی همین اعداد را نیز اضافه کنیم، باید محاسبات سنگین نجومی را در یک ماژول بزرگ، اضافه می‌کردیم. این آرایه‌ی کوچک، نماینده‌ی همان ماژول است.

و امّا روش کبیسه‌بندی ۳۳ ساله‌ی ثابت جلالی که صرفاً در یک سطر کوتاه، قابل پیاده‌سازی می‌باشد

    ((((year + 12) % 33) % 4) === 1)

و در بازه‌ی زمانی سال‌های ۱۱۷۸ تا ۱۶۳۳ خروجی آن هیچ تفاوتی با روش اعتدالی ندارد. این روش، برای نرم‌افزارهایی که با زمان حال و معاصر سر‌و‌کار دارند (مثل برنامه‌های بانکی، حسابداری، مدیریت محتوا و غیره...) مناسب‌تر است. چراکه الگوریتم آن بسیار سبُک‌تر بوده و به پردازش کم‌تری احتیاج دارد.

behrang commented 4 years ago

آیا میتوانید یک benchmark از تفاوت این ۲ روش بگیرید تا مثلا در ۱۰ هزار تاریخ مختلف تفاوت کارایی را نشان دهد؟

در مورد آموزش و توضیحات، امکان اضافه کردن توضیحات مورد نظر شما در پروژه وجود دارد. اگر علاقه مند هستید، فایل Readme را ویرایش کنید و یک PR بفرستید.

سپاس

SCR-IR commented 4 years ago

مقایسه انجام شد: https://github.com/SCR-IR/date-algorithms-article/tree/main/JavaScript/performance

behrang commented 4 years ago

ممنون. بسیار هم عالی. حالا اگر میخواهید دیگران هم این را ببینند، در صفحه ی Readme پروژه jalaali-js، کمی توضیحات و لینک به این پروژه خودتان بدهید که دیگران هم ببینند. همچنین در صورتی که کد مشابهی دارید که با این الگوریتم کار میکند، آن را هم مشخص کنید که علاقه مندان بتوانند آن را بگیرند.

zoghal commented 3 years ago

یک سوال داشتم، توی این کتابخانه (pdate.php) از این ارایه استفاده نشده! آیا این کتابخانه از یک الگوریتم دیگری استفاده کرده؟!

الگوریتم اعتدالی شما درواقع بسیار سنگین‌تر از این کدهاست. امّا بخش اعظمی از محاسبات، به‌دلیل اینکه یک نتیجه‌ی ثابت را در خروجی داشته‌اند، حذف شده و فقط همین آرایه‌ی کوتاه

    [-61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210
        , 1635, 2060, 2097, 2192, 2262, 2324, 2394, 2456, 3178]

را جایگزین آن کرده‌اند. لذا اگر می‌خواستیم روش محاسبه‌ی همین اعداد را نیز اضافه کنیم، باید محاسبات سنگین نجومی را در یک ماژول بزرگ، اضافه می‌کردیم. این آرایه‌ی کوچک، نماینده‌ی همان ماژول است.

behrang commented 3 years ago

الگوریتم های مختلفی وجود دارد و ممکن است با هر الگوریتمی نوشته شده باشد.

zoghal commented 3 years ago

خوب منم دنبال همین هستم، پیدا کنم از کدام الگوریتم استفاده شده :))

SCR-IR commented 3 years ago

خوب منم دنبال همین هستم، پیدا کنم از کدام الگوریتم استفاده شده :))

الگوریتم موردنظر شما در آن فایل، یک نسخه‌ی قدیمی منسوخ‌شده است و برای قبل از قرن ۹ هـ شمسی، خروجی منفی دارد. اکنون نسخه‌ی جدید آن در نشانی زیر موجود است که اصلاح شده https://jdf.scr.ir/jdf