PersianDate4MySQL icon indicating copy to clipboard operation
PersianDate4MySQL copied to clipboard

Wrong Date Conversion

Open shirazdb opened this issue 5 years ago • 11 comments

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 !

shirazdb avatar Oct 20 '20 20:10 shirazdb

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

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

zoghal avatar Nov 17 '20 03:11 zoghal

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

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

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


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

shirazdb avatar Nov 17 '20 03:11 shirazdb

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

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

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

zoghal avatar Nov 17 '20 05:11 zoghal

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

Spitmaan avatar Nov 17 '20 22:11 Spitmaan

@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

mbmonline avatar Oct 10 '21 08:10 mbmonline

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

zoghal avatar Oct 11 '21 00:10 zoghal

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

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

mbmonline avatar Oct 11 '21 06:10 mbmonline

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

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

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

zoghal avatar Oct 21 '21 18:10 zoghal

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

hadifarnoud avatar Dec 07 '22 08:12 hadifarnoud

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

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

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

zoghal avatar Dec 09 '22 08:12 zoghal

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

hadifarnoud avatar Dec 09 '22 13:12 hadifarnoud