Menu

תאריך ושעה ב-SQLite: strftime, date(), datetime() ו-modifiers

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

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

ל-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) חותך חלקי ימים אם אתם רוצים ספירה של ימים שלמים:

שמירת תאריכים: בחרו פורמט אחד והתחייבו אליו

שלוש בחירות סבירות, לפי הסדר של כמה פעמים כדאי לבחור בהן:

  1. טקסט ב-ISO 8601 (TEXT). קריא בקבצי dump, ממוין נכון, מסתדר טוב עם כל פונקציות התאריך. בחירת ברירת המחדל.
  2. שניות Unix (INTEGER). קומפקטי, השוואות מהירות, בלי עמימות של אזורי זמן. טוב כשיש לכם מיליוני שורות. תצטרכו datetime(col, 'unixepoch') כדי לקרוא אותו בחזרה.
  3. יום יוליאני (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; שני הדפוסים האלה מכסים כמעט כל מקרה.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל