تقویم عبری

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

در این صفحه
  1. این کلاس چه می‌کند
  2. شمارهٔ ماه‌ها
  3. ساخت تاریخ
    1. رشته چطور خوانده می‌شود
  4. بازهٔ سال و خطاها
  5. خواندن مقدارها
    1. شمارهٔ روز هفته
  6. قالب‌بندی
  7. جابه‌جایی و برش
  8. مقایسه و اختلاف
  9. محاسبه‌های تقویمی

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

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

<?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()) و از جدول کتابخانهٔ دیگر کپی نکنید.
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) طول واقعی ماه را در همان سال چک می‌کند (حشوان و کسلو بین ۲۹ و ۳۰ روز تغییر می‌کنند).

$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() است. اگر خود یک شیء Hebrew بدهید، همان بدون تغییر برمی‌گردد.

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. رقم‌های فارسی و عربی به انگلیسی تبدیل می‌شوند و فاصله‌های دو سر رشته حذف می‌شود. رشتهٔ خالی InvalidDateException می‌دهد.
  2. رشته‌ای با شکل Y/m/d یا Y-m-d (با H:i[:s] اختیاری) که سالش ۳۰۰۰ یا بیشتر باشد، تاریخ عبری است و ماه همان شمارهٔ ترتیبی بالاست. (این آستانه عکس جلالی و هجری است. آن‌ها سال کمتر از ۱۷۰۰ را مال خودشان می‌دانند.)
  3. هر رشتهٔ دیگر میلادی یا متن آزاد خوانده می‌شود.

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

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

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

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() و monthName() سال‌های ۱ تا ۱۳۷۵۹ را قبول می‌کنند (سال ۰ خطای Hebrew year out of the supported range: 0 می‌دهد). فقط ساخت تاریخ از ۳۷۶۲ شروع می‌شود.

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

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

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

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

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 می‌دهد.

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سال، ماه (ترتیبی) و روز
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 بستگی ندارد.
  • سال‌ها «همان ماه» را نگه می‌دارند. اگر از سال کبیسه به سال عادی بروید، آدار اول و دوم هر دو به آدار می‌روند. از سال عادی به کبیسه، آدار به آدار دوم می‌رود.
$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() بر اساس سالگرد است. سال عبری ۱۲ یا ۱۳ ماه دارد، پس نمی‌شود ماه‌ها را بر ۱۲ تقسیم کرد.

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)[سال, ماه, روز]
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.