تبدیل تاریخ
آذر ۲۸م, ۱۳۸۸
بارها در این باره، با خیلی ها بحث کردم. حالا یک بار قصد دارم اینجا هم همه چیز را توضیح بدهم، شاید برای بار آخر. مساله تبدیل تاریخ تقریبا مشکل همه هست. هر نو برنامه نویسی، بلافاصله زمانی که نیازمند نوشتن یک برنامه باشد، به اولین موضوعی که فکر میکند، تبدیل تاریخ هجری به میلادی و برعکس است. من کلا با تاریخ قمری کاری ندارم، اهمیتی هم برای من نداشته و ندارد، ولی این بحث شامل تاریخ قمری یا اصولا هر تاریخ دیگری که نیازمند تبدیل به میلادی و برعکس برای آن وجود داشته باشد می شود.
1- تعریف تاریخ در ویندوز
تاریخ در ویندوز، یک عدد اعشاری است، قسمت صحیح آن ، تعداد روزهایی است که از اولین روز اولین ماه سال 1900 گذشته است. قسمت اعشاری هم کسری از روز است که تا لحضه مورد نظر گذشته است. مثلا 0.5 یعنی 12 ظهر، 0.25 یعنی 6 صبح و 0.75 یعنی 6 بعد از ظهر و الی آخر. مثلا عدد 1.5 یعنی 1 روز بعد از روز مبنا، ساعت 12 ظهر. البته مناطق زمانی هم در این مبنا تاثیر دارند و در صورت لزوم باید در نظر گرفته شوند .این تعریف، در دلفی هم رعایت شده است. و تا آنجا که میدانم، در مورد .NET هم به همین صورت است. (اگر کسی اطلاع دقیق تری دارد خبر بدهد، اصولا من از دات نت فراری هستم :) )
2-تعریف تاریخ در لینوکس
تاریخ در لینوکس یک عدد صحیح است، که نشانگر تعداد ثانیه های (در بعض نسخه ها و جاوا میلی ثانیه) پس از نیمه شب روز اول، ماه اول سال 1970 است. البته این تعریف به علت اینکه از ثانیه ها استفاده میکند، با نواحی زمانی نیز تغییر میکند، مثلا برای تاریخ ما، این مبنا سه ساعت و نیم جلوتر است. یعنی در هر منطقه زمانی عدد تاریخ با منطقه زمانی دیگر در یک لحظه متفاوت است. جاوا، PHP و Ansi C هم از این تعریف استفاده میکنند.
3- تبدیل تاریخ
تبدیل تاریخ، همیشه روشی است برای تبدیل یک مبنا (مثلا شمسی) به مبنای دیگر (مثلا میلادی) اما کی؟ در چه شرایطی؟
مثلا ، یکی از بانکها، برای تاریخ شمسی، از یک سیستم خاص استفاده کرده ، مثلا 8 اسفند 88 را به صورت 881208 در دیتابیس ذخیره میکند، روشی بسیار بد که خیلی از قابلیت های فیلدهای تاریخ را از شما میگیرد، کلا به نظر من، برای ذخیره کردن و کلا همه عملیات های مربوط به تاریخ، از تاریخ میلادی و همین فرم استاندارد استفاده شود، ولی برای نمایش تاریخ، به جای استفاده از توابع استاندارد هر زبان (مثلا date در PHP یا TimeToStr در دلفی ) توابعی نوشته و استفاده شود که ورودی آنها تاریخ استاندارد (همان عدد اعشاری در ویندوز یا صحیح در لینوکس) و تاریخ مناسب با فرمت درخواستی چاپ شود. (مثلا در مورد PHP کتابخانه JDF همین کار را انجام داده، که البته من روش کار آن را نمی پسندم، گرچه حرفم به این معنی نیست که از کار آنها استفاده نکرده ام، یا اینکه کار آنها بی ارزش است.)
4- الگوریتم تبدیل
این مساله همیشه برای همه بحث بر انگیز بوده ولی شاید یکی از کار آمد ترین روشها به این صورت است (در مورد ویندوز، و گرنه در مورد لینوکس همین روش استفاده میشود با این تفاوت که به جای روز از ثانیه استفاده میشود) :
1- پیدا کردن اینکه از تاریخ مبدا مورد نظر (مثلا میلادی) تا روز اول و مبنای آن تاریخ به عبارتی 1/1/1 چند روز (لینوکس : چند ثانیه) گذشته است.
2- کم کردن یا افزودن فاصله روزهای(لینوکس : ثانیه) 1/1/1 مبنای مبدا (مثلا میلادی) تا روز 1/1/1 مبنای مقصد (مثلا شمسی) به این صورت، تعداد روزهای(لینوکس : ثانیه های) گذشته از مبنای مقصد را خواهیم داشت.
3- پیدا کردن اینکه این تعداد روزهای(لینوکس : ثانیه های) بدست آمده در گام دوم، چند سال و چند ماه و چند روز خواهد شد. (با احتساب سالهای کبیسه و قوانین و قواعد )
5- بهینه سازی
اما، این روش میتواند بهینه شود. اول ویندوز (در کل بحث اختلاف زمانی را در نظر نمیگیریم، خیلی ساده هر جا لازم است آنرا اضافه کنید):
گام اول را میتوان از سیستم میلادی به هر سیستم دیگری تقریبا حذف کرد. فقط کافی است قسمت صحیح عدد تاریخ را بگیریم، بعلاوه یک عدد ثابت بکنیم (تعداد روزهایی که از روز اول ماه اول سال 1900 از 1/1/1 فاصله دارد و اگر اشتباه نکنم، 693594 روز) و در این صورت عدد مورد نظر را خواهیم داشت، یعنی با یک Type Cast ساده، و یک تفریق، نه یکسری محاسبات وقت گیر و بیخود.
از طرفی برای تبدیل هر نوع تاریخی به تاریخ میلادی یک روش ساده هست. مثلا برای شمسی کافی است بفهمیم که روز مورد نظر چند روز بعد از روز (اگر اشتباه نکنم) 10 دی ماه 1348 است. یعنی در حقیقت نیازی به یک تبدیل واقعی نیست، در مورد قسمت ساعت هم که هیچ تغییری لازم نیست، چون در مبناهای مختلف که ساعت مثلا 12 متفاوت از ساعت 12 مبنای دیگر نیست (در یک منطقه زمانی)
و لینوکس. همین روش بالایی کاملا موثر خواهد بود، یعنی بهینه سازی دقیقا به همان شکل ممکن است، فقط به جای روز از ثانیه استفاده میشود، یا برای راحت تر شدن، ثانیه ها را به روز تبدیل میکنیم. البته باید توجه کرد مبنا سال 1970 است نه 1900
6-دانلود کد
خوب این بهینه سازی میتواند سرعت را بالا ببرد، دقت بیشتری دارد و بسیار ساده و قابل فهم خواهد بود. من الگوریتم این تبدیل برای PHP و دلفی را از قبل پیاده سازی کرده ام (نسخه نسبتا کاملی هم برای جاوا هست که بعد از کمی تغییرات، منتشر میشود) و آنرا در این آدرس قرار داده ام. علاوه بر آن، ضمن تشکر فراوان از کتابخانه JDF و کلیه کسانی که آنرا ایجاد کرده و در اختیار همگان گذاشته اند، یک مقایسه هم برای این دو ایجاد کرده ام که در این آدرس قابل مشاهده است . البته توصیه میکنم به جای استفاده از این سورس از سورس به روز شده SVN استفاده کنید، چون در هر زمان که مشکلی در این کد پیدا شود اصلاح آن در SVN قرار خواهد گرفت.
آدرس SVN :
https://jdate-project.svn.sourceforge.net/svnroot/jdate-project
امروز کار این دوستان رو هم دیدم : http://iranphp.org/node/6 کارشون خوبه و تو این زمینه میتونه خیلی مفید باشه،این دوستان از همون الگوریتم قدیمی استفاده کردن ولی تابع date رو خیلی خوب شبیه سازی کردن. به هر حال برای اینکه این پست تکمیل بشه اون رو اینجا گفتم و علاوه بر اون چون sf.net ایران رو تحریم کرده من یه نسخه از فایل تبدیل تاریخ خودمو همین جا برای دانلود میذارم.


سلام
چرا از dotNet Framework فراری هستی؟ یعنی هنوز بر روی دلفی کد های Native می زنی؟ من از قدیما میشناسمت.
فقط یک مشکلی واسه نوشتن این کامنت داشتم بی چاره شدم تا بتونم یه کلمه انگلیسی بنویسم. چرا همه چیزو به زور می خواد فارسی کنه؟ البته اگه یکی فینگلیش می نوشت خوب ترجمه می کرد و خیلی ایده خوبیه ولی وقتی میخوایی فارسی بنویسی و از اصطلاحات استفاده کنی گیر ناجوری به آدم میده
برای تبدیل تاریخ در دات نت هم خود مایکروسافت توی نسخه ۲ به بعد یک کلاس استاندارد برای این تبدیل ساخته که ما همیشه از اون استفاده می کنیم.
موافقید یا نه :
0
0
۱- نه من کلا با دات نت کاری ندارم، حتی میشه گفت با دلفی هم کاری ندارم. (اینو دروغ گفتم!! هنوز هم دلفی کار میکنم) ولی من تقریبا برنامه نویسی برای Desktop رو بیخیال شدم بیشتر وب کار میکنم. در ثانی تا Java هست کی میره تو غار!
۲- Ctrl+g این رو فعال و غیر فعال میکنه، منتها باید اینو تو یه جایی توی قالب بزارم! (معذرت که اذیت شدی!)
۳- در مورد اون قضیه تبدیل تاریخ توی دات نت، من دیدم یه چند تایی ولی این که میگی ندیدم. و کلا خوبه دیگه راحت شدید! البته من بیشتر داشتم درباره تئوری میگفتم، و قصد ندارم که حتی امتحانی هم که شده واسه دات نت کد بنویسم.
۴- منم شما رو میشناسم؟؟؟
موافقید یا نه :
0
0
Hidden due to low comment rating. Click here to see.
دیگران موافق نیستند، نظر شما :
1
7
به شما ربطی داره؟؟ هر جوری دوست داشته باشم مینویسم. دوست نداری، نخون. اصلا از ده کیلومتری اینجا هم رد نشو. حرفه ای نیست؟ وبلاگ حرفه ای تو وب کم نداریم. برو همونجا ها.خیلی ساده.
موافقید یا نه :
3
0
سلام
آقا ما همیشه به یادتیم ولی دستمون ازت کوتاهه
چند باری اومدم سری بهت بزنم پیداتون نکردم
موافقید یا نه :
0
0
سلام فرود جان عزیزم.
مطالب وبلاگت بسیار مفید و ارزشمند است.از اینکه فعال و همشه خوب می نویسی خوشحالم.
می تونید این مقاله رو هم مطالعه کنید
http://joomfa.org/jajali-date-shamsi-date-miladi-persian.html
اگر جایی اشکالی داشت ممنون میشم اشتباهش رو اصلاح کنید
تشکر
علوی نیک
جومفا
موافقید یا نه :
3
0
با سلام
خواستم از مقاله ی مفیدتون تشکر کنم.واسه من که به بلاگهای فارسی کمتر مراجعه می کنم اینطور نحوه ی نظر دادن بعضی افراد متعجبم می کنه.در دنیای opensource که همه برخورد دوستانه جهت یک هدف مشترک دارند اینطور رفتارها واقعا عجیبه.
من قصد تبدیل تاریخ کامپوننت fabrik.com az )fabrikarبه هجری رو دارم که تا به حال موفق نبودم.اگر کسی در این مورد کار کرده و می خواد کارش رو رایگان یا در ازای دریافت مبلغی انجام بده لطفا اعلام کنه.
با سپاس
موافقید یا نه :
1
0
سلام
میشه کمک کنین تا تاریخ ipb3 رو فارسی کنیم؟
برای نسخه ۲.۳۶ تونستم با بچه هاییرانفپ.نت بکنم
ولی زیاد پهپ م خوب نیست برای این نسخه نتونستم
مرسی برای کمک
موافقید یا نه :
0
0
چه کمکی میتونم بکنم؟ من اصولا با سیستم IPB آشنا نیستم. اما اگه ی از دستم برمیاد خوشحال میشم کمک کنم.
موافقید یا نه :
0
0