ל-SQLite אין באמת טיפוס תאריך
זה מפיל כל מי שמגיע מ-Postgres או מ-MySQL. ל-SQLite יש חמש מחלקות אחסון, NULL, INTEGER, REAL, TEXT, BLOB, וזהו. אין DATE, אין DATETIME, אין TIMESTAMP. אפשר לכתוב created_at DATETIME ב-CREATE TABLE, ו-SQLite תקבל את זה, אבל היא שומרת את הערך כטקסט רגיל או כמספר.
מה ש-SQLite כן נותנת לכם הוא סט של פונקציות שמבינות שלושה פורמטים מקובלים:
- טקסט ב-ISO 8601:
'2026-04-23','2026-04-23 10:15:00','2026-04-23T10:15:00.123Z'. - חותמת זמן של Unix: שניות מאז 1970-01-01 UTC, שנשמרות כמספר שלם.
- מספר יום יוליאני: ימים וחלקי ימים מאז 4714 לפנה"ס, שנשמרים כ-real.
בחרו אחד והישארו איתו. טקסט ב-ISO 8601 הוא הקריא ביותר וממוין נכון כמחרוזת, ולכן הוא ברירת המחדל.
ארבע דרכים לבקש "ממש עכשיו": תאריך כטקסט, תאריך ושעה כטקסט, שניות Unix, יום יוליאני. כולן מתארות את אותו רגע.
חמש פונקציות התאריך
SQLite נותנת לכם חמש פונקציות מובנות שמכסות כמעט הכול:
date(time, ...): מחזירהYYYY-MM-DD.time(time, ...): מחזירהHH:MM:SS.datetime(time, ...): מחזירהYYYY-MM-DD HH:MM:SS.julianday(time, ...): מחזירה real (מצוין להפרשים).strftime(format, time, ...): מחזירה מחרוזת בפורמט מותאם.
כל אחת מקבלת ערך זמן כארגומנט ראשון, ואחריו כל מספר של מחרוזות modifier.
שימו לב ל-'unixepoch': כך אומרים לפונקציות התאריך שהמספר השלם בקלט הוא חותמת זמן של Unix ולא יום יוליאני. בלי זה, SQLite מניחה שהמספר יוליאני.
strftime: פורמטים מותאמים לתאריכים
strftime היא סוס העבודה. אותם קודי % שאתם מכירים מ-C או מ-Python:
הקודים שתשתמשו בהם הכי הרבה:
%Y: שנה בארבע ספרות.%m: חודש (01-12).%d: יום בחודש (01-31).%H,%M,%S: שעות, דקות, שניות.%w: יום בשבוע (0=ראשון).%j: יום בשנה (001-366).%s: חותמת זמן של Unix.%f: שניות עם חלקי שנייה (SS.SSS).
strftime היא גם הדרך לחלץ חלקים מתאריך: אין פונקציה נפרדת בשם EXTRACT או YEAR(). פשוט מעצבים את התאריך רק לחלק שרוצים, וממירים אם צריך מספר:
strftime תמיד מחזירה טקסט, אז עטפו אותה ב-CAST(... AS INTEGER) כשאתם רוצים לעשות חשבון או להשוות מספרית.
Modifiers: חשבון תאריכים בלי אופרטור
זו התכונה שהופכת את הטיפול בתאריכים ב-SQLite לנעים. אחרי ארגומנט הזמן, אפשר להעביר כל מספר של מחרוזות modifier, והן מוחלות לפי הסדר:
ה-modifiers שתשתמשו בהם כל הזמן:
'+N days','-N days', ואותו דבר עבורhours,minutes,seconds,months,years.'start of day','start of month','start of year': חיתוך לגבול הזה.'weekday N': התקדמות ליום השבוע הבא שצוין (0=ראשון).'localtime'ו-'utc': המרה בין אזורי זמן.
הטריק של "היום האחרון בחודש", תחילת החודש, ועוד חודש, פחות יום, שווה שינון. ל-SQLite אין פונקציית LAST_DAY, אבל שרשור modifiers נותן את אותו דבר.
UTC מול שעון מקומי
'now' מחזיר תמיד UTC. אם אתם רוצים שעון מקומי, צריך לבקש:
ה-modifier 'localtime' ממיר ערך UTC לאזור הזמן המקומי של המערכת. ה-modifier 'utc' עושה את ההפך: הוא מתייחס לקלט כשעון מקומי וממיר ל-UTC.
ההרגל הבטוח: שמרו הכול ב-UTC, והמירו לשעון מקומי רק בזמן התצוגה. ערבוב אזורי זמן באחסון מוביל לבאגים שמופיעים פעמיים בשנה, כששעון הקיץ משתנה.
השוואת תאריכים וסינון טווחים
אם שומרים תאריכים כטקסט ב-ISO 8601, השוואה ו-BETWEEN פשוט עובדים: ISO 8601 ממוין לפי סדר מילוני באותו אופן שהוא ממוין כרונולוגית. זו כל הסיבה שהוא פורמט ברירת המחדל.
הטווח החצי פתוח (>= start, < end) הוא הרגל שימושי: הוא מונע לגמרי את השאלה "האם חצות של ה-30 נכללה או לא?".
ל"שבעת הימים האחרונים", תנו ל-SQLite לחשב את הגבול:
הפרשי תאריכים
ל-SQLite אין DATEDIFF. שני דפוסים מכסים הכול:
הפרשים של julianday() הם בימים (עם דיוק של חלקי ימים), כך שהכפלה ב-24 נותנת שעות, וב-1440 נותנת דקות. הפרשים של strftime('%s', ...) הם בשניות: נוח כשרוצים מספר שלם.
CAST(... AS INTEGER) חותך חלקי ימים אם אתם רוצים ספירה של ימים שלמים:
שמירת תאריכים: בחרו פורמט אחד והתחייבו אליו
שלוש בחירות סבירות, לפי הסדר של כמה פעמים כדאי לבחור בהן:
- טקסט ב-ISO 8601 (
TEXT). קריא בקבצי dump, ממוין נכון, מסתדר טוב עם כל פונקציות התאריך. בחירת ברירת המחדל. - שניות Unix (
INTEGER). קומפקטי, השוואות מהירות, בלי עמימות של אזורי זמן. טוב כשיש לכם מיליוני שורות. תצטרכוdatetime(col, 'unixepoch')כדי לקרוא אותו בחזרה. - יום יוליאני (
REAL). כמעט אף פעם לא שווה את זה, אלא אם אתם עושים חשבון תאריכים כבד ורוצים דיוק של פחות משנייה בעמודה אחת.
מה ש_לא_ כדאי לעשות זה לערבב פורמטים באותה עמודה. פונקציות התאריך יקבלו בשקט כל אחד מהם, אבל אינדקסים, מיונים והשוואות יפיקו שטויות.
DEFAULT (datetime('now')) היא המקבילה ב-SQLite ל-DEFAULT CURRENT_TIMESTAMP: היא מחתימה כל שורה חדשה בזמן ה-UTC הנוכחי בלי שום קוד באפליקציה.
קיבוץ לפי תקופת זמן
strftime זוהרת כשרוצים לחלק שורות לדליים לפי חודש, שבוע או שעה:
אותו רעיון עובד ל"הזמנות לפי שעה ביום", "הרשמות לפי יום בשבוע" או "אירועים לפי דקה": בחרו מחרוזת פורמט שתופסת רק את הרזולוציה שאתם רוצים, קבצו לפיה, וצברו.
הבא בתור: פונקציות צבירה
ואם כבר מדברים על קיבוץ, ה-COUNT(*) הזה הוא הפשוטה מבין פונקציות הצבירה של SQLite. בעמוד הבא נסתכל על הסט המלא: SUM, AVG, MIN, MAX, ואיך הן מכווצות שורות רבות לערך סיכום אחד.
שאלות נפוצות
יש ל-SQLite טיפוס נתונים DATE או DATETIME?
לא: ל-SQLite אין טיפוס ייעודי לתאריכים. שומרים תאריכים כ-TEXT בפורמט ISO 8601 ('2026-04-23 10:15:00'), כחותמת זמן של Unix מסוג INTEGER, או כיום יוליאני מסוג REAL. פונקציות התאריך המובנות מקבלות את שלושת הפורמטים ומחזירות כברירת מחדל טקסט ב-ISO 8601.
איך מקבלים את התאריך והשעה הנוכחיים ב-SQLite?
השתמשו ב-date('now') לתאריך הנוכחי, ב-time('now') לשעה הנוכחית, ב-datetime('now') לשניהם, וב-strftime('%s', 'now') לחותמת זמן של Unix. כברירת מחדל הן מחזירות UTC: העבירו 'localtime' כ-modifier כדי להמיר: datetime('now', 'localtime').
איך מוסיפים ימים או חודשים לתאריך ב-SQLite?
מעבירים מחרוזת modifier לכל פונקציית תאריך: date('2026-04-23', '+7 days'), date('now', '-1 month'), datetime('now', '+2 hours', '+30 minutes'). ה-modifiers משורשרים לפי הסדר, והיחידות כוללות days, hours, minutes, seconds, months ו-years.
איך מחשבים את ההפרש בין שני תאריכים?
לימים, השתמשו ב-julianday(end) - julianday(start): ימים יוליאניים הם מספרי נקודה צפה, כך שהתוצאה כוללת חלקי ימים. לשניות, החסירו חותמות זמן של Unix: strftime('%s', end) - strftime('%s', start). ל-SQLite אין פונקציית DATEDIFF; שני הדפוסים האלה מכסים כמעט כל מקרה.