رفتن به متن راهنما
همه‌ی راهنماها

تقویم عبری

کلاس تغییرناپذیر Hebrew با شمارهٔ ترتیبی ماه‌ها، آدار اول و دوم در سال کبیسه و نام ماه به انگلیسی و عبری و فارسی. ساخت، خواندن، قالب‌بندی، جابه‌جایی و اختلاف تاریخ.

برنامه RTLY-Kit 0.3.0آخرین بررسی زمان خواندن 12 دقیقه

در این صفحه

این کلاس چه می‌کند

کلاس RtlyKit\Calendar\Hebrew یک تاریخ و زمان در تقویم عبری (یهودی) است و تغییر نمی‌کند. با PHP خالص نوشته شده و به ext-calendar نیاز ندارد. تقویم حسابی ثابت را پیاده می‌کند: مولاد تیشری، چهار تعویق به نام دهییوت، و سال‌هایی با ۳۵۳، ۳۵۴ یا ۳۵۵ روز (عادی) و ۳۸۳، ۳۸۴ یا ۳۸۵ روز (کبیسه). مثل دو تقویم دیگر، یک DateTimeImmutable زیرش است و قرارداد CalendarDate را دارد (تبدیل و مقایسهٔ تاریخ‌ها).

PHP
<?php
require 'vendor/autoload.php';

use RtlyKit\Calendar\Hebrew;
use RtlyKit\Exceptions\InvalidDateException;
use function RtlyKit\hebrew_date;   // تابع کمکی فضای‌نام‌دار، همان Hebrew::make()

$utc = new DateTimeZone('UTC');

خوب است بدانید. روز عبری در اصل از غروب شروع می‌شود، ولی این کلاس مثل بقیهٔ تقویم‌های کتابخانه تاریخ را در نیمه‌شب مدنی عوض می‌کند. پس برای ساعت عصر یا شب (مثلاً 21:30 یا 23:59 در 2026-03-21) همان تاریخ عبریِ همان روز مدنی را می‌گیرید (5786/07/03)، هرچند در شمارش دینی تاریخ بعدی از غروب شروع شده است. کلاس تعطیلات، پاراشا و شمارش عومر را حساب نمی‌کند.

شمارهٔ ماه‌ها

ماه‌ها بر اساس جایگاهشان در سال، از تیشری (آغاز سال مدنی) شماره می‌خورند. در سال کبیسه آدار اول و آدار دوم دو ماه جدا هستند:

  • ماه‌های ۱ تا ۵ همیشه تیشری، حشوان، کسلو، طوت و شواط‌اند.
  • سال عادی: ۶ = آدار، ۷ = نیسان، ۸ = ایار، ۹ = سیوان، ۱۰ = تموز، ۱۱ = آو، ۱۲ = الول.
  • سال کبیسه: ۶ = آدار اول، ۷ = آدار دوم، ۸ = نیسان، ۹ = ایار، ۱۰ = سیوان، ۱۱ = تموز، ۱۲ = آو، ۱۳ = الول.

شماره‌گذاری Hebcal نیست. این روش با Hebcal (نیسان = ۱) و با ext-calendar خود PHP فرق دارد. الول در سال عادی ماه ۱۲ و در سال کبیسه ماه ۱۳ است. نیسان هم ماه ۷ یا ۸ است. شمارهٔ ماه را از خود Hebrew بگیرید (getMonth()، monthName()، monthsInYear()) و از جدول کتابخانهٔ دیگر کپی نکنید.

PHP
foreach ([5784, 5785] as $y) {
    $a = [];
    for ($m = 1; $m <= Hebrew::monthsInYear($y); $m++) {
        $a[] = $m.':'.Hebrew::monthName($y, $m).'('.Hebrew::daysInMonth($y, $m).')';
    }
    echo $y, ' ', implode(' ', $a), "\n";
}
// 5784 1:Tishrei(30) 2:Cheshvan(29) 3:Kislev(29) 4:Tevet(29) 5:Shevat(30) 6:Adar I(30) 7:Adar II(29) 8:Nisan(30) 9:Iyar(29) 10:Sivan(30) 11:Tammuz(29) 12:Av(30) 13:Elul(29)
// 5785 1:Tishrei(30) 2:Cheshvan(30) 3:Kislev(30) 4:Tevet(29) 5:Shevat(30) 6:Adar(29) 7:Nisan(30) 8:Iyar(29) 9:Sivan(30) 10:Tammuz(29) 11:Av(30) 12:Elul(29)

Hebrew::monthName($year, $month, $locale = 'en') زبان‌های en، he و fa را دارد (زبان ناشناخته مثل en رفتار می‌کند). در سال عادی، ماه ۶ فقط «آدار» است.

ساخت تاریخ

متد Hebrew::create($year, $month, $day, $hour = 0, $minute = 0, $second = 0, $timezone = null) طول واقعی ماه را در همان سال چک می‌کند (حشوان و کسلو بین ۲۹ و ۳۰ روز تغییر می‌کنند).

PHP
$e = Hebrew::create(5785, 1, 1, 0, 0, 0, $utc);

echo $e;                                   // 5785/01/01 00:00:00
echo $e->toGregorian()->format('Y-m-d');   // 2024-10-03
echo Hebrew::create(5785, 7, 15, 0, 0, 0, $utc)->toGregorian()->format('Y-m-d');  // 2025-04-13  (۱۵ نیسان 5785)
echo Hebrew::create(5786, 1, 10, 0, 0, 0, $utc)->toGregorian()->format('Y-m-d l'); // 2025-10-02 Thursday

متد Hebrew::make($time = null, $timezone = null) این ورودی‌ها را قبول می‌کند: DateTimeInterface، هر CalendarDate، زمان یونیکس، رشته یا null. تابع کمکی‌اش hebrew_date() است و همان ورودی‌ها را می‌گیرد، جز CalendarDate. اگر خود یک شیء Hebrew بدهید، همان بدون تغییر برمی‌گردد.

PHP
echo Hebrew::make('2025-10-07', $utc);                       // 5786/01/15 00:00:00
echo hebrew_date('2025-10-07')->format('Y/m/d F');           // 5786/01/15 Tishrei
echo Hebrew::make('5785/01/10', $utc);                       // 5785/01/10 00:00:00
echo Hebrew::make('0001-09-06')->format('Y/m/d');            // 3762/01/01

رشته چطور خوانده می‌شود

  1. رقم‌های فارسی و عربی به انگلیسی تبدیل می‌شوند و فاصله‌های دو سر رشته حذف می‌شود. فاصلهٔ بدون شکست، نیم‌فاصله (ZWNJ) و نشانه‌های LRM و RLM هم فاصله حساب می‌شوند. رشتهٔ خالی، یا رشته‌ای که بایت NUL دارد، InvalidDateException می‌دهد.
  2. رشته‌ای که دقیقاً به شکل Y/m/d یا Y-m-d باشد (سال ۴ یا ۵ رقمی) و سالش ۳۰۰۰ یا بیشتر باشد، تاریخ عبری است و ماه همان شمارهٔ ترتیبی بالاست. بعد از آن می‌تواند یک فاصله یا T یا t بیاید، سپس H:i[:s[.u]] و یک نشانهٔ منطقه (Z، +03:30، +0330 یا +03). نشانهٔ منطقه، منطقهٔ زمانی نتیجه را تعیین می‌کند و اگر آرگومان $timezone هم بدهید، نتیجه به آن منطقه تبدیل می‌شود. سال پنج‌رقمی هم کار می‌کند، تا '13759/01/01'، و toDateString() متنی می‌دهد که make() دوباره می‌خواند. برای تاریخ میلادیِ سال ۳۰۰۰ به بعد یک DateTimeImmutable بدهید. (این آستانه عکس جلالی و هجری است. آن‌ها سال کمتر از ۱۷۰۰ را مال خودشان می‌دانند.)
  3. متنی که شروعش همین شکل است ولی چیزی کم یا زیاد دارد (نام منطقه بعد از ساعت، PM) و رشتهٔ فقط‌رقمِ ۳ تا ۸ رقمی مثل '5785' InvalidDateException می‌دهند.
  4. هر رشتهٔ دیگر میلادی یا متن آزاد خوانده می‌شود، از جمله هشت رقمی که با سالی زیر ۳۰۰۰ شروع شود ('20240101'). رشتهٔ میلادی با روز غیرممکن، مثل '2024-02-30'، InvalidDateException می‌دهد.

پس '5785/01/10' عبری است و '2025-10-07' میلادی. رشتهٔ '3000/01/01' سال عبری ۳۰۰۰ حساب می‌شود، که از کمترین سالِ پشتیبانی‌شده کوچک‌تر است و خطای Invalid Hebrew date: 3000/1/1 می‌دهد. متن سال منفی ندارد: make('-0100/01/01') خطا می‌دهد، پس برای آن‌ها از create() یا زمان یونیکس استفاده کنید.

با قالب: createFromFormat()

متد Hebrew::createFromFormat($format, $time, $timezone = null) مثل نسخهٔ جلالی کار می‌کند، با سال عبری و شمارهٔ ترتیبی ماه مثل create(). توکن‌های مجاز d j m n Y H G i s g h A a و بک‌اسلش‌اند. توکن‌های دیگر (z y F M D l S e T P O p u v) InvalidDateException می‌دهند و نام توکن را می‌گویند. قالب U به‌تنهایی زمان یونیکس را می‌خواند. Y حداکثر ۴ رقم می‌خواند، پس سال‌های ۱۰۰۰۰ به بعد create() لازم دارند.

PHP
echo Hebrew::createFromFormat('Y-n-j', '5784-13-29'); // 5784/13/29 00:00:00 (a leap year has 13 months)

serialize() فقط لحظه را در یک آرایهٔ کوچک نسخه‌دار نگه می‌دارد. unserialize() بازه را دوباره چک می‌کند و برای داده‌های خراب InvalidDateException می‌دهد.

بازهٔ سال و خطاها

سال عبری از Hebrew::MIN_YEAR = 3762 تا Hebrew::MAX_YEAR = 13759 پشتیبانی می‌شود. این همان بخشی است که در سال‌های میلادی ۱ تا ۹۹۹۹ می‌افتد. اولین روز، اول تیشری ۳۷۶۲ (برابر 0001-09-06) و آخرین روز، آخر الول ۱۳۷۵۹ (برابر 9999-11-03) است. هر چیز بیرون از آن InvalidDateException می‌دهد. متد isValid() به‌جای خطا false می‌دهد.

PHP
foreach ([[3761, 1, 1], [13760, 1, 1], [5785, 13, 1], [5785, 3, 31]] as [$y, $m, $d]) {
    try { Hebrew::create($y, $m, $d); }
    catch (InvalidDateException $x) { echo $x->getMessage(), "\n"; }
}
// Invalid Hebrew date: 3761/1/1
// Invalid Hebrew date: 13760/1/1
// Invalid Hebrew date: 5785/13/1       (5785 سال عادی است: ۱۲ ماه)
// Invalid Hebrew date: 5785/3/31

echo Hebrew::create(5784, 13, 1) instanceof Hebrew ? 'ok' : '';   // ok  (5784 سال کبیسه است)

try { Hebrew::make('0001-01-01'); }
catch (InvalidDateException $x) { echo $x->getMessage(); }
// Date out of the supported Hebrew range (3762..13759): 3761

متدهای محاسبه‌ای daysInYear() و daysInMonth() سال‌های ۱ تا ۱۳۷۵۹ را قبول می‌کنند (سال ۰ خطای Hebrew year out of the supported range: 0 می‌دهد). متد monthName() فقط شمارهٔ ماه را بررسی می‌کند. فقط ساخت تاریخ از ۳۷۶۲ شروع می‌شود.

خواندن مقدارها

گیرنده‌ها همان قرارداد مشترک‌اند (getYear()، getMonth()، getDay()، اجزای زمان، getTimestamp()، getTimezone()، toGregorian()، toDateString()، toDateTimeString()). getMonth() همان شمارهٔ ترتیبی ماه را می‌دهد.

شمارهٔ روز هفته

getDayOfWeek() و توکن w از یکشنبه شروع می‌کنند: ۰ = یکشنبه تا ۶ = شنبه (مثل هجری و PHP، برعکس جلالی). توکن N شمارهٔ ISO است (دوشنبه = ۱).

PHP
echo $e->getDayOfWeek();   // 4   (اول تیشری 5785 پنجشنبه بود)
foreach (range(0, 6) as $i) { echo $e->addDays($i)->getDayOfWeek(); }  // 4560123

قالب‌بندی

format($pattern = 'Y/m/d H:i:s', $locale = 'en') با زبان en، he یا fa. رقم‌ها همیشه لاتین‌اند. بک‌اسلش نویسهٔ بعدی را همان‌طور که هست می‌نویسد (بک‌اسلشِ آخر الگو نادیده گرفته می‌شود). الگوی بلندتر از Hebrew::MAX_FORMAT_LENGTH (۲۵۶ بایت) InvalidDateException با کد input_too_long می‌دهد.

PHP
echo $e->format('l j F Y');         // Thursday 1 Tishrei 5785
echo $e->format('l j F Y', 'he');   // חמישי 1 תשרי 5785
echo $e->format('l j F Y', 'fa');   // پنجشنبه 1 تشری 5785

echo Hebrew::create(5784, 6, 15, 0, 0, 0, $utc)->format('j F');   // 15 Adar I
echo Hebrew::create(5784, 7, 15, 0, 0, 0, $utc)->format('j F');   // 15 Adar II
توکنمعنی
Y y m n d jسال (دست‌کم ۴ رقم، و از سال ۱۰۰۰۰ پنج رقم؛ y دو رقم آخر است)، ماه (ترتیبی) و روز
H G h g i sزمان روز (۲۴ ساعته و ۱۲ ساعته)
F Mنام ماه به زبان انتخاب‌شده (آدار اول و دوم، یا فقط آدار، بسته به سال)
lنام روز هفته به زبان انتخاب‌شده
w Nیکشنبه = ۰. و شمارهٔ ISO با دوشنبه = ۱
z t Lشمارهٔ روز در سال از صفر. تعداد روزهای ماه. و ۱ برای سال کبیسه (۱۳ ماه)
a Aam/pm و AM/PM
S W c rخالی. هفتهٔ ISO لحظهٔ میلادی. Y-m-d\TH:i:sP با تاریخ عبری. و RFC 2822
U e T P p O Z I u vاز لحظهٔ زیرین گرفته می‌شوند

جابه‌جایی و برش

متدها مثل جلالی هستند. دو قاعدهٔ مخصوص عبری را بدانید:

  • ماه‌ها ترتیبی شمرده می‌شوند و آدار اول و دوم دو ماه جدا هستند. اگر ماه مقصد کوتاه‌تر باشد، روز کم می‌شود. صفر ماه همان تاریخ را برمی‌گرداند و میکروثانیه حفظ می‌شود. حجم محاسبه کم است (چرخه‌های کامل ۱۹ ساله و حداکثر ۱۹ گام سالانه) و به بزرگی $months بستگی ندارد.
  • سال‌ها «همان ماه» را نگه می‌دارند. اگر از سال کبیسه به سال عادی بروید، آدار اول و دوم هر دو به آدار می‌روند. از سال عادی به کبیسه، آدار به آدار دوم می‌رود.
PHP
$adar1 = Hebrew::create(5784, 6, 15, 0, 0, 0, $utc);
echo $adar1->addMonths(1)->format('Y/m/d F');                                  // 5784/07/15 Adar II
echo Hebrew::create(5784, 7, 15, 0, 0, 0, $utc)->addYears(1)->format('Y/m/d F'); // 5785/06/15 Adar
echo Hebrew::create(5785, 2, 29, 0, 0, 0, $utc)->addMonths(1);                   // 5785/03/29 00:00:00
echo Hebrew::create(5785, 5, 30, 0, 0, 0, $utc)->addMonths(1)->format('Y/m/d F'); // 5785/06/29 Adar  (روز کم شد)
echo $e->endOfMonth();   // 5785/01/30 23:59:59
echo $e->endOfYear();    // 5785/12/29 23:59:59

مقایسه و اختلاف

مقایسه روی کل لحظه، با میکروثانیه، انجام می‌شود و هر تقویمی را قبول می‌کند. diffInMonths() ماه کامل عبری می‌شمارد (آدار اول و دوم جدا حساب می‌شوند). diffInYears() بر اساس سالگرد است. هر دو میکروثانیه را هم می‌شمارند. endOfDay() و endOfMonth() و endOfYear() در 23:59:59.999999 تمام می‌شوند. سال عبری ۱۲ یا ۱۳ ماه دارد، پس نمی‌شود ماه‌ها را بر ۱۲ تقسیم کرد.

PHP
echo Hebrew::create(5784, 1, 1, 0, 0, 0, $utc)->diffInMonths(Hebrew::create(5785, 1, 1, 0, 0, 0, $utc)); // 13
echo Hebrew::create(5780, 3, 3, 0, 0, 0, $utc)->diffInYears(Hebrew::create(5785, 3, 2, 0, 0, 0, $utc));  // 4

محاسبه‌های تقویمی

متدخروجی
Hebrew::isValid($y, $m, $d)bool
Hebrew::isLeapYear($y)true برای سال‌های ۳، ۶، ۸، ۱۱، ۱۴، ۱۷ و ۱۹ از چرخهٔ ۱۹ ساله
Hebrew::monthsInYear($y)۱۲ یا ۱۳
Hebrew::daysInYear($y)۳۵۳، ۳۵۴، ۳۵۵، ۳۸۳، ۳۸۴ یا ۳۸۵
Hebrew::daysInMonth($y, $m)۲۹ یا ۳۰. اگر شمارهٔ ماه از تعداد ماه‌های سال بیشتر باشد، خطا می‌دهد
Hebrew::gregorianToHebrew($gy, $gm, $gd)[سال, ماه ترتیبی, روز]
Hebrew::hebrewToGregorian($hy, $hm, $hd)[سال, ماه, روز]
PHP
echo (Hebrew::isLeapYear(5784) ? 'leap' : 'regular'), ' ', (Hebrew::isLeapYear(5785) ? 'leap' : 'regular'); // leap regular
echo Hebrew::daysInYear(5784), ' ', Hebrew::daysInYear(5785), ' ', Hebrew::daysInYear(5786);             // 383 355 354
echo json_encode(Hebrew::gregorianToHebrew(2025, 10, 3));   // [5786,1,11]
echo json_encode(Hebrew::hebrewToGregorian(5786, 1, 1));    // [2025,9,23]

ببینید: تبدیل بین تقویم‌ها در تبدیل و مقایسهٔ تاریخ‌ها. ماکروهای Carbon (toHebrew() و createFromHebrew()) در ماکروهای Carbon.