این پروژه رو تقدیم می کنم به سازمان مدیریت برنامه نویسان php
در تمامی پروژه ها یی که نیاز به تاریخ شمسی هست. برنامه نویسان با مشکلات خاصی ربرو هستند. در خیلی از تالار های گفتگو بارها و بارها خوندم که برای ذخیره تاریخ و محاسبات دقیق تر بر روی فیلد هایی که نوع انها تاریخ هست. بهتر هست تاریخ رو به صورت میلادی و به صورت timestamp نگهداری کنیم.خوب این روش بسیار کار آمد هست و بهینه . زیرا میتونیم با داشتن یک تاریخ میلادی ، تمامی تاریخ های دیگر همچون شمسی و قمری را استخراج کنیم. اما این روش معایب خودش رو همراه داره.این معایب رو با بیان یک مثال بررسی می کنم:
در Mysql توابع بسیار قدرتمند و مهمی برای کار با مقادیر نوع تاریخ و زمان وجود دارد. که برنامه نویس میتواند بدون درگیر شدن با کد نویسی و با استفاده از یک دستور در خط کوئری خود به نتیجه دلخواه خودش برسه. به عنوان مثال فرض کنید. میخواهیم یک آرشیو ماهیانه برای سیستم خبری ایجاد کنیم.
[sql]
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
[/sql]
برنامه نویس با مثال بالا به راحتی می تواند آرشیو ماهیانه مطالب سیستم خود را ایجاد کند. البته به میلادی.
اما برای آرشیو ماهیانه شمسی آیا جواب گو هست. جواب این هست. خیر!!!.
برای این خواسته برنامه نوبسان روش های متنوعه ای رو بسته به نیاز خود به اجرا میگزارند. عده ای یک فیلد با جدول خود اضافه می کنند و مقادیر تاریخ شمسی را درج می کنند.عده ای دیگر می یایند تاریخ شروع مطالب . تاریخ پایانی رو پیدا میکنند. و بعد از تجزیه و تحلیل کردن آرشیو ماهانه را استخراج می کنند.تمامی روش های موجود دارای پردازش کم و بیش بالایی هستند. تا به نتیجه دلخواه برسند.
من در این پروژه با استفاده از قابلیت تعریف پروسیجر و تابع که در نسخه ۵٫x.x به بعد ارائه شد. یک سری تابع ، همانند توابع MySql شبیه سازی کردم با این تفاوت که این توابع نتیجه را به صورت شمسی بر میگردانند.
در این پروژه ۴ تا بع کاربردی date(),month(),year(), monthname() شبیه سازی شده.
برای استفاده از این توابع شما کافیست مراحل زیر را انجام بدید.
۱- دریافت فایل توابع : دریافت
۲- ایپورت کردن فایل در دیتابیس مورد نظر
بعد از انجام مراحل بالا برای تست توابع می تونید. از این کوئری برای تست استفاده کنید.
[sql]
SELECT pnum(pdate(NOW())),pyear(‘2009-09-22’),pmonth(‘2009-09-22’) , pmonthname( NOW());
[/sql]
مثال آرشیو ماهیانه
[sql]
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
[/sql]
اگر نتیجه گرفتید. پس براحتی می توانید از این توابع کمال استفاده را ببرید.
نکته : در حال حاضر فقط می توان این توابع را از نسخه ۵٫۱٫به بالا استفاده کرد
جهت ادامه روند توسعه و رفع مشکلات این پروژه، من پروژه رو در github قرار دادم.
ممنون از شما پروژه رو در گیت هاب منتشر کردم. ممنون میشم به اسم خودتون این مورد رو فیکس کنید.
https://github.com/zoghal/Presian-Date-for-MySQL
سلام،
ممنون بابت توابع بسیار خوب اما یک مشکل وجود داره. وقتی در یک سرور production تنظیمات binary logging فعال باشه اجازه ی ساخت توابع داده نمیشه:
برای رفع این مشکل مجبور هستیم چک کردن این مورد رو برداریم:
SET GLOBAL log_bin_trust_function_creators = 1;
که کار جالبی نیست بهتره keyword های لازم به توابع اضافه بشن که مشکل حل بشه. من متاسفانه در git بخش issue ها رو باز ندیدم و نشد اونجا مطرح کنم.
متاسفانه فرصت مناسبی درست نداده روی این پروژه کار کنم.
سعی میکنم در اسرع وقت دستی برویش بکشم کلی موارد هست که باید اعمال شود.
از به اشتراک گذاری این توابع واقعا ممنونم.
سلام
ممنون از زحماتتون .از کد شما استفاده کردم و درست کار می کرد . فقط آیا می شه اسم روزهای هفته رو استخراج کرد ؟تاریخ رو بگیره بگه که کدوم روز از هفته س مثل شنبه ،یکشنبه … .
شاد و سر بلند باشید
ممنون از زحماتتون 😉
سلام دوست عزیز من تابع ()time را بعنوان زمان و تاریخ در دیتابیس در جدول tbl_post و فیلد create_time ذخیره میکنم و در کدی که شما قرار دادید نیازی به تبدیل تاریخ به unix ندارم یعنی نیازی به استفاده از FROM_UNIX ندارم چون خروجی ()time خودش unix هست. فانکشن هایی که قرار دادید با موفقیت اجرا شد.
ولی خروجی `
SELECT
pmonth(`create_time`)
as
mo from `tbl_postصحیح نیست ولی
select pmonth(now()) test خروجی صحیحی میده
آیا فانکشن ها روی خروجی ()time کار نمیکند؟
لطفا راهنمایی کنید چه مقداری را بعنوان تاریخ در فیلد create_time قرار دهم که توابع شما بتوانند درست عمل کنند pyear هم خروجی صحیحی نمیدهد و -۶۲۵ را برمیگرداند.
نسخه mysql بنده ۵٫۶٫۲۱ می باشد. استفاده از FROM_UNIX خطا میدهد
لطفا ذر گیتهاب گزارش بدید. تا بررسی کینم.
با سلام
قبل هر چیز بگم بنده زیاد وارد نیستم اما برام جای سوال شد که چرا با یک کد ساده میشه این کارو انجام داد انقدر سختش کرد ؟
قبل از هرچیزی اگه از تایم استمپ استفاده کنیم فقط یک فیلد در جدول خواهد بود که این خودش کارو راحت تر میکنه
پس
function jalali_to_gregorian($j_y,$j_m,$j_d,$mod=”){
$j_y=tr_num($j_y); $j_m=tr_num($j_m); $j_d=tr_num($j_d);/* <= :این سطر ، جزء تابع اصلی نیست */
$d_4=($j_y+1)%4;
$doy_j=($j_m<7)?(($j_m-1)*31)+$j_d:(($j_m-7)*30)+$j_d+186;
$d_33=(int)((($j_y-55)%132)*.0305);
$a=($d_33!=3 and $d_4<=$d_33)?287:286;
$b=(($d_33==1 or $d_33==2) and ($d_33==$d_4 or $d_4==1))?78:(($d_33==3 and $d_4==0)?80:79);
if((int)(($j_y-19)/63)==20){$a–;$b++;}
if($doy_j<=$a){
$gy=$j_y+621; $gd=$doy_j+$b;
}else{
$gy=$j_y+622; $gd=$doy_j-$a;
}
foreach(array(0,31,($gy%4==0)?29:28,31,30,31,30,31,31,30,31,30,31) as $gm=>$v){
if($gd<=$v)break;
$gd-=$v;
}
return($mod==”)?array($gy,$gm,$gd):$gy.$mod.$gm.$mod.$gd;
}
function Jalali_To_TimeStamp($year,$month,$day,$time){
$converttotimestamp=jalali_to_gregorian($year,$month,$day);
$mtime=explode(‘:’,$time);
$converttotimestamp=strtotime(“$converttotimestamp[0]-$converttotimestamp[1]-$converttotimestamp[2]”)+(($mtime[0]*60*60)+($mtime[1]*60)+$mtime[2]);
return $converttotimestamp;
}
با توجه به دو تابع بالا
$mytime=Jalali_To_TimeStamp(‘1394′,’1′,’1′,’00:01’);
SELECT * FROM news WHERE publish_date>$mytime
درود بر شما، اگر در توضیحات خوب دقت کنید مثالی زده با این تابه شما امکان پذیر نیست.
هدف جامع بودن و کاربردپذیر بودن در شرایط مختلف هست. نه فقط یک تبدیل ساده. مثل استفاده از group by روی یک ماه شمسی. اونوقت چی؟
از اپن کارت کد ندزد بابام جان 😀
توابع اپن کارت را بر میداری میاری میزاری اینجا چرا اخه بابام جان 😀
خداوند شفای عاجل به شما اعطا فرماید تا بیشتر از این به خودتون زحمت همچین نظرات شور انگیزی را ندهید.امین
عالی بود – خیلی ممنون از زحمتی که کشیدی
ممنون بخاطر زحمتی که کشیدین. خیلی عالی بود.
موفق باشید