zoghal / PersianDate4MySQL

pDate is a Gregorian / Jalali(Shamsi) date convertor functions for MySQL 5.1+
http://saleh.soozanchi.ir/1388/07/05/%D8%AA%D9%88%D8%A7%D8%A8%D8%B9-%D8%AA%D8%A7%D8%B1%DB%8C%D8%AE-%D8%B4%D9%85%D8%B3%DB%8C-%D8%AC%D9%87%D8%AA-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%AF%D8%B1-mysql/
182 stars 67 forks source link

Wrong Date Conversion #25

Open shirazdb opened 4 years ago

shirazdb commented 4 years ago

wrong calculate in below date "2030-03-20" as below :

pdate('2030-03-20') // Result : 1408-12-30

gdatestr('1408/12/29') // Result : 2030-03-20 00:00:00

one miladi date with two persian date result !

zoghal commented 3 years ago

سلام چک کردم دیدم سال ۱۴۰۸ سال کبیسه است. اما چرا تو محاسبه درست عمل نمیشه رو هنوز نمی‌دونم

@Spitmaan شما نظری داری؟ تا الان همچین موردی نداشتیم!

shirazdb commented 3 years ago

سلام. در مورد خطای تبدیل : سال کبیسه به صورت دقیق هر چهارسال یکبار نیست و جمع دقیقه ها و ساعت های اضافه خودشو تو دوره های ۳۲ یا ۳۳ یا ۳۱ ساله نشون میده مثلا بجای اینکه سال ۱۴۰۷ کبیسه باشه دوره پنج ساله میشه و ۱۴۰۸ کبیسه میشه . اینکه چه خطایی در محاسبه کد شما وجود داره نمیدونم اما تقویم های زیادی مشکل مشابه رو دارن در این سال.

طی تست هایی که انجام دادم دوتا تقویم دقیق عمل میکنن یکی تقویم فارسی که در زبانهای برنامه نویسی دات نت تعبیه شده مثل c# و دومی یکی از کامپوننت ها زبان برنامه نویسی دلفی که سورسش تو اینترنت موجوده به اسم xcalendar http://xcalendar.sourceforge.net

البته برای نسخه های پایینتر دلفی مثل دلفی۷ هست که با تغییرات کمی اپدیت میشه اما عملکردشو برای یک دوره ۲۰۰ ساله تست کردم


با تشکر از شما برای طراحی این تقویم مفید و امید به بهتر شدن و رفع این ایراد جزیی

zoghal commented 3 years ago

اما تقویم های زیادی مشکل مشابه رو دارن در این سال.

اتفاقا میخواستم همین تست رو بزنم که شما زحمتش رو کشیدید راستش من هم یکی از این پروژه‌ها رو کانورت کردم و زیاد وارد مباحث محاسباتیش نشدم.

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

Spitmaan commented 3 years ago

@zoghal خیلی وقت بود که به این پروژه سر نزده بودم. تجدید خاطره شد. همونطور که @shirazdb هم اشاره کردن مشکل از اینجا نشات می گیره که محاسبات ما با روز انجام شده در حالی که اگه سال رو تا عدد ساعت و دقیقه در نظر بگیریم هر چند سال دوره چهار ساله به پنج تبدیل می شه. یادم هست که در نظر گرفتن چنین امری به مکان (موقعیت جفرافیایی) محاسبه تقویم هم مربوط می شه. مثلا ممکنه سالی در تهران کبیسه باشه ولی اگه در لس آنجلس حساب کنیم نباشه. جزئیات اش رو به خاطر ندارم ولی به این بر می گرده که لحظه تحویل سال در چه ساعتی از روز قرار می گیره. ممنون از پیگیری همه. امیدوارم در آخر سال میلادی یه وقت خالی باز شه برام تا مشکل رو اساسی بررسی کنم.

mbmonline commented 3 years ago

@zoghal

edit function gdatestr :
BEGIN
# Copyright (C) 2011-2019 Mehran . M . Spitman
# WebLog spitman.azdaa.com
# Version V2.0.0

    DECLARE
        i, j, e, k, mo,
        gy, gm, gd,
        g_day_no, j_day_no, bkab, jmm, mday, g_day_mo, jd, jy, jm,bkab1,j1
    INT DEFAULT 0; /* ### Can't be unsigned int! ### */
    DECLARE resout char(100);
    DECLARE jdd, jyd, jmd, jt varchar(100);
    DECLARE fdate datetime;
    DECLARE indate char(100);
    DECLARE exdate char(100) DEFAULT NULL;

    SET jdd = SUBSTRING_INDEX(jdat, '/', -1);
    SET jt = SUBSTRING_INDEX(jdat, '/', 2);
    SET jyd = SUBSTRING_INDEX(jt, '/', 1);
    SET jmd = SUBSTRING_INDEX(jt, '/', -1);
    SET jd = CAST(jdd as SIGNED);
    SET jy = CAST(jyd as SIGNED);
    SET jm = CAST(jmd as SIGNED);
    SET indate = CONCAT(jyd,'-',jmd,'-',jdd);

     SET bkab = __mymod(jy,33);

  IF (bkab = 1 or bkab= 5 or bkab = 9 or bkab = 13 or bkab = 17 or bkab = 22 or bkab = 26 or bkab = 30) THEN
    SET j=1;
  end IF;

  SET bkab1 = __mymod(jy+1,33);

  IF (bkab1 = 1 or bkab1= 5 or bkab1 = 9 or bkab1 = 13 or bkab1 = 17 or bkab1 = 22 or bkab1 = 26 or bkab1 = 30) THEN
    SET j1=1;
  end IF;

    CASE jm
        WHEN 1 THEN IF jd > _jdmarray2(jm) or jd <= 0 THEN SET e=1; end IF;
        WHEN 2 THEN IF jd > _jdmarray2(jm) or jd <= 0 THEN SET e=1; end IF;
        WHEN 3 THEN IF jd > _jdmarray2(jm) or jd <= 0 THEN SET e=1; end IF;
        WHEN 4 THEN IF jd > _jdmarray2(jm) or jd <= 0 THEN SET e=1; end IF;
        WHEN 5 THEN IF jd > _jdmarray2(jm) or jd <= 0 THEN SET e=1; end IF;
        WHEN 6 THEN IF jd > _jdmarray2(jm) or jd <= 0 THEN SET e=1; end IF;
        WHEN 7 THEN IF jd > _jdmarray2(jm) or jd <= 0 THEN SET e=1; end IF;
        WHEN 8 THEN IF jd > _jdmarray2(jm) or jd <= 0 THEN SET e=1; end IF;
        WHEN 9 THEN IF jd > _jdmarray2(jm) or jd <= 0 THEN SET e=1; end IF;
        WHEN 10 THEN IF jd > _jdmarray2(jm) or jd <= 0 THEN SET e=1; end IF;
        WHEN 11 THEN IF jd > _jdmarray2(jm) or jd <= 0 THEN SET e=1; end IF;
        WHEN 12 THEN IF jd > _jdmarray2(jm)+j or jd <= 0 THEN SET e=1; end IF;
    END CASE;
  IF jm > 12 or jm <= 0 THEN SET e=1; end IF;
  IF jy <= 0 THEN SET e=1; end IF;

  IF e>0 THEN
    SET exdate = 0;
  end IF;

  IF (jm>=11) or (jm=10 and jd>=11 and j=0) or (jm=10 and jd>11 and j=1) THEN
    SET i=1;
  end IF;
  SET gy = jy + 621 + i;

  IF (__mymod(gy,4)=0) THEN
    SET k=1;
  end IF;

    IF (__mymod(gy,100)=0) and (__mymod(gy,400)<>0) THEN
        SET k=0;
    END IF;

  SET jmm=jm-1;

  WHILE (jmm > 0) do
    SET mday=mday+_jdmarray2(jmm);
    SET jmm=jmm-1;
  end WHILE;

  SET j_day_no=(jy-1)*365+(__mydiv(jy,4))+mday+jd;
  SET g_day_no=j_day_no+226899;

  SET g_day_no=g_day_no-(__mydiv(gy-1,4));
  SET g_day_mo=__mymod(g_day_no,365);

    IF (k=1 and j=1) THEN
        IF ((g_day_mo=0) and (exdate is NULL)) THEN
            SET exdate = CONCAT_WS('-',gy,'12','30');
        END IF;
        IF ((g_day_mo=1) and (exdate is NULL)) THEN
            SET exdate = CONCAT_WS('-',gy,'12','31');
        END IF;
    END IF;

    IF ((g_day_mo=0) and (exdate is NULL)) THEN
        SET exdate = CONCAT_WS('-',gy,'12','31');
    END IF;

  SET mo=0;
  SET gm=gm+1;
  while g_day_mo>_gdmarray2(mo,k) do
        SET g_day_mo=g_day_mo-_gdmarray2(mo,k);
    SET mo=mo+1;
    SET gm=gm+1;
  end WHILE;
  SET gd=g_day_mo;

  IF (exdate is NULL) THEN
    SET exdate = CONCAT_WS('-',gy,gm,gd);
  END IF;

  IF (pdate(replace(exdate,'-','/'))!=indate) THEN
    IF (pdate(replace(DATE_ADD(exdate, INTERVAL 1 DAY),'-','/'))=indate) THEN
        SET exdate = DATE_ADD(exdate, INTERVAL 1 DAY);
    END IF;
    IF (pdate(replace(DATE_ADD(exdate, INTERVAL 2 DAY),'-','/'))=indate) THEN
        SET exdate = DATE_ADD(exdate, INTERVAL 2 DAY);
    END IF;
    IF (pdate(replace(DATE_ADD(exdate, INTERVAL 3 DAY),'-','/'))=indate) THEN
        SET exdate = DATE_ADD(exdate, INTERVAL 3 DAY);
    END IF;
    IF (pdate(replace(DATE_ADD(exdate, INTERVAL -1 DAY),'-','/'))=indate) THEN
        SET exdate = DATE_ADD(exdate, INTERVAL -1 DAY);
    END IF;
    IF (pdate(replace(DATE_ADD(exdate, INTERVAL -2 DAY),'-','/'))=indate) THEN
        SET exdate = DATE_ADD(exdate, INTERVAL -2 DAY);
    END IF;
    IF (pdate(replace(DATE_ADD(exdate, INTERVAL -3 DAY),'-','/'))=indate) THEN
        SET exdate = DATE_ADD(exdate, INTERVAL -3 DAY);
    END IF;
  END IF;
  RETURN exdate;
END
zoghal commented 3 years ago

@mbmonline سلام، کمی توضیح بدید داستان چیه؟

mbmonline commented 3 years ago

@mbmonline سلام، کمی توضیح بدید داستان چیه؟

سلام، تابع pdate برای بازه 1200 تا 1600 شمسی درست عمل میکند، اما تابع gdatestr در 116 سال درین بازه 400 ساله خروجی اشتباه دارد. کد تابع gdatestr رو تغییر دادم که در نهایت کار با تابع pdate خودش را چک کرده و تاریخ درست را خروجی می دهد.

zoghal commented 3 years ago

@mbmonline سلام، کمی توضیح بدید داستان چیه؟

سلام، تابع pdate برای بازه 1200 تا 1600 شمسی درست عمل میکند، اما تابع gdatestr در 116 سال درین بازه 400 ساله خروجی اشتباه دارد. کد تابع gdatestr رو تغییر دادم که در نهایت کار با تابع pdate خودش را چک کرده و تاریخ درست را خروجی می دهد.

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

hadifarnoud commented 1 year ago

این باگ حل شده @zoghal ؟

zoghal commented 1 year ago

این باگ حل شده @zoghal ؟

هادی جان سلام، واقعیتش اصلا نمی‌دانم یا بخاطرم نیست که این باگ واقعا درست است یا نه؟! چون مدتی است که من روی این پروژه هیچ تمرکزی نداشتم و تازه نسخه سومش رو استارت زدم. اگر شما هم معتقدید که این مورد یک باگ هست. بفرمایید تا در نسخه سوم بررسی و اصلاحش کنم.

پ.ن: درضمن بدنبال یک جدول با دیتای خوب می‌گردم برای تست کردن توابع این پروژه به عنوان test unit شما پیشنهادی دارید؟

hadifarnoud commented 1 year ago

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