ניתוח מחרוזות זמן
חלק מהיחידה לוגיקה וזרימת התוכנית במסלול ה-GO של Coddy. שיעור 61 מתוך 68.
לפעמים תקבלו מידע על תאריך ושעה כמחרוזות שצריך להמיר לאובייקטים מסוג time.Time לצורך עיבוד. Go מספקת את הפונקציה time.Parse כדי לבצע את ההמרה הזאת.
הפונקציה time.Parse פועלת בכיוון ההפוך לעיצוב — היא מקבלת מחרוזת תבנית ומחרוזת זמן, ואז מחזירה אובייקט time.Time:
dateString := "2023-10-26"
parsedTime, err := time.Parse("2006-01-02", dateString)
if err != nil {
fmt.Println("Error parsing time:", err)
} else {
fmt.Println(parsedTime)
}בדומה לעיצוב, משתמשים באותם רכיבי תאריך ייחוס במחרוזת התבנית. התבנית "2006-01-02" מורה ל-Go לצפות שמחרוזת הקלט תהיה בפורמט YYYY-MM-DD. התבנית חייבת להתאים בדיוק לפורמט של מחרוזת הקלט שלך.
זכור ש־time.Parse מחזירה שני ערכים: אובייקט time.Time שפוענח ושגיאה. בדוק תמיד את השגיאה כדי לוודא שהפענוח הצליח, מכיוון שמחרוזות תאריך לא תקינות או פריסות שאינן תואמות יגרמו לכישלון הפענוח.
אתגר
קלצרו מנתח לקובצי יומן שממיר מחרוזות חותמת זמן בפורמטים שונים לאובייקטים מסוג time.Time לצורך ניתוח. אתגר זה יבחן את יכולתכם להשתמש ב-time.Parse עם תבניות פריסה שונות כדי לטפל בפורמטים מרובים של תאריך ושעה, הנפוצים ביומני מערכת.
הערה חשובה: מכיוון שהודעות יומן ותבניות פריסה עשויות להכיל רווחים, תצטרכו להשתמש ב-bufio.Scanner כדי לקרוא שורות קלט שלמות. הפונקציה fmt.Scanln מפסיקה לקרוא ברווח הראשון, דבר שישבש רשומות יומן ותבניות שמכילות רווחים. השתמשו ב-bufio.NewScanner(os.Stdin) וקראו ל-scanner.Scan() ולאחר מכן ל-scanner.Text() כדי לקרוא שורות שלמות.
תקבלו שני קלטים:
- מחרוזת המכילה רשומות יומן בפורמט
"timestamp1:message1,timestamp2:message2,timestamp3:message3"(לדוגמה,"2023-10-26:System startup,2023/12/25:Holiday shutdown,Jan 15 2024:Maintenance window") - מחרוזת המכילה תבניות פריסה המופרדות בפסיקים בפורמט
"layout1,layout2,layout3"(לדוגמה,"2006-01-02,2006/01/02,Jan 2 2006")
המשימה שלכם היא:
- להשתמש ב-
bufio.Scannerכדי לקרוא כראוי את שורות הקלט ולטפל ברווחים בהודעות יומן ובתבניות פריסה - לנתח את הקלט הראשון באמצעות פיצול לפי פסיקים, כדי לקבל רשומות יומן נפרדות
- עבור כל רשומת יומן, לפצל לפי נקודתיים כדי לחלץ את מחרוזת חותמת הזמן ואת ההודעה
- לנתח את הקלט השני באמצעות פיצול לפי פסיקים, כדי לקבל תבניות פריסה
- להציג את כותרת היישום:
"=== LOG TIMESTAMP PARSER ===" - להציג את מצב הניתוח:
"Processing log entries with multiple timestamp formats..." - עבור כל רשומת יומן, לנסות לנתח את חותמת הזמן באמצעות כל תבנית פריסה עד שאחת מהן מצליחה:
- לנסות כל תבנית פריסה באמצעות
time.Parseעד שהניתוח מצליח (ללא שגיאה) - כאשר הניתוח מצליח, להציג:
"Parsed: [timestamp_string] -> [parsed_time_object] (using layout: [successful_layout])" - להציג גם:
" Message: [log_message]" - אם אף תבנית אינה מתאימה לחותמת זמן, להציג:
"Failed to parse: [timestamp_string] - no matching layout found"
- לנסות כל תבנית פריסה באמצעות
- לאחר עיבוד כל הרשומות, להציג נתונים סטטיסטיים של הניתוח:
"=== PARSING RESULTS ===""Total log entries processed: [number_of_entries]""Successfully parsed timestamps: [number_of_successful_parses]""Failed parsing attempts: [number_of_failed_parses]"
- להציג נתונים סטטיסטיים על השימוש בתבניות הפריסה:
"Layout pattern usage:"- עבור כל תבנית פריסה:
" [layout_pattern]: [number_of_times_used] times"
- אם חותמות זמן כלשהן נותחו בהצלחה, להציג ניתוח כרונולוגי:
"=== CHRONOLOGICAL ANALYSIS ===""Earliest timestamp: [earliest_parsed_time]""Latest timestamp: [latest_parsed_time]""Time span covered: [time_difference_description]"
- להציג את הודעת הסיום:
"Log parsing completed - timestamps converted to time objects"
השתמשו בחבילת time לפעולות הניתוח, בחבילת strings לפיצול מחרוזות הקלט, בחבילות bufio ו-os לטיפול נכון בקלט, ובחבילת fmt לפלט מעוצב. זכרו ש-time.Parse מחזירה גם אובייקט מסוג time.Time וגם שגיאה — עליכם לבדוק את השגיאה כדי לקבוע אם הניתוח הצליח. כאשר הניתוח נכשל עם תבנית אחת, נסו את תבנית הפריסה הבאה עד שתמצאו תבנית מתאימה או עד שתמצו את כל האפשרויות. אתגר זה מדגים כיצד לטפל בפורמטים מרובים של חותמות זמן בתרחישים מציאותיים של עיבוד יומנים.
נסו בעצמכם
package main
import (
"bufio"
"fmt"
"os"
"strings"
"time"
)
func main() {
// צור סורק לקריאת שורות קלט
scanner := bufio.NewScanner(os.Stdin)
// קרא רשומות יומן
scanner.Scan()
logEntries := scanner.Text()
// קרא תבניות פריסה
scanner.Scan()
layoutPatterns := scanner.Text()
// נתח את הקלטים
entries := strings.Split(logEntries, ",")
layouts := strings.Split(layoutPatterns, ",")
// אתחל מונים לסטטיסטיקה
totalEntries := len(entries)
successfulParses := 0
failedParses := 0
layoutUsage := make(map[string]int)
var parsedTimes []time.Time
// TODO: כתוב את הקוד שלך למטה
// 1. הצג כותרת ליישום
// 2. הצג את מצב העיבוד
// 3. עבד כל רשומת יומן:
// - פצל את הרשומה לפי ":" כדי לקבל חותמת זמן והודעה
// - נסה כל תבנית פריסה עד שאחת מהן תעבוד
// - הצג את תוצאות הניתוח
// - עדכן את הסטטיסטיקות
// 4. הצג סטטיסטיקות של ניתוח הקלט
// 5. הצג סטטיסטיקות שימוש בתבניות layout
// 6. אם חותמות הזמן נותחו, הצג ניתוח כרונולוגי
// 7. הצג הודעת סיום
}השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה לוגיקה וזרימת התוכנית
1בקרת זרימה מתקדמת
switch עם `fallthrough`יציאה מלולאות מקוננותהמשך לולאה מסוימתהצהרת `goto`סיכום – שליטה מתקדמת בלולאות4פרויקט: רשימת משימות פשוטה
הגדרת הפרויקטהוספת משימה7טיפול בשגיאות לעומק
סוגי שגיאות מותאמים אישיתעטיפת שגיאות באמצעות `%w`חילוץ שגיאות באמצעות `errors.Is`חילוץ שגיאות באמצעות `errors.As`הבנת `panic`שימוש ב־`recover`סיכום — חלוקה בטוחה10עבודה עם זמן
קבלת הזמן הנוכחייצירת זמן מסויםעיצוב זמןניתוח מחרוזות זמןמשך זמןחישובים עם זמןהשהיה וטיקריםסיכום - טיימר פשוט2מבנים ושיטות
הגדרת שיטות במבניםמקבלי ערךמקבלי מצביעבחירת מקבליםשיטות לעומת פונקציותסיכום — התנהגות המבנים5מפות לעומק
מפות של Structsמצביעים כערכים במפהבדיקה אם מפות הן nilהשוואת מפותסיכום - מונה תדירות מילים8פרויקט: ניהול מלאי פשוט
סקירת הפרויקטבדיקת המלאיתרגלו בעצמכם: קומפיילר Go אונליין