المسارات
/
Julia
Julia
/
التمارين
/
احجز موعدك للتجميل
احجز موعدك للتجميل

احجز موعدك للتجميل

تمرين تعلّمي

مقدمة

"التواريخ والأوقات شيء نُعلّمه للأطفال الصغار. فما مدى صعوبته؟"

ارتكب كثير من المبرمجين هذا الخطأ، وعادةً ما يكون للتجربة التي تلي ذلك تأثير سيئ على صحتهم وسعادتهم.

على أي شخص يكتب برامج غير بسيطة تتعامل مع التواريخ والأوقات أن يكون مستعدًا على الأقل لفهم المشكلات المحتملة والتخفيف من آثارها.

تحاول هذه الوثيقة تقديم نظرة عامة على كيفية تعامل Julia مع التواريخ والأوقات، لكن ستحتاج إلى الرجوع إلى الدليل لمزيد من التفاصيل. يوجد أيضًا ويكيبوك قد يجد بعض القراء شروحه أوضح، ويتضمن مخططًا مفيدًا للتسلسل الهرمي للأنواع.

وحدة Dates

توجد معظم الوظائف الأساسية في Dates، وهي وحدة مضمنة في التثبيت الافتراضي لكنها ليست جزءًا من المكتبة القياسية.

لاستخدام هذه الوحدة، لديك خياران:

  1. أضف import Dates، ثم اسبق كل استدعاءات الدوال بـ Dates.
  2. أضف using Dates، وهذا يجلب الوحدة بأكملها إلى النطاق الحالي (باستثناء بعض الأسماء الإشكالية).
# option 1
julia> import Dates

julia> Dates.now()
2025-06-21T16:02:39.080

julia> now()  # wrong: need to include `Dates.` after an import
ERROR: UndefVarError: `now` not defined in `Main`


# option 2
julia> using Dates

julia> now()  # functions are now in the namespace
2025-06-21T16:03:04.161

وحدة Dates كبيرة ومعقدة، لكنها توفر أربعة أنواع رئيسية من الوظائف:

  • Dates.Date، ويشمل اليوم والشهر والسنة لكن ليس وقت اليوم.
  • Dates.Time، ويشمل وقت اليوم لكن ليس التاريخ.
  • Dates.DateTime، ويجمع بين التاريخ والوقت.
  • Dates.Period، ويتعامل مع الفترات الزمنية والتاريخية.

لاحظ أن DateTime عمومًا لا يتضمن معلومات المنطقة الزمنية (كانت Python تسمي هذا النوع من قيم datetime بـ "naive"). والاستثناء الوحيد هو now()، الذي يحصل على الوقت المحلي من ساعة نظامك، ويمكنه تحويله إلى UTC عند الحاجة.

ربما تكون الاحتياجات الأكثر شيوعًا هي:

  • تحليل صيغة إدخال مناسبة لإنشاء نوع من أنواع Dates.
  • الحصول على الصيغة الرقمية أو النصية المطلوبة من نوع من أنواع Dates.
  • تطبيق إزاحة على قيمة Date أو Time أو DateTime.
  • حساب الفترة بين قيمتين كهاتين.
  • الحصول على التاريخ الحالي (باستخدام today()) و/أو الوقت الحالي (باستخدام now()).
Note

لتقليل التشتيت البصري، تفترض معظم أمثلة الكود في بقية هذه الوثيقة وجود using Dates، وتتجنب كتابة اسم الوحدة Dates. في استدعاءات الدوال.

صيغ التاريخ والوقت

هناك طرق كثيرة لكتابة التواريخ والأوقات، وهي غالبًا ما تكون مرتبطة بثقافة معينة. التواريخ المكوّنة من أرقام فقط مثل "7/6/23" غامضة ومربكة، وقد أدت إلى أخطاء مكلفة كثيرة في الشركات متعددة الجنسيات (يقول المؤلف هذا من تجربة شخصية مريرة).

المعيار الدولي معرّف في ISO 8601، وله ميزتان رئيسيتان:

  • التحليل سريع ولا يحتمل التأويل.
  • الترتيب سهل، إذ يمكن التعامل مع التاريخ والوقت كنص عادي وترتيبه أبجديًا.

رأينا في مثال سابق أن Date.now() أرجع 2025-06-21T16:03:04.161.

ويتكوّن هذا من عدة أجزاء:

  • YYYY-MM-DD لجزء التاريخ.
  • hh:mm:ss لجزء الوقت.
  • واختياريًا، أجزاء من الثانية بالميلي ثانية (أو وحدة أصغر) بعد الفاصلة العشرية.

سنناقش صيغًا نصية أخرى في قسم لاحق.

التواريخ

Dates.Date نوع بسيط نسبيًا للتاريخ فقط، ولا يفهم الأوقات أو المناطق الزمنية.

# constructor with year, month, day arguments
julia> date1 = Date(2025, 06, 23)
2025-06-23

# constructor with ISO 8601 string
julia> date2 = Date("2025-06-23")
2025-06-23

julia> date1 == date2
true

julia> typeof(date1)
Date

توجد دوال وصول لأجزاء التاريخ الفردية، وهي تأتي في أزواج يميّز بعضها عن بعض بحالة الأحرف.

# lowercase returns an integer
julia> month(date1)
6

julia> typeof(month(date1))
Int64

# Propercase returns a Period type
julia> Month(date1)
6 months

julia> typeof(Month(date1))
Month

دوال الاستعلام

هناك مجموعة متنوعة من الدوال التي لديها بعض الفهم للتقويم. يعرض المثال التالي بعضًا منها فقط.

julia> date1
2025-06-23

julia> dayofweek(date1) # 1 = Monday, 7 = Sunday
1

julia> dayname(date1)
"Monday"

julia> daysinmonth(date1)
30

julia> isleapyear(date1)
false

julia> lastdayofmonth(date1)
2025-06-30

الأوقات

Dates.Time هو النوع الأساسي للوقت فقط. إنه لا يفهم التواريخ: تنتقل الأوقات تلقائيًا إلى Time(0, 0, 0) عند منتصف الليل.

صيغة البانية الكاملة هي Time(hour, min, sec, millisec, microsec) أو ما يعادلها بصيغة ISO 8601.

جميع المعاملات اختيارية وقيمتها الافتراضية 0.

julia> Time(14, 57, 25, 142)
14:57:25.142

julia> Time("14:57:25.142")
14:57:25.142

julia> Time(14, 57, 25, 142, 32)
14:57:25.142032

كما هو الحال مع Date، تتوفر الأجزاء الفردية عبر دوال الوصول:

julia> minute(t) # => integer
57

julia> Minute(t) # => Period
57 minutes

التواريخ والأوقات

يجمع Dates.DateTime معظم مزايا النوعين Date و Time.

julia> dt1 = DateTime(2025, 6, 23, 14, 57, 25, 142)
2025-06-23T14:57:25.142

# date1 and t were defined in previous examples
julia> dt2 = DateTime(date1, t)
2025-06-23T14:57:25.142

القيم الافتراضية لمعاملات السنة والشهر واليوم هي 1، والقيم الافتراضية لجميع معاملات الوقت هي 0.

قد يكون تتبّع كل هذه المعاملات بدقة تحديًا، لذا قد تكون صيغة ISO أفضل للإدخال.

أو بدلًا من ذلك، يمكن إنشاء DateTime من Date و Time، كما في المثال أعلاه.

الفترات

لكل مكوّن من مكوّنات التاريخ/الوقت نوع Period خاص به، من Year وصولًا إلى Nanosecond، ويمثل فترة زمنية. وهذه مفيدة بشكل خاص في العمليات الحسابية.

julia> dt1
2025-06-23T14:57:25.142

julia> Year(21)
21 years

julia> Second(61)
61 seconds

julia> dt1 + Year(21) - Second(61)
2046-06-23T14:56:24.142

julia> Date(2025, 07, 03) - Date(2025, 04, 25)
69 days

عند العمل مع أنواع Period، تحاول Julia التعامل بذكاء مع التفاوتات في التقويم مثل طول الشهر، وتقرّب القيم عند الحاجة.

# February has fewer days than January
julia> Date(2025, 1, 31) + Month(1) 
2025-02-28

التمثيلات النصية

ذكرنا سابقًا معيار ISO 8601، وهو التمثيل الافتراضي للتاريخ/الوقت في Julia عند تنسيق السلاسل النصية أو تحليلها.

من الواضح أن هناك صيغًا أخرى كثيرة شائعة الاستخدام، وغالبًا بطرق مرتبطة بثقافة معينة. للتعامل معها، توفر Julia النوع DateFormat، الذي يمكن إنشاؤه من سلسلة تنسيق بأي درجة من التعقيد.

# dateformat"" string syntax
julia> dtfmt = dateformat"d/m/y"
dateformat"d/m/y"

julia> typeof(dtfmt)
DateFormat{Symbol("d/m/y"), Tuple{Dates.DatePart{'d'}, Dates.Delim{Char, 1}, Dates.DatePart{'m'}, Dates.Delim{Char, 1}, Dates.DatePart{'y'}}}

# DateFormat constructor
julia> DateFormat("d/m/y")
dateformat"d/m/y"

المثال أعلاه بسيط جدًا، وهو مجرد تاريخ بصيغة اليوم/الشهر/السنة الشائعة في أوروبا. تظهر صيغتان مختلفتان من حيث التركيب، لكن النتيجة متطابقة.

يمكن بعد ذلك استخدام DateFormat في تحليل أي سلسلة نصية مناسبة:

julia> DateTime("14/7/2023", dtfmt)
2023-07-14T00:00:00

يتضمن إنشاء DateFormat قدرًا كبيرًا من العمل الإضافي، لذا فإن القيام بهذه الخطوة مرة واحدة فقط (كما هنا مع dtfmt) مفيد للأداء عند تكرار المرور على سلاسل نصية كثيرة للتاريخ/الوقت.

يمكن أن تكون الصيغ أكثر تعقيدًا بكثير من هذا، فراجع الدليل للتفاصيل.

يمكن أيضًا استخدام نفس DateFormat لإخراج تاريخ/وقت بأي صيغة نصية مرغوبة، باستخدام الدالة Dates.format().

للأسف، يبدو أن هناك تعارضًا في النطاق مع format (على الأقل في Julia 1.11.5)، لذا من الأفضل تضمين البادئة Dates. حتى بعد using Dates.

julia> dt1
2025-06-23T14:57:25.142

julia> Dates.format(dt1, dateformat"e, u d")
"Mon, Jun 23"

كما هو موثّق، تعطي "e, u d" التمثيل النصي المختصر لاسم اليوم والشهر.

التمثيل النصي يكون افتراضيًا بالإنجليزية. يمكن إضافة لغات أخرى، لكن الدعم لذلك دون المستوى الأمثل حاليًا.

التعليمات

في هذا التمرين ستعمل على منظّم مواعيد لصالون تجميل في نيويورك افتُتح في 15 سبتمبر 2012.

لديك خمس مهام، وكلها تتعلق بتواريخ المواعيد. الوقت مكتوب بصيغة 24 ساعة (بدون AM/PM).

1. حلّل تاريخ موعد مكتوبًا بأرقام فقط

نفّذ الدالة schedule_appointment() لتحليل تمثيل نصي لتاريخ موعد إلى صيغة DateTime المقابلة.

لاحظ أن المدخل مكتوب بالترتيب الأمريكي: الشهر/اليوم/السنة.

julia> schedule_appointment("07/25/2023 13:45:00")
2023-07-25T13:45:00

2. تحقق مما إذا كان الموعد قد مضى

نفّذ الدالة has_passed() التي تأخذ تاريخ موعد وتتحقق مما إذا كان الموعد في وقت ما في الماضي:

julia> has_passed(DateTime(1999, 12, 31, 9, 0, 0))
true

3. تحقق مما إذا كان الموعد بعد الظهر

نفّذ الدالة is_afternoon_appointment() التي تأخذ تاريخ موعد وتتحقق مما إذا كان الموعد في فترة بعد الظهر (12:00 فأكثر وأقل من 18:00):

julia> is_afternoon_appointment(DateTime(2023, 3, 29, 15, 0, 0))
true

4. صِف وقت الموعد وتاريخه

نفّذ الدالة description() التي تأخذ تاريخ موعد وتُرجع وصفًا لذلك التاريخ والوقت:

julia> describe(DateTime(2023, 3, 29, 15, 0, 0))
"You have an appointment on Wednesday, March 29, 2023 at 15:00"

5. أرجِع تاريخ الذكرى السنوية

نفّذ الدالة anniversary_date() التي تُرجع تاريخ الذكرى السنوية لهذا العام، وهو 15 سبتمبر:

julia> anniversary_date()  # run during 2025
2025-09-15
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Julia Exercism

مستعد لبدء احجز موعدك للتجميل؟

سجّل في Exercism لتتعلّم وتتقن Julia عبر 35 مفهومًا128 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.