מאיפה הגיעה ה Z בסוף הזמן?

בשביל לקחת בסקאלה (או Java) את השעה הנוכחית ולשמור אותה כמחרוזת אוכל להשתמש בקוד הבא:

import java.time.*
import java.time.format.DateTimeFormatter

LocalTime.now().format(DateTimeFormatter.ISO_LOCAL_TIME)

והמחרוזת שתתקבל עשויה להיראות כך:

"16:51:44.748375"

אבל כשמסתכלים בבסיסי נתונים וברשת אנחנו נתקלים במחרוזות דומות שמסתיימות באות Z לדוגמה:

14:54:10.140198Z

למה הם התכוונו? מאיפה ה Z הגיע? ואיך אני גם מקבל אחד?

אז בואו נתחיל בקוד בשביל ליצור מחרוזת זמן עם ה Z בסוף אני לא צריך לשרשר אותו ידנית אלא להשתמש בקוד מקביל שכולל התיחסות לאזור זמן:

OffsetTime.now(ZoneId.of("UTC")).format(DateTimeFormatter.ISO_OFFSET_TIME)

ה Z מסמן שזוהי תווית זמן באזור זמן UTC. אזורי זמן אחרים כבר מקבלים סימון יותר ברור לדוגמה עבור ישראל נקבל:

scala> OffsetTime.now(ZoneId.of("Israel")).format(DateTimeFormatter.ISO_OFFSET_TIME);

val res5: String = 16:57:24.769026+02:00

וכן היה אפשר במקום ה Z לכתוב משהו כמו פלוס אפס, אבל כנראה שזה לא מספיק מבלבל בשביל מי שכותב תקנים לדברים כאלה.

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

אופציה שניה יותר מורכבת היא לשמור את המידע כולל אזור הזמן בבסיס הנתונים. בשביל זה אנחנו יכולים להפוך את השעה למחרוזת הכוללת אזור זמן (עם ה Z בסוף ל UTC, או עם Offset לאזורי זמן אחרים). במצב כזה לא נדרשת המרה אבל כל קוד המערכת יהיה מורכב יותר כי תמיד צריך לחשוב באיזה אזור זמן אנחנו ולעבוד עם סט המחלקות המתאים.