تقویم فارسی برای php 5.3

شش ماه پیش امید متقی توی وبلاگش در مورد پشتیبانی php 5.3 از تقویم فارسی نوشته بود. این امکان با اضافه شدن اکستنشن Intl به اکستنشن های پیشفرض php در نسخه 5.3 به بعد فراهم شده. این اکستنشن در واقع امکان کار با کتابخونه ICU رو برای php فراهم میکنه.  دیدم کار با این توابع یک کمی مشکله تصمیم گرفتم با این توابع یک توسعه برای کلاس DateTime بنویسم که کار باهاش آسون بشه. این شد که چهار ماه پیش این کلاس رو نوشتم (اینجا) ولی خوب به خاطر مشغله کاری و تنبلی وقت نکردم در موردش چیزی بنویسیم.

با این کلاس در واقع همون امکانات DateTime رو به اضافه پشتیبانی از تقویم‌ها و زبان‌های مختلف دارید. برای مثال:

$date = new IntlDateTime('now', 'Asia/Tehran', 'persian', 'fa');
echo $date->format('yyyy/MM/dd'); // ۱۳۸۹/۰۲/۱۰
echo $date->format('E dd LLL yyyy'); // جمعه ۱۰ اردیبهشت ۱۳۸۹

نحوه کارش مشابه کلاس DateTime هست با تفاوت های زیر:

  1. پارامتر اول علاوه بر رشته میتونه timestamp و یا یک شی از نوع DateTime باشه.
  2. در پارامتر اول کاراکترهای عددی به هر زبانی میتوانند باشند. یعنی اگر رشته شما شامل اعداد فارسی یا عربی یا ترکیبی از اونها و یا هر زبون دیگه ای که باشه با این کلاس بدون مشکل کار میکنه. (این قسمت رو به لطف کلاس NumberFormatter که یکی دیگه از امکانات intl هست نوشتم )
  3. برای پارامتر دوم به جای شی DateTimeZone میشه از رشته هم استفاده کرد.
  4. پارامتر سوم نوع تقویم رو مشخص میکنه که میتونه Buddhist, Chinese, Coptic, Ethiopic, Gregorian, Hebrew, Indian, Islamic, Islamic-Civil, Japanese, Persian, Taiwan باشه. (دم ICU گرم فکر کنم فقط تقویم مایاها رو یادشون رفته پیاده کنن!)
  5. پارامتر چهارم زبانه برای مثال میتونه fa ، fa_IR ، en ، en_US ، en_UK و … باشه
  6. یکی از سختی های کار با کلاس IntlDateFormatter اینه که باید حتما pattern تاریخ رو مشخص کنید ولی کلاس IntlDateTime در اکثر مواقع خودش میتونه pattern رو تشخیص بده و برای موارد خاص که pattern توسط کلاس قابل تشخیص نباشه باید خودتون pattern رو به عنوان پارامتر پنجم بدید.
  7. برای استفاده از متد format باید pattern رو به فرمتی که ICU قبول میکنه بدید. برای استفاده از فرمت خود php  از متد classicFormat استفاده کنید.
  8. متد فرمت timezone هم به عنوان پارامتر دوم قبول میکنه (بدون تغییر timezone داخلی شی)
  9. کلاس IntlDateFormatter با تایم زون هایی که DST دارن مشکل داره که من توی IntlDateTime رفعش کردم.
  10. تنها اشکالش اینه که با تاریخ های خارج از محدوده timestamp کار نمیکنه که به عنوان باگ برای IntlDateFormatter گزارش دادم. (آپدیت: این مشکل هم رفع شد.)
  11. متد modify تاریخ رو مطابق با تقویمی که ست شده ویرایش میکنه (مثلا برای تاریخ امروز +1 month رو اگر روی تقویم میلادی اجرا کنی 30 روز و اگر روی تقویم هجری شمسی اجرا کنی 31 روز تاریخ رو جلو میبره)
  12. با متد setCalendar و setLocale تقویم و زبان رو میتونید عوض کنید که مثلا برای تبدیل تاریخ از میلادی به شمسی و بالعکس کاربرد داره.

یک تعداد testcase هم براش نوشتم که برای آشنایی با طرز کار کلاس میتونین یک نگاهی بهش بندازین. البته هنوز تستهاش کامل نیست. بعدا اگه فرصت کنم کاملش میکنم.

همونطور که گفتم این کلاس فقط روی php 5.3 به بعد کار میکنه اگر دنبال کدی میگردید که روی php 5 هم کار کنه یک کلاس دیگه نوشتم (اینجا) که البته محدودیت هایی نسبت به این کلاس داره (در حال حاضر فقط تقویم فارسی و میلادی رو ساپورت میکنه ولی قابل گسترش برای سایر تقویم ها هست. از الگوی factory استفاده میکنه و بعد از ایجاد شی دیگه تقویم قابل تغییر نیست.)

22 دیدگاه برای “تقویم فارسی برای php 5.3”

  1. میثم گفته:

    سلام
    من این کدی که شما نوشتین رو تست کردم،
    فقط اعداد رو فارسی میکنه، مثلا خروجی : پنجشنبه ۱۳ مهٔ ۲۰۱۰
    ولی با استفاده از همون نوع که آقای متقی دادن (کد خود php) تاریخ فارسی و به درستی نمایش داده میشه.
    بازم ممنون به خاطر توسعه دهنده‌گی‌تون.
    موفق باشید.

  2. علی گفته:

    @میثم:
    احتمالا شما پارامتر سوم رو پاس ندادی به کلاس (یا اشتباه تایپی داشته). چون این پارامتر نوع تقویم رو مشخص میکنه و اگر خالی باشه و یا مقدار نامعتبری داشته باشه تقویم پیشفرض یعنی gregorian استفاده میشه.

  3. محمود گفته:

    با سلام من با wamp 2i کار می کنم و ورژن php هم 5.3 هست ولی خطای داره :
    Fatal error: Class ‘IntlDateTime’ not found in C:\wamp\www\fdate.php on line 13
    چگونه میشه مشکل رو بر طرف کرد.
    با تشکر

  4. علی گفته:

    سلام

    شما باید فایل IntlDateTime.php رو توی برنامه تون include کنید.

    از لینک زیر میتونید دانلودش کنید:
    http://github.com/farhadi/IntlDateTime/zipball/master

  5. پویا گفته:

    ارور زیر علتش چی میتونه باشه؟
    Class ‘NumberFormatter’ not found
    با تشکر از زحمتت

  6. Adam گفته:

    # امروز +1 month رو اگر روی تقویم میلادی اجرا کنی 30 روز و اگر روی تقویم هجری شمسی اجرا کنی 31 روز تاریخ رو جلو میبره)

  7. علی گفته:

    @پویا: مطمئنی که php 5.3 به بالا داری؟

  8. مهران گفته:

    سلام
    من هم با من با wamp 2i کار می کنم و ورژن php هم 5.3 هست ولی خطای داره :
    Class ‘NumberFormatter’ not found را میده!
    میشه از متد بالا در یک smarty outputfilter استفاده کرد؟ چطوری؟
    ممنون

  9. حمید گفته:

    سلام آقای فرهادی.
    برنامه ی دیگه ای برای توسعه اش ندارید؟
    مثلا قصد ندارید تقویم هجری رو هم بهش اضافه کنید؟

  10. علی گفته:

    @مهران:
    کلاس NumberFormatter مربوط به اکستنشن intl میشه که توی 5.3 به بعد built-in هست.
    در مورد اسمارتی از نمونه کدهای خودش برای نوشتن modifier استفاده کن.

    @حمید:
    اگه منظورت این کلاسی که برای 5.3 نوشتم هست که همه تقویم ها رو ساپورت میکنه برای تقویم هجری باید موقع New کردن پارامتر سوم رو Islamic-Civil بدی.

  11. سینا گفته:

    سلام علی
    این کلاسی که نوشتی خیلی مفیده می خواستم بدونم که وضعیت به چه شکله. وقت می کنی که بازم روی کار کنی و توسعه ش بدی؟

  12. ناشناس گفته:

    من هم با من با wamp 2i کار می کنم و ورژن php هم 5.3 هست ولی خطای داره :
    Class ‘NumberFormatter’ not found را میده!

  13. علی گفته:

    @سینا:
    سلام
    اگه پیشنهاد یا امکان خاصی مد نظرت هست که بهش اضافه بشه اینجا گزارش بده.

  14. صادق گفته:

    خط ۶۶ : تابع getFormatter
    را عوض کردم به
    $calendar==”gregorian”?IntlDateFormatter::GREGORIAN:IntlDateFormatter::TRADITIONAL, $pattern);

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

  15. علی گفته:

    @صادق:
    من کاربرد این پارامتر $calendar توی IntlDateFormatter رو نفهمیدم چیه. من که همیشه IntlDateFormatter::GREGORIAN پاس میدم و درست هم کار میکنه. همه تست هایی که نوشتم (توی شاخه tests) پاس میشه.

    اگه برای شما درست کار نمیکنه لطفا یک تست بنویسید که fail بشه.

  16. نیما گفته:

    سلام. میشه لطف کنید و مراحل استفاده از این تابع را توضیح بدید. مثلا اینکه اگر کسی از codeigniter استفاده میکتد، IntlDateTime را کجا باید کپی کند و بقیه مراحل ….

  17. علی گفته:

    @نیما:
    تو چه شاخه ای باشه مهم نیست کافیه include اش کنی و مشابه کدی که نوشتم ازش استفاده کنی.
    البته فریم ورکها معمولا برای library ها یک شاخه دارند که بهتره فایل رو اونجا بذاری.

  18. محمد گفته:

    منم از wamp2 استفاده می کنم با php 5.3.0 ولی بازم ارور میده

    Fatal error: Class ‘NumberFormatter’ not found in D:\wamp\www\IntlDateTime.php on line 70

    البته میخوام با wamp2.1e امتحان کنم که جدید با php 5.3.5 ببیینم چی میشه!

  19. هادی گفته:

    سلام ایا از این تقویم شما می شود در برنامه های crm استفاده نمود اگر امکانش هست باید کار خاصی انجام داد؟

  20. علی گفته:

    در مورد خطای پیدا نشدن کلاس NumberFormatter متوجه شدم که در ابونتو اکستنش intl به صورت پیشفرض نصب نیست که باعث میشه این خطا به وجود بیاد.
    برای رفع این خطا باید پکیج php5-intl رو نصب کنید.

  21. محمد گفته:

    سلام
    من نمیتونم این افزونه رو روی ویندوز استفاده کنم
    خیلی هم گشتم اما علت رو متوجه نشدم
    آیا شما میتوانید راهنمایی کنید؟

  22. فراز گفته:

    دوستان که با خطا مواجه میشوند سری به لینک زیر بزنند:
    http://www.tiv.net/2010/12/php-intl-extension-windows-apache.html
    خلاصه مهمترین اشکال اینستکه باید مسیر فایل پی اچ پی به
    path
    ویندوز اضافه شود مثل
    E:\xampp\php
    لازم به توضیح نیست که نسخه 5.3 و در فایل
    php.ini
    این دو خط حتما باشند
    extension_dir=”C:\Program Files\PHP\ext”
    extension=php_intl.dll

    فایلهای زیر در پوشه اکستنشن بالایی دیده شوند
    icudt*.dll
    icuin*.dll
    icuio*.dll
    icule*.dll
    iculx*.dll
    icutu*.dll
    icuuc*.dll
    بجای ستاره یک عدد بسته به نسخه تان دارید

    و در” پی اچ پی اینفو “حتما قسمت
    INTL
    نمایش داده شود . موفق باشید

دیدگاهی بنویسید