امتیاز موضوع:
  • 0 رأی - میانگین امتیازات: 0
  • 1
  • 2
  • 3
  • 4
  • 5
توابع تاریخ شمسی جهت استفاده در Mysq
نویسنده پیام
lord_viper غایب
مدیر کل انجمن
*****

ارسال‌ها: 3,949
موضوع‌ها: 352
تاریخ عضویت: بهمن ۱۳۸۴

تشکرها : 5193
( 9875 تشکر در 2650 ارسال )
ارسال: #1
توابع تاریخ شمسی جهت استفاده در Mysq
در تمامی پروژه ها یی که نیاز به تاریخ شمسی هست. برنامه نویسان با مشکلات خاصی ربرو هستند. در خیلی از تالار های گفتگو بارها و بارها خوندم که برای ذخیره تاریخ و محاسبات دقیق تر بر روی فیلد هایی که نوع انها تاریخ هست. بهتر هست تاریخ رو به صورت میلادی و به صورت timestamp نگهداری کنیم.خوب این روش بسیار کار آمد هست و بهینه . زیرا میتونیم با داشتن یک تاریخ میلادی ، تمامی تاریخ های دیگر همچون شمسی و قمری را استخراج کنیم. اما این روش معایب خودش رو همراه داره.این معایب رو با بیان یک مثال بررسی می کنم:
در Mysql توابع بسیار قدرتمند و مهمی برای کار با مقادیر نوع تاریخ و زمان وجود دارد. که برنامه نویس میتواند بدون درگیر شدن با کد نویسی و با استفاده از یک دستور در خط کوئری خود به نتیجه دلخواه خودش برسه. به عنوان مثال فرض کنید. میخواهیم یک آرشیو ماهیانه برای سیستم خبری ایجاد کنیم.

کد:
SELECT month(FROM_UNIX(regdate) as mo, SELECT year(FROM_UNIX(regdate) as yr, COUNT(*) as total FROM table GROUP BY mo,yr ORDER BY mo DESC yr DESC

برنامه نویس با مثال بالا به راحتی می تواند آرشیو ماهیانه مطالب سیستم خود را ایجاد کند. البته به میلادی.
اما برای آرشیو ماهیانه شمسی آیا جواب گو هست. جواب این هست. خیر!!!.
برای این خواسته برنامه نوبسان روش های متنوعه ای رو بسته به نیاز خود به اجرا میگزارند. عده ای یک فیلد با جدول خود اضافه می کنند و مقادیر تاریخ شمسی را درج می کنند.عده ای دیگر می یایند تاریخ شروع مطالب . تاریخ پایانی رو پیدا میکنند. و بعد از تجزیه و تحلیل کردن آرشیو ماهانه را استخراج می کنند.تمامی روش های موجود دارای پردازش کم و بیش بالایی هستند. تا به نتیجه دلخواه برسند.
من در این پروژه با استفاده از قابلیت تعریف پروسیجر و تابع که در نسخه ۵.x.x به بعد ارائه شد. یک سری تابع ، همانند توابع MySql شبیه سازی کردم با این تفاوت که این توابع نتیجه را به صورت شمسی بر میگردانند.
در این پروژه ۴ تا بع کاربردی date(),month(),year(), monthname() شبیه سازی شده.
برای استفاده از این توابع شما کافیست مراحل زیر را انجام بدید.
۱- دریافت فایل توابع : دریافت
۲- ایپورت کردن فایل در دیتابیس مورد نظر
بعد از انجام مراحل بالا برای تست توابع می تونید. از این کوئری برای تست استفاده کنید.

کد:
1.SELECT pnum(pdate(NOW())),pyear('2009-09-22'),pmonth('2009-09-22') , pmonthname( NOW());

ارشیو ماهیانه

کد:
1.SELECT pmonth(FROM_UNIX(regdate) as mo, SELECT pyear(FROM_UNIX(regdate) as yr, COUNT(*) as total FROM table GROUP BY mo,yr ORDER BY mo DESC yr DESC

اگر نتیجه گرفتید. پس براحتی می توانید از این توابع کمال استفاده را ببرید.
نکته : در حال حاضر فقط می توان این توابع را از نسخه ۵.۱.به بالا استفاده کرد


منبع : soozanchi.ir
۰۶-مهر-۱۳۸۸, ۰۹:۵۷:۵۰
وب سایت ارسال‌ها
پاسخ
تشکر شده توسط : ha_60, alaska
ajlajlajl آفلاین
مدیر بازنشسته
*****

ارسال‌ها: 2,192
موضوع‌ها: 70
تاریخ عضویت: مهر ۱۳۸۴

تشکرها : 932
( 2618 تشکر در 1020 ارسال )
ارسال: #2
RE: توابع تاریخ شمسی جهت استفاده در Mysq
http://saleh.soozanchi.ir/wp-content/upl.../pdate.sql
لینک فایل یادتون رفت. این کداشه:
کد:
-- ----------------------------
-- Function structure for `__mydiv`
-- ----------------------------
DROP FUNCTION IF EXISTS `__mydiv`;
DELIMITER ;;
CREATE DEFINER=`eleroboc_s8em4l0`@`localhost` FUNCTION `__mydiv`(`a` int,`b` int) RETURNS int(11)
BEGIN

# Copyright (C) 2009  Mohammad Saleh Souzanchi
# WebLog : www.saleh.soozanchi.ir
# Version V1.0
return FLOOR( a / b);
END;;
DELIMITER ;

-- ----------------------------
-- Function structure for `_gdmarray`
-- ----------------------------
DROP FUNCTION IF EXISTS `_gdmarray`;
DELIMITER ;;
CREATE DEFINER=`eleroboc_s8em4l0`@`localhost` FUNCTION `_gdmarray`(`m` smallint) RETURNS smallint(2)
BEGIN
# Copyright (C) 2009  Mohammad Saleh Souzanchi
# WebLog : www.saleh.soozanchi.ir
# Version V1.0

    CASE m
        WHEN 0 THEN RETURN 31;
        WHEN 1 THEN RETURN 28;
        WHEN 2 THEN RETURN 31;
        WHEN 3 THEN RETURN 30;
        WHEN 4 THEN RETURN 31;
        WHEN 5 THEN RETURN 30;
        WHEN 6 THEN RETURN 31;
        WHEN 7 THEN RETURN 31;
        WHEN 8 THEN RETURN 30;
        WHEN 9 THEN RETURN 31;
        WHEN 10 THEN RETURN 30;
        WHEN 11 THEN RETURN 31;
    END CASE;
  

END;;
DELIMITER ;

-- ----------------------------
-- Function structure for `_jdmarray`
-- ----------------------------
DROP FUNCTION IF EXISTS `_jdmarray`;
DELIMITER ;;
CREATE DEFINER=`eleroboc_s8em4l0`@`localhost` FUNCTION `_jdmarray`(`m` smallint) RETURNS smallint(2)
BEGIN
# Copyright (C) 2009  Mohammad Saleh Souzanchi
# WebLog : www.saleh.soozanchi.ir
# Version V1.0

    CASE m
        WHEN 0 THEN RETURN 31;
        WHEN 1 THEN RETURN 31;
        WHEN 2 THEN RETURN 31;
        WHEN 3 THEN RETURN 31;
        WHEN 4 THEN RETURN 31;
        WHEN 5 THEN RETURN 31;
        WHEN 6 THEN RETURN 30;
        WHEN 7 THEN RETURN 30;
        WHEN 8 THEN RETURN 30;
        WHEN 9 THEN RETURN 30;
        WHEN 10 THEN RETURN 30;
        WHEN 11 THEN RETURN 29;
    END CASE;
  

END;;
DELIMITER ;

-- ----------------------------
-- Function structure for `pdate`
-- ----------------------------
DROP FUNCTION IF EXISTS `pdate`;
DELIMITER ;;
CREATE DEFINER=`eleroboc_s8em4l0`@`localhost` FUNCTION `pdate`(`gdate` datetime) RETURNS char(100) CHARSET utf8
BEGIN
# Copyright (C) 2009  Mohammad Saleh Souzanchi
# WebLog : www.saleh.soozanchi.ir
# Version V1.0

    DECLARE
        i,
        gy, gm, gd,
        g_day_no,j_day_no, j_np,
        jy,jm,jd INT DEFAULT 0;
    DECLARE resout char(100);
    DECLARE ttime CHAR(20);

    SET gy = YEAR(gdate)-1600;
    SET gm = MONTH(gdate)-1;
    SET gd = DAY(gdate)-1;
    SET ttime = TIME(gdate);
    SET g_day_no = ((365 *  gy) + __mydiv( gy+3, 4 ) - __mydiv( gy+99 , 100 )+ __mydiv ( gy+399, 400 ) );
        SET i = 0;

    WHILE (i < gm) do
        SET  g_day_no = g_day_no + _gdmarray(i);
        SET i = i+1;
    end WHILE;

    if  gm > 1 and (( gy% 4 = 0 and gy%100 <> 0 )) or gy % 400 = 0 THEN
        SET     g_day_no =    g_day_no +1;
    end IF;
    
    SET g_day_no = g_day_no + gd;

    SET j_day_no = g_day_no -79;
    SET j_np =  j_day_no DIV 12053;
    set j_day_no = j_day_no % 12053;
    SET jy = 979 + 33 * j_np + 4 * __mydiv(j_day_no,1461);
    SET j_day_no = j_day_no % 1461;

    if j_day_no >= 366 then
        SET jy = jy + __mydiv(j_day_no-1, 365);
        SET j_day_no =( j_day_no-1) % 365;
    end if;

    SET i = 0;

    WHILE ( i < 11 and j_day_no >= _jdmarray(i) ) do
        SET  j_day_no = j_day_no -  _jdmarray(i);
        SET i = i+1;
    end WHILE;

    SET jm = i+1;
    SET jd = j_day_no+1;
         SET resout = CONCAT_WS ('-',jy,jm,jd);

    if (ttime <> '00:00:00' ) then
        SET resout = CONCAT_WS(' ',resout,ttime);
    END IF;
    
    RETURN      resout;
END;;
DELIMITER ;

-- ----------------------------
-- Function structure for `PMONTH`
-- ----------------------------
DROP FUNCTION IF EXISTS `PMONTH`;
DELIMITER ;;
CREATE DEFINER=`eleroboc_s8em4l0`@`localhost` FUNCTION `PMONTH`(`gdate` datetime) RETURNS char(100) CHARSET utf8
BEGIN
# Copyright (C) 2009  Mohammad Saleh Souzanchi
# WebLog : www.saleh.soozanchi.ir
# Version V1.0

    DECLARE
        i,
        gy, gm, gd,
        g_day_no,j_day_no, j_np,
        jy,jm,jd INT DEFAULT 0;
    DECLARE resout char(100);
    DECLARE ttime CHAR(20);

    SET gy = YEAR(gdate)-1600;
    SET gm = MONTH(gdate)-1;
    SET gd = DAY(gdate)-1;
    SET ttime = TIME(gdate);
    SET g_day_no = ((365 *  gy) + __mydiv( gy+3, 4 ) - __mydiv( gy+99 , 100 )+ __mydiv ( gy+399, 400 ) );
        SET i = 0;

    WHILE (i < gm) do
        SET  g_day_no = g_day_no + _gdmarray(i);
        SET i = i+1;
    end WHILE;

    if  gm > 1 and (( gy% 4 = 0 and gy%100 <> 0 )) or gy % 400 = 0 THEN
        SET     g_day_no =    g_day_no +1;
    end IF;
    
    SET g_day_no = g_day_no + gd;

    SET j_day_no = g_day_no -79;
    SET j_np =  j_day_no DIV 12053;
    set j_day_no = j_day_no % 12053;
    SET jy = 979 + 33 * j_np + 4 * __mydiv(j_day_no,1461);
    SET j_day_no = j_day_no % 1461;

    if j_day_no >= 366 then
        SET jy = jy + __mydiv(j_day_no-1, 365);
        SET j_day_no =( j_day_no-1) % 365;
    end if;

    SET i = 0;

    WHILE ( i < 11 and j_day_no >= _jdmarray(i) ) do
        SET  j_day_no = j_day_no -  _jdmarray(i);
        SET i = i+1;
    end WHILE;

    SET jm = i+1;
    SET jd = j_day_no+1;
    RETURN      jm;
END;;
DELIMITER ;

-- ----------------------------
-- Function structure for `pmonthname`
-- ----------------------------
DROP FUNCTION IF EXISTS `pmonthname`;
DELIMITER ;;
CREATE DEFINER=`eleroboc_s8em4l0`@`localhost` FUNCTION `pmonthname`(`gdate` datetime) RETURNS varchar(100) CHARSET utf8
BEGIN
# Copyright (C) 2009  Mohammad Saleh Souzanchi
# WebLog : www.saleh.soozanchi.ir
# Version V1.0

CASE PMONTH(gdate)
    WHEN 1 THEN     RETURN 'فروردين';
    WHEN 2 THEN RETURN 'ارديبهشت';
    WHEN 3 THEN    RETURN 'خرداد';
    WHEN 4 THEN    RETURN 'تير';
    WHEN 5 THEN    RETURN 'مرداد';
    WHEN 6 THEN     RETURN 'شهريور';
    WHEN 7 THEN    RETURN 'مهر';
    WHEN 8 THEN    RETURN 'آبان';
    WHEN 9 THEN    RETURN 'آذر';
    WHEN 10 THEN RETURN    'دي';
    WHEN 12 THEN RETURN    'بهمن';
    WHEN 12 THEN RETURN    'اسفند';
end CASE;


END;;
DELIMITER ;

-- ----------------------------
-- Function structure for `pyear`
-- ----------------------------
DROP FUNCTION IF EXISTS `pyear`;
DELIMITER ;;
CREATE DEFINER=`eleroboc_s8em4l0`@`localhost` FUNCTION `pyear`(`gdate` datetime) RETURNS char(100) CHARSET utf8
BEGIN
# Copyright (C) 2009  Mohammad Saleh Souzanchi
# WebLog : www.saleh.soozanchi.ir
# Version V1.0

    DECLARE
        i,
        gy, gm, gd,
        g_day_no,j_day_no, j_np,
        jy,jm,jd INT DEFAULT 0;
    DECLARE resout char(100);
    DECLARE ttime CHAR(20);

    SET gy = YEAR(gdate)-1600;
    SET gm = MONTH(gdate)-1;
    SET gd = DAY(gdate)-1;
    SET ttime = TIME(gdate);
    SET g_day_no = ((365 *  gy) + __mydiv( gy+3, 4 ) - __mydiv( gy+99 , 100 )+ __mydiv ( gy+399, 400 ) );
        SET i = 0;

    WHILE (i < gm) do
        SET  g_day_no = g_day_no + _gdmarray(i);
        SET i = i+1;
    end WHILE;

    if  gm > 1 and (( gy% 4 = 0 and gy%100 <> 0 )) or gy % 400 = 0 THEN
        SET     g_day_no =    g_day_no +1;
    end IF;
    
    SET g_day_no = g_day_no + gd;

    SET j_day_no = g_day_no -79;
    SET j_np =  j_day_no DIV 12053;
    set j_day_no = j_day_no % 12053;
    SET jy = 979 + 33 * j_np + 4 * __mydiv(j_day_no,1461);
    SET j_day_no = j_day_no % 1461;

    if j_day_no >= 366 then
        SET jy = jy + __mydiv(j_day_no-1, 365);
        SET j_day_no =( j_day_no-1) % 365;
    end if;

    SET i = 0;

    WHILE ( i < 11 and j_day_no >= _jdmarray(i) ) do
        SET  j_day_no = j_day_no -  _jdmarray(i);
        SET i = i+1;
    end WHILE;

    SET jm = i+1;
    SET jd = j_day_no+1;
    RETURN      jy;
END;;
DELIMITER ;

میزان رای دشمن است!
[تصویر:  cff100.png]
۰۶-مهر-۱۳۸۸, ۱۲:۵۶:۴۱
وب سایت ارسال‌ها
پاسخ
تشکر شده توسط : lord_viper, alaska


موضوعات مرتبط با این موضوع...
موضوع نویسنده پاسخ بازدید آخرین ارسال
  [سوال] اختلاف دوتاریخ تاریخ Ghoghnus 0 1,520 ۲۱-فروردین-۱۳۹۳, ۱۹:۵۱:۴۳
آخرین ارسال: Ghoghnus
  تاریخ میلادی رو چطوری به شمسی تبدیل کنم بوسیله sql iran58 9 20,283 ۱۵-شهریور-۱۳۸۸, ۱۶:۳۲:۲۵
آخرین ارسال: HoseinVig

پرش به انجمن:


کاربرانِ درحال بازدید از این موضوع: 1 مهمان

صفحه‌ی تماس | IranVig | بازگشت به بالا | | بایگانی | پیوند سایتی RSS