تحليل النصوص الزمنية
جزء من قسم Logic & Flow في رحلة 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)
}تماماً كما هو الحال مع التنسيق، تستخدم نفس مكونات التاريخ المرجعي في سلسلة التنسيق (layout string) الخاصة بك. يخبر التنسيق "2006-01-02" لغة Go بتوقع سلسلة الإدخال بتنسيق YYYY-MM-DD. يجب أن يتطابق التنسيق مع التنسيق الدقيق لسلسلة الإدخال الخاصة بك.
تذكر أن time.Parse تعيد قيمتين: كائن time.Time الذي تم تحليله وخطأ (error). تحقق دائماً من الخطأ للتأكد من أن عملية التحليل تمت بنجاح، حيث أن سلاسل التاريخ غير الصالحة أو التنسيقات (layouts) غير المتطابقة ستؤدي إلى فشل عملية التحليل.
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
التحدي
سهلقم بإنشاء محلل لملفات السجلات (log file parser) يقوم بتحويل سلاسل الطوابع الزمنية (timestamp strings) من تنسيقات مختلفة إلى كائنات time.Time للتحليل. سيختبر هذا التحدي قدرتك على استخدام time.Parse مع أنماط تخطيط (layout patterns) مختلفة للتعامل مع تنسيقات التاريخ والوقت المتعددة الموجودة عادةً في سجلات النظام.
ملاحظة هامة: نظراً لأن رسائل السجل وأنماط التخطيط قد تحتوي على مسافات، ستحتاج إلى استخدام 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 وخطأ - يجب عليك التحقق من الخطأ لتحديد ما إذا كان التحليل ناجحاً. عندما يفشل التحليل باستخدام تخطيط واحد، جرب نمط التخطيط التالي حتى تجد نمطاً يعمل أو تستنفد جميع الخيارات. يوضح هذا التحدي كيفية التعامل مع تنسيقات الطوابع الزمنية المتعددة في سيناريوهات معالجة السجلات في العالم الحقيقي.
ورقة مرجعية
استخدم 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)
}يجب أن تتطابق سلسلة التنسيق (layout string) مع التنسيق الدقيق لسلسلة الإدخال الخاصة بك باستخدام مكونات التاريخ المرجعية في Go. تُرجع 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. عرض إحصائيات استخدام التنسيقات
// 6. إذا تم تحليل الطوابع الزمنية، قم بعرض التحليل الزمني
// 7. عرض رسالة الإكمال
}يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Logic & Flow
1تدفق التحكم المتقدم
جملة Switch مع `fallthrough`الخروج من الحلقات المتداخلةالاستمرار في حلقة محددةجملة `goto`ملخص - التحكم المتقدم في الحلقات7معالجة الأخطاء بعمق
أنواع الأخطاء المخصصةتغليف الأخطاء باستخدام `%w`فك التغليف باستخدام `errors.Is`فك التغليف باستخدام `errors.As`فهم `panic`استخدام `recover`ملخص - القسمة الآمنة10التعامل مع الوقت
الحصول على الوقت الحاليإنشاء وقت محددتنسيق الوقتتحليل النصوص الزمنيةالمدة الزمنيةالعمليات الحسابية على الوقتالانتظار والـ Tickersمراجعة - مؤقت بسيط2الـ Structs والميثودز (Methods)
تعريف الـ Methods على الـ Structsالـ Value Receiversالـ Pointer Receiversاختيار الـ Receiversالـ Methods مقابل الـ Functionsملخص - سلوك الـ Struct5تعمق في الـ Maps
Maps من نوع Structsالـ Pointers كقيم في الـ Mapsالتحقق من الـ Nil Mapsمقارنة الـ Mapsمراجعة - عداد تكرار الكلمات3الواجهات (الأساسيات)
ما هي الواجهة؟تعريف الواجهةتطبيق الواجهةاستخدام أنواع الواجهاتالواجهة الفارغةتأكيدات النوع (Type Assertions)تبديل النوع (Type Switch)ملخص - الأشكال والسلوكيات