הבלוג של ארתיום
בלוג על לינוקס, תוכנה חופשית, מוזיקה, סלסה, ומה לא!
ייסורי בינאום ולוקליזציה בשנת 2009
מה יותר פשוט מאשר להציג תאריך ושעה בהתאם למקובל באיזור? בארה"ב תכתוב 6/15/2008 8:30 PM ובישראל תכתוב 15/6/2008 20:30. לא מסובך, נכון? כמובן strftime עושה את העבודה הנאמנה בצורה טובה. אכן, יש אופציות "%x" ו־"%X" להצגת תאריך ושעה בהתאם ללוקל מקומי.
עכשיו בואו נעשה את הדרך ההפוכה: יש לנו טופס HTML בו אנחנו רוצים להציג תאריך ולתת למשתמש אפשרות לערוך אותו? במילים אחרות אני רוצה אופציה של פענוח תאריך ושעה לפי התבנית המקובלת לאיזור ובשפה הספציפיים... ואכן, יש פונקציה הפוכה ל־strftime --- strptime. שעושה את העבודה ההפוכה.
כמובן גם ב־C++ יש מקבילות std::facet
מסוג: std::time_put
ו־std::time_get
עושות את העבודה וגם מאפשרות להשתמש ביותר מ־locale אחד בתהליך, שמאפשר, למשל לייצר טקסט שונה למשתמשים שונים בחוטים שונים. ב־C ובשירותי מערכת ההפעלה הסטנדרטיים אין כלי כזה, יש רק strftime_l
ו־strptime_l
הלא מתועדים ולא מוגדרים לפי סטנדרט שעושים את העבודה.
מכאן, הכל פשוט... על הנייר. במציאות המצב הרבה יותר מסובך:
- הגדרות סטנדרט C++ של
std::time_get
מכילות באג לוגי שמקשה מאוד על יצירת כלים לפענוח תאריך ושעה בצורה נכונה וגם כשעובדים, הם עושים זאת בצורה חלקית --- כי אין מקבילה של strptime המלאה של C. - גם API של C, מסתבר כלא תמיד עובד כמו שצריך.
לצורך ההשוואה, בניתי תכנה פשוטה, שמייצרת מחרוזת עם תאריך ושעה בעזרת כלֵי C, C++ וספריית ICU. ולאחר מכן מפענחת אותה אם אותם הכלים. בדקתי את זה עבור מספר לוקלים. בטבלה למטה מוצגים: לוקל, שעה ותאריך כפי שמייוצרים ע"י כלים שונים והפענוח של אותם תאריך ושעה המוצגים בפורמט בינלאומי.
en_US.UTF-8
strftime 10/05/2009 11:36:38 PM to 2009-10-05 23:36:38
std::facet 10/05/2009 11:36:38 PM to 2009-10-05 00:00:00
icu::DateFormat Oct 5, 2009 11:36:38 PM to 2009-10-05 23:36:38
he_IL.UTF-8
strftime 05/10/09 23:36:38 to 2009-10-05 23:36:38
std::facet 05/10/09 23:36:38 to 1909-10-05 23:36:38
icu::DateFormat 23:36:38 05/10/2009 to 2009-10-05 23:36:38
de_DE.UTF-8
strftime 05.10.2009 23:36:38 to 2009-10-05 23:36:38
std::facet 05.10.2009 23:36:38 to 2009-10-05 23:36:38
icu::DateFormat 05.10.2009 23:36:38 to 2009-10-05 23:36:38
en_GB.UTF-8
strftime 05/10/09 23:36:38 to 2009-10-05 23:36:38
std::facet 05/10/09 23:36:38 to 1909-10-05 23:36:38
icu::DateFormat 5 Oct 2009 23:36:38 to 2009-10-05 23:36:38
ja_JP.UTF-8
strftime 2009年10月05日 23時36分38秒 to 2009-10-05 23:36:38
std::facet 2009年10月05日 23時36分38秒 to 2009-10-05 23:36:38
icu::DateFormat 2009/10/05 23:36:38 to 2009-10-05 23:36:38
ar_EG.UTF-8
strftime 05 أكت, 2009 IST 11:36:38 to 2009-10-05 00:00:00
std::facet 05 أكت, 2009 IST 11:36:38 to 2009-10-05 11:36:38
icu::DateFormat ٠٥/١٠/٢٠٠٩ ١١:٣٦:٣٨ م to 2009-10-05 23:36:38
tr_TR.UTF-8
strftime 05-10-2009 23:36:38 to 2009-10-05 23:36:38
std::facet 05-10-2009 23:36:38 to 2009-10-05 23:36:38
icu::DateFormat 05.Eki.2009 23:36:38 to 2009-10-05 23:36:38
ru_RU.UTF-8
strftime 05.10.2009 23:36:38 to 2009-10-05 23:36:38
std::facet 05.10.2009 23:36:38 to 2009-10-05 23:36:38
icu::DateFormat 05.10.2009 23:36:38 to 2009-10-05 23:36:38
zh_CN.UTF-8
strftime 2009年10月05日 23时36分38秒 to 2009-10-05 23:36:38
std::facet 2009年10月05日 23时36分38秒 to 2009-10-05 23:36:38
icu::DateFormat 2009-10-5 下午11:36:38 to 2009-10-05 23:36:38
כפי שניתן לראות:
- std::facet לא מתמודד עם שעון של 12 שעות המכיל ציון AM/PM.
- std::facet לא מוסוגל לשחזר שנה בעזרת שתי ספרות בלבד וזורק אותנו משנת 2009 ל־1909 ב־2 מתוך 9 דוגמאות.
- strptime לא מצליח לשחזר שעה בכלל ו־std::facet וטועה ב־12 שעות בלוקל מצרי.יש לציין שזה באג בייצוג locale כי הפורמט המוגדר הוא "%Z %I:%M:%S" במקום "%p %I:%M:%S" --- להציג איזור זמן במקום סימון AM/PM המתאים (م).
במילים אחרות... מימוש של std::facet גרוע, יש בעיות בייצוג locale באופן כללי.
עצוב שזה המצב בשנת 2009...
הוסף תגובה:
חובה לאפשר JavaScript כדי להגיב.