אלול

תאריכים עבריים ב-PHP

“יש פונקציה של php שמתרגמת תאריך לועזי לעברי”.  את המשפט הזה –  שגרם לי תדהמה – אמר לי  לפני כמה חודשים מתכנת  שהשתתף איתי בפרוייקט שביצעתי שלא במסגרת העבודה (שיתוף פעולה עם אנשים מחוץ לצוות הרגיל שלי הוא דרך נהדרת לגלות דברים פשוטים ונפלאים שלא ידעתי). במסגרת אותו פרוייקט התבקשתי להפוך לוח שנה של וורדפרס מהצגה לפי תאריכים לועזיים להצגה לפי תאריכים עבריים, וגם להציג תאריכים עבריים ליש התאריך הלועזי של כל פוסט.

לאור המידע הזה חשבתי לעצמי שהמשימות הללו תהיינה קלילות, אך התבדיתי. אמנם ללא הפונקציות הנ”ל הייתי אבודה לגמרי, אבל גם איתן  נותרה עבודת נמלים רבה.  כעת, משסיימתי אני יכולה לשתף אתכם בכמה אתגרים , מסקנות ותובנות בעקבות האירוע המכונן.

  1. ל-PHP יש מספר פונקציות המתייחסות לתאריכים עבריים:
    1. jewishtojd – ממירה תאריך בלוח השנה העברי ליום בספירה יוליאנית (ארחיב על זה בהמשך). הפונקציה מקבלת 3 פרמטרים: חודש (מספר בין 1 ל-13. כן, 13 – בגלל שנים מעוברות); יום (מספר בין 1 ל-30); ושנה (מספר בין 1 ל-9999. אתם רואים כאן פתח לבאג 2000 של היהודים? לעת עתה נראה שזה כבר לא יהיה בתקופתנו…).  הפלט הוא לדוגמה: 2456897.
    2. jdtojewish – ממירה יום בספירה יוליאנית לתאריך בלוח השנה העברי (הפוך מהפונקציה הקודמת). מקבלת פרמטר הכרחי 1, ו-2 אופציונליים: פרמטר ראשון הוא יום יוליאני כמספר (integer); הפרמטר השני הוא בוליאני – אם הוא אמת (true) אז משתמשים  בפרמטר הבא  בפלט בעברית;   הפרמטר השלישי מקבל אחת מ-3 מלים שמורות, שאומרות: להוסיף אלפים עם גרש, להוסיף אלפים, להוסיף גרשיים. הפלט הוא – אם הועבר רק הפרמטר הראשון: מערך
      Array ( [0] => 13 [1] => 15 [2] => 5774 )

      . אם הועברו הפרמטר השני והשלישי: כ”ט אדר התשע”ב.

    3. cal_days_in_month – מחזירה מספר ימים בחודש מסויים בשנה מסויימת, לפי הלוח שמועבר כפרמטר. מקבלת 3 פרמטרים: הלוח המבוקש (CAL_GREGORIAN או  CAL_JEWISH); חודש (מספר בין 1 ל-30); שנה (מספר בין 1 ל-9999).
  2. כבר בהתחלה מצאתי את האתר הזה שמכיל בתוכו המון קוד לחישובים של תאריכים עבריים (חישוב שנים מעוברות, המרה בין תאריכים לועזיים לעבריים, ועוד מלא דברים כיפיים). חד משמעית, לא הייתי מסתדרת בלעדיו. הוא היה הצלה מדהימה.
  3. יוליוס? גרגורי? מי אתם ולמה אני צריכה אתכם?  יש שני סוגי תאריכים: יוליאניים וגרגוריאניים. ולמה זה משנה? כי הפונקציות של PHP שממירות לתאריכים עבריים, רוצות לקבל תאריך יוליאני. אבל התאריכים הרגילים שוורדפרס מתעסקת איתם, ושמוחזרות מפונקציות כגון date, הם דווקא התאריכים הגרגוריאנים. על אף שההבדל בין שנה יוליאנית לשנה גרגוריאנית הוא רק 0.002%, עדיין אני בבעיה, מפני שהפונקציות הנ”ל, הרוצות תאריך יוליאני, לא רוצות תאריך בפורמט תאריכי כמו שאנחנו רגילים, אלא  יום יוליאני, שהוא הספירה המתמשכת של ימים מתחילת התקופה היוליאנית. (בויקיפדיה כתוב שמשתמשים בו בעיקר אסטרונומים. מישהו צריך לעדכן את הערך ולהוסיף שגם פונקציות PHP משתמשות בו. שהאסטרונומים יידעו שהם בחברה טובה). בקיצור, לעזרתנו נחלצות פונקציות JDToGregorian ו-GregorianToJD שמתווכות בהמרה בין תאריך יוליאני לעברי. כך למשל, כדי להמיר תאריך עברי ללועזי, נכתוב
    jdtogregorian( jewishtojd( $thisHmonthNum, 1, $thisHyearNum ) );

    והמרה הפוכה תהיה

    jdtojewish( gregoriantojd( $month, $day, $year ), true, CAL_JEWISH_ADD_GERESHAYIM );

    . יש  לשים לב שבמקרה של ההמרה האחרונה, שבה מקבלים את התאריך בעברית, כדי למנוע את הצגת התאריך בג’יבריש יש להעביר את התאריך בפונקציה הבאה:

    iconv( 'WINDOWS-1255', 'UTF-8', $jew_date );

    יש עוד סוג של תאריך –  unix time (מספר השניות שחלפו מאז חצות ב-1 בינואר 1970) בחסדי שמיים הצלחתי להמנע ממנו בהרפתקה הזו, אבל אני יודעת שאפשר למצוא אתרים שמבצעים המרה כזו.

     

  4. קשה להיות יהודי . jewishtojd מצפה לקבל תאריך  עברי במספרים,   וכך גם cal_days_in_month. הפונקציה jdtojewish  יכולה להחזיר תאריך עברי במלים (למשל ד’ אייר תשע”ד) או במספרים (מערך בן 3 איברים של חודש, יום, שנה).  אז כמובן שצריך לזגזג ביניהם, כי בתצוגה נרצה להראות את התאריך במילים, אבל לצורך חישובים נצטרך דווקא את המספרים. למרבה הזוועה, אין פונקציות שממירות תאריכים עבריים במספרים לתאריכים עבריים במילים, ולכן צריך לעבור בדרך בין תאריכים גרגוריאניים ויוליאניים.
  5. יום בשבוע – יש פונקציה שמחזירה יום בשבוע של תאריך – jddayofweek – אבל מקבלת כפרמטר רק יום יוליאני…  מזל שאני ממילא צריכה יום יוליאני בשביל כל שאר החישובים.
  6. איך כותבים ינואר בעברית?  בכותרת של לוח השנה הייתי צריכה לכתוב את שם החודש המוצג. היה בידי מספר החודש (למשל 8 ) ולכן יכולתי לכאורה להשתמש בפונקציה גנרית של PHP כך :
    date('F', strtotime("2012-$int-01"));

    אבל הבעיה היא שהיא מחזירה את שם החודש באנגלית (August),  ואני צריכה שיהיה כתוב אוגוסט. למרבה השמחה יש פונקציית וורדפרס

    $wp_locale->get_month($int);

    שמחזירה את שם החודש הגרגוריאני בעברית.

     

  7. איך כותבים 25 בעברית? רוב הזמן השתמשתי בתאריכים עבריים במספרים מפני שזה מה שהפונקציות שהייתי צריכה ביקשו. אבל בלוח השנה המוצג, לא יכולתי לכתוב מספרים ביום החדש. הרי התאריך איננו 1 באלול, אלא א’ באלול. לבעיה הזו אין פתרון, למיטב ידיעתי, לא ב-PHP ולא בוורדפרס. לכן נאלצתי, בצורה לא-אלגנטית בעליל, ליצור מערך של 30 איברים:
    $hebrew_days_dates = array( 'א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט', 'י', 'י"א', 'י"ב', 'י"ג', 'י"ד', 'ט"ו', 'ט"ז', 'י"ז', 'י"ח', 'י"ט', 'כ', 'כ"א', 'כ"ב', 'כ"ג', 'כ"ד', 'כ"ה', 'כ"ו', 'כ"ז', 'כ"ח', 'כ"ט', 'ל' );

    ולגשת אליו עם האינדקס של יום החודש:  $hebrew_days_dates[ $day ] כאשר $day הוא האינדקס של הלולאה  העוברת על מספר ימי החודש.

  8. PHP לא עומדת בסטנדרטים עבריים. אמרנו כי כש-PHP מחזירה תאריך, הוא נראה כך:  ד’ אייר תשע”ד. האם אתם רואים בעיה בפורמט הזה? מתברר שעל-פי האקדמיה ללשון העברית  צריך לכתוב  ד’ באייר תשע”ד.  וגם – PHP כותבת סיון ולא סיוון,  וחשון במקום מרחשוון  (מתברר  שמר הוא חלק אינטגרלי משם החודש, לא כינוי רשמי שאפשר לקצר).  אז גם בזה אני מטפלת (case פשוט על שם החודש, והחלפה בהתאם).
  9. שנים מעוברות. עד עכשיו היה סבבה? עכשיו מתחיל הכיף האמתי.
    1. כמה חודשים יש בשנה? שעתיים בזבזתי עד שהבנתי שהפונקציה המרנינה cal_days_in_month מחזירה 0 עבור החודש ה-6 בשנה לא מעוברת.  יש כאן הסבר מפורט וברור (אם גם באנגלית) ואנסה לתמצת אותו פה: הפונקציה הנ”ל מוכנה לקבל מספרים מ-1 עד 13, מפני שבשנה מעוברת יש 13 חודשים. נשאלת השאלה, כיצד היא תתמודד עם 12 חודשים בלבד בשנה רגילה. ההנחה הטבעית היא שהיא תתייחס ל-12 החודשים הראשונים, ותתעלם מהחודש ה-13. אך לא. הפונקציה הזו יודעת שזה לא החודש ה-13 שלא קיים בשנה רגילה, אלא החודש השישי – אדר א’ – שמתווסף בשנה מעוברת. ולכן בשנה רגילה הוא לא קיים, והיא מחזירה 0 עבור הפרמטר 6 בשנה רגילה. נפלא. הבעיה שהפונקציות האחרות – jdtojewish ו-jewishtojd מחזירות/מקבלות שחודש אדר בשנה רגילה הוא גם  6  וגם 7 (מכיוון שגם הן יכולות לקבל 13 חודשים בשנה רגילה). אז כדי לקבל ערך נכון מהפונקציה cal_days_in_month צריך לדלג על חודש 6 בשנה רגילה… אמרנו כבר שקשה להיות יהודי?
    2. שני דברים קטנים, אך מעצבנים: משום מה, באדר ב’, הפונקציה jdtojewish כותבת את הגרש לפני המילה אדר במקום אחרי האות ב: ז’ ‘אדר ב התשע”ד. למה? לא ידוע. אז אני חייבת להריץ את הקוד הזה כדי לתקן זאת:
      if ( mb_strpos( $jew_date[ 1 ], '\'' ) === 0 ) {             
           $jew_date[ 1 ] = mb_substr( $jew_date[ 1 ], 1 );             
           $jew_date[ 2 ] .= '\'';        
      }
    3. בשנה מעוברת, jdtojewish קוראת לאדר הראשון אדר, ולאדר השני אדר ב’. לא קיים אצלה אדר א’. למה? כנ”ל.

כששיתפתי את המתכנת שסיפר לי על הפונקציות הללו בתלאותיי, הוא הבין אותי, אבל אמר: אם לא היו פונקציות כאלה של PHP, זה בטח היה לוקח הרבה הרבה יותר זמן.
מה שנכון.

אם מישהו אי פעם צריך לעשות המרה כזו, אני מקווה שהמידע פה יעזור. אפשר גם לפנות אלי אם יש משהו שלא התייחסתי אליו כאן (בנושא הזה, כן?). וכמובן, אם מצאתם טעויות במה שכתבתי (וזה יתכן – אפילו תוך כדי כתיבת הפוסט הזה מצאתי שני באגים…) אשמח מאד אם תאירו את עיניי.

11 תגובות על “תאריכים עבריים ב-PHP

  1. אני מבין שאת לא מכירה את תוסף התאריך העברי שלי. גם אני נתקלתי בכל הבעיות והבאגים שהיו לך וכתבתי פונקציות מתאימות.
    כתבתי אותו לפני כמה שנים כך שהקוד שלו לא יפה אבל עושה את העבודה.

    יש גם ספריה חמודה lib-hdate שמתאימה כמעט לכל שפה פופולרית כולל PHP שאפשר לקבל ממנה גם את פרשת השבוע.

    1. חתול – אין כמוך. רק חבל שבנוסף לכישוריך כמפתח תוספים, לא ניחנת בכושר ניבוי שהיה מאפשר לך לדעת שאני זקוקה לזה לפני שכתבתי על כך 🙂
      קראתי את הקוד של התוסף שלך והוא ממש חמוד. אציין כי לבושתי לא הכרתי את פונקציית list של PHP והיא ממש מדליקה. בקיצור – תודה על תגובתך!

  2. שלום
    אני מנסה עכשיו להמיר לוח לועזי לעברית אבל יש לי בעיה עם השנים איך מראים 15 שנה קדימה בעברית בMENU של הלוח? האם את יודעת?

    1. אני לא בטוחה שאני מבינה מהו ה-menu של הלוח, אבל אני יצרתי קישורים לחודש קדימה וחודש אחורה, ואפשר להתקדם איתם גם לאורך השנים.
      איפה את נתקלת בבעיה?

  3. יש לי בעיה בהמרת השנים בלוח קדימה הוא כל הזמן מראה לי תשע”ה ואם אני עושה לו שנה קדימה עם לולאת FOR אז הוא לא ממיר לעברית מראה רק מספרים.

כתבו תגובה

כתובת הדוא"ל שלכם לא תוצג.