قد تشغّل برامجك أثناء جلوسك أمام الحاسوب، ولكنك ستفضّل تشغيلها دون إشرافك المباشر، إذ يمكن لساعة حاسوبك جدولة البرامج لتشغيل الشيفرة البرمجية في وقت وتاريخ محدَّد أو على فترات زمنية منتظمة، فمثلًا يمكن أن يستخلص Scrape برنامجك البيانات من موقع ويب كل ساعة للتحقق من التغييرات أو يجري مهمةً تستخدم وحدة المعالجة المركزية بصورة كبيرة في الساعة 4 صباحًا أثناء نومك، حيث توفر وحدتا time
و datetime
في لغة بايثون الدوال التي تقدّم هذه الوظائف.
الوحدة time
تُضبَط ساعة نظام حاسوبك على تاريخٍ ووقت ومنطقة زمنية محددة، حيث تسمح الوحدة time
المُدمَجة لبرامج بايثون الخاصة بك بقراءة ساعة النظام للوقت الحالي، وتُعَد الدالتان time.time()
و time.sleep()
الأكثر فائدة في هذه الوحدة.
الدالة time.time()
توقيت يونيكس Unix Epoch هو مرجع زمني شائع الاستخدام في البرمجة، وهو الساعة 12 صباحًا في 1 من الشهر الأول من عام 1970 بالتوقيت العالمي المنسق Coordinated Universal Time -أو UTC اختصارًا، حيث تعيد الدالة time.time()
عدد الثواني منذ تلك اللحظة التي تمثّل توقيت يونيكس بوصفها قيمةً عشرية Float، والتي تُعَد مجرد عددٍ مع فاصلة عشرية، ويسمى هذا العدد الذي تعيده الدالة time.time()
بعلامة يونيكس الزمنية Epoch Timestamp. أدخِل ما يلي مثلًا في الصدفة التفاعلية Interactive Shell:
>>> import time >>> time.time() 1543813875.3518236
استدعينا الدالة time.time()
في 2 من الشهر 12 من عام 2018 في الساعة 9:11 مساءً بتوقيت المحيط الهادئ، وتكون القيمة المُعادة هي عدد الثواني التي مرّت بين توقيت يونيكس ولحظة استدعاء الدالة time.time()
.
يمكن استخدام علامات يونيكس الزمنية لفحص أداء Profile الشيفرة البرمجية، أي قياس المدة التي يستغرقها تشغيل جزء من هذه الشيفرة البرمجية. إذا استدعيتَ الدالة time.time()
في بداية مقطع الشيفرة البرمجية الذي تريد قياس المدة التي يستغرقها تشغيله وفي نهايته مرةً أخرى، فيمكنك طرح العلامة الزمنية الأولى من الثانية لإيجاد الوقت المنقضي بين هذين الاستدعاءين. افتح تبويبًا جديدًا في محرّرك لإنشاء ملفٍ جديد وأدخِل البرنامج التالي مثلًا:
import time ➊ def calcProd(): # حساب حاصل ضرب أول 100,000 عدد product = 1 for i in range(1, 100000): product = product * i return product ➋ startTime = time.time() prod = calcProd() ➌ endTime = time.time() ➍ print('The result is %s digits long.' % (len(str(prod)))) ➎ print('Took %s seconds to calculate.' % (endTime - startTime))
نعرّف الدالة calcProd()
➊ للتكرار ضمن حلقة على الأعداد الصحيحة من 1 إلى 99,999 وإعادة ناتج ضربها. نستدعي الدالة time.time()
ونخزّنها في المتغير startTime
➋، ثم نستدعي الدالة time.time()
مرةً أخرى بعد استدعاء الدالة calcProd()
مباشرةً ونخزّنها في المتغير endTime
➌، ثم نطبع عدد أرقام حاصل الضرب الذي تعيده الدالة calcProd()
➍ والمدة التي استغرقها تشغيل هذه الدالة ➎.
احفظ البرنامج السابق بالاسم calcProd.py وشغّله، حيث سيبدو خرجه كما يلي:
The result is 456569 digits long. Took 2.844162940979004 seconds to calculate.
ملاحظة: هناك طريقة أخرى لفحص أداء شيفرتك البرمجية باستخدام الدالة cProfile.run()
التي توفّر مستوًى أعلى من التفاصيل بدلًا من استخدام تقنية الدالة time.time()
البسيطة. اطلّع على مقال قياس أداء وسرعة تنفيذ شيفرة بايثون لمزيدٍ من التفاصيل عن الدالة cProfile.run()
.
تُعَد القيمة المُعادة من الدالة time.time()
مفيدةً للحصول على عدد الثواني منذ توقيت يونيكس إلى لحظة استدعائها بوصفها قيمةً عشرية، ولكن لا يستطيع البشر قراءتها، لذا توجد دالة أخرى هي الدالة time.ctime()
التي تعيد سلسلةً نصية تمثّل وصفًا للوقت الحالي. يمكنك أيضًا اختياريًا تمرير عدد الثواني منذ توقيت يونيكس الذي تعيده الدالة time.time()
إلى الدالة time.ctime()
للحصول على قيمة السلسلة النصية التي تمثّل ذلك الوقت. لندخِل الآن ما يلي في الصدفة التفاعلية:
>>> import time >>> time.ctime() 'Mon Jun 15 14:00:38 2023' >>> thisMoment = time.time() >>> time.ctime(thisMoment) 'Mon Jun 15 14:00:45 2023'
الدالة time.sleep()
إذا أردتَ إيقاف برنامجك مؤقتًا لفترة من الوقت، فاستدعِ الدالة time.sleep()
ومرّر إليها عدد الثواني التي تريد أن يبقى فيها برنامجك متوقفًا مؤقتًا. إذًا لندخِل ما يلي في الصدفة التفاعلية:
>>> import time >>> for i in range(3): ➊ print('Tick') ➋ time.sleep(1) ➌ print('Tock') ➍ time.sleep(1) Tick Tock Tick Tock Tick Tock ➎ >>> time.sleep(5)
تطبع حلقة for الكلمة Tick
➊، وتتوقف مؤقتًا لمدة ثانية واحدة ➋، ثم تطبع الكلمة Tock
➌، وتتوقف مؤقتًا لمدة ثانية واحدة ➍، ثم تطبع الكلمة Tick
، وتتوقف مؤقتًا، وهكذا حتى طباعة كلٍّ من الكلمتين Tick
و Tock
ثلاث مرات.
تُعَد الدالة time.sleep()
مُعطِّلة، أي أنها لن تعيد شيئًا ولن تحرّر برنامجك لتنفيذ شيفرة برمجية أخرى إلّا بعد انقضاء عدد الثواني التي مررتها إلى الدالة time.sleep()
، فمثلًا إذا أدخلتَ time.sleep(5)
➎، فلن تظهر تعليمة المطالبة التالية (>>>
) إلّا بعد مرور 5 ثوانٍ.
تقريب الأعداد
سترى في أغلب الأحيان عند التعامل مع الأوقات قيمًا عشرية تحتوي على العديد من الأعداد بعد الفاصلة العشرية، حيث يمكن تسهيل التعامل مع هذه القيم من خلال تقصيرها باستخدام الدالة round()
المُدمَجة مع لغة بايثون، والتي تقرّب الأعداد العشرية إلى الدقة التي تحدّدها، حيث تدخِل العدد الذي تريد تقريبه، بالإضافة إلى وسيط ثانٍ اختياري يمثّل عدد الأعداد بعد الفاصلة العشرية التي تريد تقريبه إليها. إذا حذفتَ الوسيط الثاني، فستقرّب الدالة round()
العدد إلى أقرب عدد صحيح كامل بدون فاصلة عشرية. لندخِل مثلًا ما يلي في الصدفة التفاعلية:
>>> import time >>> now = time.time() >>> now 1543814036.6147408 >>> round(now, 2) 1543814036.61 >>> round(now, 4) 1543814036.6147 >>> round(now) 1543814037
استوردنا الوحدة time
وخزّنا الدالة time.time()
في المتغير now
، ثم استدعينا الدالة round(now, 2)
لتقريب now
إلى عددين بعد الفاصلة العشرية، واستدعينا الدالة round(now, 4)
للتقريب إلى أربعة أعداد بعد الفاصلة العشرية، واستدعينا الدالة round(now)
للتقريب إلى أقرب عدد صحيح.
تطبيق عملي: برنامج المؤقت الزمني الفائق Super Stopwatch
لنفترض أنك تريد تعقّب مقدار الوقت الذي تقضيه لإنجاز المهام المملة التي لم تؤتمتها بعد، فليس لديك مؤقت زمني فعلي ومن الصعب العثور على تطبيق مؤقت زمني مجاني لحاسوبك المحمول أو هاتفك الذكي غير مملوءٍ الإعلانات ولا يرسل نسخة من سجل متصفحك إلى المسوّقين، فمذكور أن هذا التطبيق يمكنه ذلك في اتفاقية ترخيصه التي وافقت عليها ولم تقرأها على الأغلب. إذًا لنكتب برنامج مؤقت زمني بسيط باستخدام لغة بايثون.
إليك الخطوات العامة التي سيطبقها برنامجك:
-
تعقّب مقدار الوقت المنقضي بين الضغطات على مفتاح
ENTER
، حيث تبدأ كل ضغطة "دورةً Lap" جديدة في المؤقت. - طباعة رقم الدورة والوقت الإجمالي ووقت الدورة.
يجب أن تطبق شيفرتك البرمجية الخطوات التالية:
-
إيجاد الوقت الحالي من خلال استدعاء الدالة
time.time()
وتخزينه بوصفه علامة زمنية في بداية البرنامج، وفي بداية كل دورة أيضًا. -
الاحتفاظ بعدّاد دورات وزيادته في كل مرة يضغط فيها المستخدم على مفتاح
ENTER
. - حساب الوقت المنقضي من خلال طرح العلامات الزمنية.
-
معالجة الاستثناء
KeyboardInterrupt
حتى يتمكّن المستخدم من الضغط على الاختصارCTRL-C
للإنهاء.
افتح تبويبًا جديدًا في محرّرك لإنشاء ملف جديد واحفظه بالاسم stopwatch.py.
الخطوة الأولى: إعداد البرنامج لتعقّب الأوقات
يحتاج برنامج المؤقت الزمني إلى استخدام الوقت الحالي، لذا يجب استيراد الوحدة time
، ويجب أن يطبع برنامجك أيضًا بعض التعليمات المختصَرة للمستخدم قبل استدعاء الدالة input()
، إذ يمكن أن يبدأ المؤقت بعد أن يضغط المستخدم على مفتاح ENTER
، ثم ستبدأ الشيفرة البرمجية في تعقّب أوقات الدورات.
أدخِل الآن الشيفرة البرمجية التالية في محرّر ملفاتك، واكتب تعليقاتٍ في النهاية، والتي تمثّل عناصر بديلة لما تبقى من شيفرتك البرمجية:
#! python3 # stopwatch.py - برنامج مؤقت زمني بسيط import time # عرض تعليمات البرنامج print('Press ENTER to begin. Afterward, press ENTER to "click" the stopwatch. Press Ctrl-C to quit.') input() # الضغط على مفتاح Enter للبدء print('Started.') startTime = time.time() # الحصول على وقت بدء الدورة الأولى lastTime = startTime lapNum = 1 # البدء بتعقّب أوقات الدورات
كتبنا الشيفرة البرمجية لعرض التعليمات للمستخدم وبدء الدورة الأولى وتسجيل الوقت وضبط عدد الدورات على القيمة 1.
الخطوة الثانية: تعقّب أوقات الدورات وطباعتها
لنكتب الآن الشيفرة البرمجية لبدء دورات جديدة، وحساب المدة التي استغرقتها الدورة السابقة، وحساب إجمالي الوقت المنقضي منذ بدء المؤقت الزمني، حيث سنعرض وقت الدورة والوقت الإجمالي ونزيد عدد الدورات بمقدار 1 عند كل دورة جديدة. إذًا أضِف الشيفرة البرمجية التالية إلى برنامجك:
#! python3 # stopwatch.py - برنامج مؤقت زمني بسيط import time --snip-- # البدء بتعقّب أوقات الدورات ➊ try: ➋ while True: input() ➌ lapTime = round(time.time() - lastTime, 2) ➍ totalTime = round(time.time() - startTime, 2) ➎ print('Lap #%s: %s (%s)' % (lapNum, totalTime, lapTime), end='') lapNum += 1 lastTime = time.time() # إعادة ضبط وقت الدورة الأخيرة ➏ except KeyboardInterrupt: # معالجة الاستثناء Ctrl-C لمنع عرض رسالة الخطأ print('\nDone.')
إذا ضغط المستخدم على الاختصار CTRL-C
لإيقاف المؤقت الزمني، فسيظهر الاستثناء KeyboardInterrupt
، وسيتعطل البرنامج إذا لم يكن تنفيذه موجودًا ضمن تعليمة try
، لذا غلّفنا هذا الجزء من البرنامج ضمن تعليمة try
➊، وسنعالج الاستثناء ضمن التعليمة except
➏، لذا ينتقل تنفيذ البرنامج إلى التعليمة except
لطباعة الكلمة Done
بدلًا من رسالة الخطأ KeyboardInterrupt
عند الضغط على الاختصار CTRL-C
ورفع الاستثناء. يكون التنفيذ ضمن حلقة لا نهائية ➋ حتى حدوث الاستثناء، حيث تستدعي هذه الحلقة الدالة input()
وتنتظر حتى يضغط المستخدم على مفتاح ENTER
لإنهاء الدورة. إذا انتهت الدورة، فسنحسب المدة التي استغرقتها الدورة من خلال طرح وقت بدء الدورة lastTime
من الوقت الحالي time.time()
➌، ويمكننا حساب إجمالي الوقت المنقضي من خلال طرح وقت البدء الإجمالي للمؤقت الزمني startTime
من الوقت الحالي ➍.
ستحتوي نتائج حسابات الوقت على العديد من الأعداد بعد الفاصلة العشرية مثل العد 4.766272783279419، لذا استخدمنا الدالة round()
لتقريب القيمة العشرية إلى عددين في التعلمتين ➌ و➍.
نطبع بعد ذلك رقم الدورة والوقت الإجمالي المنقضي ووقت الدورة ➎. يطبع المستخدم، الذي يضغط على مفتاح ENTER
لاستدعاء الدالة input()
، سطرًا جديدًا على الشاشة، لذا مرّر الوسيط end=''
إلى الدالة print()
لتجنب مضاعفة المسافة بين المخرجات. نتجهّز للدورة التالية بعد طباعة معلومات الدورة من خلال إضافة القيمة 1 إلى العدّاد lapNum
ونضبط المتغير lastTime
على الوقت الحالي الذي يمثّل وقت بدء الدورة التالية.
أفكار لبرامج مماثلة
يفتح تعقّب الوقت العديدَ من الاحتمالات أمام برامجك، حيث يمكنك كتابة هذه البرامج بنفسك بالرغم من أنه يمكنك تنزيل تطبيقاتٍ تنفّذ بعضًا منها، ولكن ستكون البرامج التي تكتبها بنفسك مجانية وغير مملوءة بالإعلانات والميزات عديمة الفائدة، لذلك جرّب كتابة برامج مماثلة تطبّق ما يلي:
- إنشاء تطبيق جدول حضور زمني Timesheet بسيط يسجّل متى كتبتَ اسم شخصٍ ما ويستخدم الوقت الحالي لتسجيل زمن دخوله أو خروجه.
-
إضافة ميزة إلى برنامجك لعرض الوقت المنقضي منذ بدء عمليةٍ ما مثل عملية التنزيل التي تستخدم الوحدة
requests
. - التحقّق خلال فترات زمنية متقطعة من مدة تشغيل البرنامج ومنح المستخدم فرصة لإلغاء المهام التي تستغرق وقتًا طويلًا.
الوحدة datetime
تُعَد الوحدة time
مفيدةً للحصول على علامة يونيكس الزمنية للعمل معها، ولكن إذا أردتَ عرض التاريخ بتنسيق أسهل أو إجراء العمليات الحسابية باستخدام التواريخ مثل معرفة التاريخ الذي كان قبل 205 يومًا أو التاريخ الذي سيكون بعد 123 يومًا من الآن، فيجب أن تستخدم الوحدة datetime
.
تمتلك الوحدة datetime
نوع البيانات datetime
الخاص بها، حيث تمثل القيم التي نوعها datetime
لحظةً محددة من الزمن. لندخِل الآن ما يلي في الصدفة التفاعلية:
>>> import datetime ➊ >>> datetime.datetime.now() ➋ datetime.datetime(2024, 2, 27, 11, 10, 49, 55, 53) ➌ >>> dt = datetime.datetime(2023, 10, 21, 16, 29, 0) ➍ >>> dt.year, dt.month, dt.day (2023, 10, 21) ➎ >>> dt.hour, dt.minute, dt.second (16, 29, 0)
يؤدي استدعاء الدالة datetime.datetime.now()
➊ إلى إعادة الكائن datetime
➋ للتاريخ والوقت الحاليين وفقًا لساعة حاسوبك، حيث يتضمن هذا الكائن السنة والشهر واليوم والساعة والدقيقة والثانية والميكروثانية للحظة الحالية. يمكنك أيضًا استرداد الكائن datetime
للحظة معينة باستخدام الدالة datetime.datetime()
➌ وتمرير أعداد صحيحة إليها، والتي تمثّل السنة والشهر واليوم والساعة والدقيقة والثانية للحظة التي تريدها، وتُخزَّن هذه الأعداد الصحيحة في سمات Attributes خاصة بالكائن datetime
، وهذه السمات هي year
و month
و day
➍ و hour
و minute
و second
➎.
يمكن تحويل علامة يونيكس الزمنية إلى كائن datetime
باستخدام الدالة datetime.datetime.fromtimestamp()
، ويُحوَّل التاريخ والوقت الخاصين بكائن datetime
إلى المنطقة الزمنية المحلية. إذًا أدخِل ما يلي في الصدفة التفاعلية:
>>> import datetime, time >>> datetime.datetime.fromtimestamp(1000000) datetime.datetime(1970, 1, 12, 5, 46, 40) >>> datetime.datetime.fromtimestamp(time.time()) datetime.datetime(2023, 10, 21, 16, 30, 0, 604980)
يؤدي استدعاء الدالة datetime.datetime.fromtimestamp()
وتمرير القيمة 1000000
إليها إلى إعادة كائن datetime
للحظة التي تكون بعد 1,000,000 ثانية من توقيت يونيكس، بينما يؤدي تمرير الدالة time.time()
، التي تمثّل علامة يونيكس الزمنية للحظة الحالية، إلى الدالة datetime.datetime.fromtimestamp()
إلى إعادة كائن datetime
للحظة الحالية، إذ يفعل التعبيران datetime.datetime.now()
و datetime.datetime.fromtimestamp(time.time())
الشيء نفسه، حيث يعطيان كائن datetime
للوقت الحالي.
يمكنك مقارنة كائنات datetime
مع بعضها البعض باستخدام عوامل المقارنة لمعرفة أيّ منها يسبق الآخر، حيث يكون لكائن datetime
الأحدث القيمة الأكبر. لندخِل الآن ما يلي في الصدفة التفاعلية:
➊ >>> halloween2023 = datetime.datetime(2023, 10, 31, 0, 0, 0) ➋ >>> newyears2024 = datetime.datetime(2024, 1, 1, 0, 0, 0) >>> oct31_2023 = datetime.datetime(2023, 10, 31, 0, 0, 0) ➌ >>> halloween2023 == oct31_2023 True ➍ >>> halloween2023 > newyears2024 False ➎ >>> newyears2024 > halloween2023 True >>> newyears2024 != oct31_2023 True
أنشأنا كائن datetime
للحظة الأولى (منتصف الليل) من 31 من الشهر العاشر من عام 2023، وخزّناه في المتغير halloween2023
➊، ثم أنشأنا كائن datetime
للحظة الأولى من 1 من الشهر الأول من عام 2024، وخزّناه في المتغير newyears2024
➋، ثم أنشأنا كائنًا آخر لمنتصف ليل يوم 31 من الشهر العاشر من عام 2023، وخزّناه في المتغير oct31_2023
. تُظهِر المقارنة بين المتغيرين halloween2023
و oct31_2023
أنهما متساويان ➌، وتُظهِر مقارنة المتغيرين newyears2024
و halloween2023
أن newyears2024
أكبر (أو أحدث) من halloween2023
➍ ➎.
نوع البيانات timedelta
توفر الوحدة datetime
أيضًا نوع البيانات timedelta
الذي يمثل مدة زمنية بدلًا من توفير لحظة زمنية. لندخِل الآن ما يلي في الصدفة التفاعلية:
➊ >>> delta = datetime.timedelta(days=11, hours=10, minutes=9, seconds=8) ➋ >>> delta.days, delta.seconds, delta.microseconds (11, 36548, 0) >>> delta.total_seconds() 986948.0 >>> str(delta) '11 days, 10:09:08'
نستخدم الدالة datetime.timedelta()
لإنشاء كائن timedelta
، حيث تأخذ هذه الدالة وسطاء الكلمات المفتاحية Keyword Arguments التي هي weeks
و days
و hours
و minutes
و seconds
و milliseconds
و microseconds
، ولا توجد وسطاء الكلمات المفتاحية month
و year
، إذ يُعَد الشهر أو السنة مقدارًا متغيرًا من الزمن اعتمادًا على شهرٍ أو سنة معينة. يحتوي الكائن timedelta
على المدة الإجمالية المُمثَّلة بالأيام والثواني والميكروثانية، حيث تُخزَّن هذه الأعداد في السمات days
و seconds
و microseconds
. يعيد التابع total_seconds()
المدة بعدد الثواني فقط، بينما يؤدي تمرير كائن timedelta
إلى الدالة str()
إلى إعادة تمثيل سلسلة نصية مُنسَّقة جيدًا وقابلة للقراءة البشرية لهذا الكائن.
مرّرنا في المثال السابق وسطاء الكلمات المفتاحية إلى الدالة datetime.timedelta()
لتحديد مدة 11 يومًا و10 ساعات و9 دقائق و8 ثوانٍ، وخزّنا كائن timedelta
المُعاد في المتغير delta
➊. تخزِّن السمة days
الخاصة بكائن timedelta
القيمة 11، وتخزن السمة seconds
القيمة 36548 (أي 10 ساعات و9 دقائق و8 ثوانٍ من خلال التعبير عنها بالثواني) ➋. يخبرنا استدعاء الدالة total_seconds()
أن 11 يومًا و10 ساعات و9 دقائق و8 ثوانٍ هي 986,948 ثانية، ويعيد تمرير كائن timedelta
إلى الدالة str()
سلسلةً نصية تشرح المدة بوضوح.
يمكن استخدام المعاملات الحسابية لإجراء عملية حسابية للتاريخ على قيم datetime
، فمثلًا أدخِل ما يلي في الصدفة التفاعلية لحساب التاريخ بعد 1000 يوم من الآن:
>>> dt = datetime.datetime.now() >>> dt datetime.datetime(2018, 12, 2, 18, 38, 50, 636181) >>> thousandDays = datetime.timedelta(days=1000) >>> dt + thousandDays datetime.datetime(2021, 8, 28, 18, 38, 50, 636181)
أنشأنا أولًا كائن datetime
للحظة الحالية وخزّناه في المتغير dt
، ثم أنشأنا كائن timedelta
لمدة 1000 يوم وخزّناه في المتغير thousandDays
، ثم جمعنا dt
و thousandDays
للحصول على كائن datetime
للتاريخ بعد 1000 يوم من الآن. تجري شيفرة بايثون عملية حسابية للتاريخ لمعرفة أن 1000 يوم بعد 2 من الشهر 12 من عام 2018 ستكون في 18 من الشهر الثامن من عام 2021. يُعَد ذلك مفيدًا لأنه يجب أن تتذكّر عدد الأيام في كل شهر والعامل المشترك للسنوات الكبيسة وغيرها من التفاصيل الصعبة عندما تحسب 1000 يوم بعد تاريخ معين، لذا تعالج الوحدة datetime
جميع تلك الأمور نيابةً عنك.
يمكن جمع كائنات timedelta
أو طرحها من كائنات datetime
أو كائنات timedelta
الأخرى باستخدام المعاملَين +
و -
، ويمكن ضرب كائن timedelta
أو قسمته على عدد صحيح أو قيم عشرية باستخدام المعاملَين *
و /
. لندخِل مثلًا ما يلي في الصدفة التفاعلية:
➊ >>> oct21st = datetime.datetime(2019, 10, 21, 16, 29, 0) ➋ >>> aboutThirtyYears = datetime.timedelta(days=365 * 30) >>> oct21st datetime.datetime(2019, 10, 21, 16, 29) >>> oct21st - aboutThirtyYears datetime.datetime(1989, 10, 28, 16, 29) >>> oct21st - (2 * aboutThirtyYears) datetime.datetime(1959, 11, 5, 16, 29)
أنشأنا كائن datetime
ليوم 21 من الشهر العاشر من عام 2019 ➊، وأنشأنا كائن timedelta
لمدة 30 عامًا تقريبًا بافتراض أن السنة تتكون من 365 يومًا ➋. يؤدي طرح aboutThirtyYears
من oct21st
إلى الحصول على كائن datetime
للتاريخ قبل 30 عامًا من تاريخ 21 من الشهر العاشر من عام 2019، ويؤدي طرح 2 * aboutThirtyYears
من oct21st
إلى إعادة كائن datetime
للتاريخ قبل 60 عامًا من تاريخ 21 من الشهر العاشر من عام 2019.
الإيقاف المؤقت حتى تاريخ محدد
يتيح التابع time.sleep()
إيقافَ برنامجٍ ما مؤقتًا لعددٍ محدّدٍ من الثواني، حيث يمكنك إيقاف برامجك مؤقتًا حتى تاريخ محدّد باستخدام حلقة while، فمثلًا ستستمر الشيفرة البرمجية التالية في التكرار حتى يوم الهالوين من عام 2024:
import datetime import time halloween2024 = datetime.datetime(2024, 10, 31, 0, 0, 0) while datetime.datetime.now() < halloween2016: time.sleep(1)
سيؤدي استدعاء time.sleep(1)
إلى إيقاف برنامج بايثون الخاص بك مؤقتًا حتى لا يضيع الحاسوب دورات معالجة لوحدة المعالجة المركزية بعد التحقق من الوقت مرارًا وتكرارًا، لذا تتحقق حلقة while
من الشرط مرة واحدة في الثانية وتستمر إلى باقي البرنامج بعد يوم الهالوين من عام 2024 (أو أيّ تاريخ تبرمجه للتوقف).
تحويل كائنات datetime إلى سلاسل نصية
لا تُعَد علامات يونيكس الزمنية وكائنات datetime
سهلة القراءة، لذا نستخدم التابع strftime()
لعرض كائن datetime
بوصفها سلسلة نصية، حيث يشير الحرف f الموجود في اسم الدالة strftime()
إلى التنسيق format. يستخدم التابع strftime()
موجّهات Directives مشابهة لتنسيق سلاسل بايثون النصية، حيث يحتوي الجدول التالي على قائمة كاملة بموجّهات التابع strftime()
:
موجّه التابع strftime() | معناه |
---|---|
%Y |
العام مع القرن مثل '2024'
|
%y |
العام بدون القرن من '00' إلى '99' (من عام 1970 إلى 2069 مثلًا)
|
%m |
الشهر كعدد عشري من '01' إلى '12'
|
%B |
اسم الشهر كاملًا مثل 'November'
|
%b |
اسم الشهر المختصر مثل 'Nov'
|
%d |
يوم من الشهر من '01' إلى '31'
|
%j |
يوم من السنة من '001' إلى '366'
|
%w |
يوم من الأسبوع من '0' (الأحد) إلى '6' (السبت)
|
%A |
الاسم الكامل ليوم من الأسبوع مثل 'Monday'
|
%a |
الاسم المختصر ليوم من الأسبوع مثل 'Mon'
|
%H |
الساعة (نظام 24 ساعة) من '00' إلى '23'
|
%I |
الساعة (نظام 12 ساعة) من '01' إلى '12'
|
%M |
الدقيقة من '00' إلى '59'
|
%S |
الثانية من '00' إلى '59'
|
%p |
صباحًا 'AM' أو مساءً 'PM'
|
%% |
المحرف '%' حرفيًا
|
مرّر سلسلة نصية ذات تنسيقٍ مخصَّص تحتوي على موجّهات التنسيق (مع أيّ خطوط مائلة ونقطتين وغير ذلك) إلى التابع strftime()
، وسيعيد هذا التابع معلومات كائن datetime
بوصفها سلسلة نصية مُنسَّقة. لندخِل الآن ما يلي في الصدفة التفاعلية:
>>> oct21st = datetime.datetime(2023, 10, 21, 16, 29, 0) >>> oct21st.strftime('%Y/%m/%d %H:%M:%S') '2023/10/21 16:29:00' >>> oct21st.strftime('%I:%M %p') '04:29 PM' >>> oct21st.strftime("%B of '%y") "October of '23"
خزّنا في المثال السابق كائن datetime
ليوم 21 من الشهر العاشر من عام 2023 في الساعة 4:29 مساءً في المتغير oct21st
. يعيد تمرير سلسلة التنسيق المخصَّصة '%Y/%m/%d %H:%M:%S'
إلى التابع strftime()
سلسلةً نصية تحتوي على القيم 2023 و10 و21 المفصولة بخطوط مائلة والقيم 16 و29 و00 المفصولة بنقطتين، ويؤدي تمرير السلسلة النصية '%I:%M% p'
إلى إعادة '04:29 PM'
، ويؤدي تمرير السلسلة النصية "%B of '%y"
إلى إعادة "October of '23"
. لاحظ أننا لا نضع datetime.datetime
قبل التابع strftime()
.
تحويل السلاسل النصية إلى كائنات datetime
إذا كان لديك سلسلة نصية تمثّل معلومات التاريخ مثل '2023/10/21 16:29:00'
أو 'October 21, 2023'
وتريد تحويلها إلى كائن datetime
، فاستخدم الدالة datetime.datetime.strptime()
، حيث تُعَد هذه الدالة عكس التابع strftime()
. يجب تمرير سلسلة تنسيق مُخصَّصة تستخدم الموجّهات نفسها التي يستخدمها التابع strftime()
إلى الدالة strptime()
حتى تعرف كيفية تحليل السلسلة النصية وفهمها، ويشير الحرف p الموجود في اسم الدالة strptime()
إلى التحليل Parse. لندخِل الآن ما يلي في الصدفة التفاعلية:
➊ >>> datetime.datetime.strptime('October 21, 2023', '%B %d, %Y') datetime.datetime(2023, 10, 21, 0, 0) >>> datetime.datetime.strptime('2023/10/21 16:29:00', '%Y/%m/%d %H:%M:%S') datetime.datetime(2023, 10, 21, 16, 29) >>> datetime.datetime.strptime("October of '23", "%B of '%y") datetime.datetime(2023, 10, 1, 0, 0) >>> datetime.datetime.strptime("November of '63", "%B of '%y") datetime.datetime(2063, 11, 1, 0, 0)
يمكن الحصول على كائن datetime
من السلسلة النصية 'October 21, 2023'
من خلال تمرير هذه السلسلة كوسيطٍ أول إلى الدالة strptime()
وتمرير سلسلة التنسيق المُخصصة المقابلة للسلسلة النصية 'October 21, 2023'
كوسيطٍ ثانٍ ➊. يجب أن تتطابق السلسلة النصية التي تحتوي على معلومات التاريخ مع سلسلة التنسيق المخصصة تمامًا، وإلّا سيرفع بايثون استثناء ValueError
.
مراجعة لدوال بايثون الخاصة بالوقت
يمكن أن تتضمن التواريخ والأوقات في بايثون عددًا من أنواع البيانات والدوال المختلفة، لذا سنوضح فيما يلي الأنواع الثلاثة المختلفة من القيم المُستخدَمة لتمثيل الوقت:
-
علامة يونيكس الزمنية التي تستخدمها الوحدة
time
، وهي قيمة عشرية أو صحيحة لعدد الثواني منذ الساعة 12 صباحًا في 1 من الشهر الأول من عام 1970 بالتوقيت العالمي المنسق. -
كائن
datetime
الخاص بالوحدةdatetime
، والذي يحتوي على أعداد صحيحة مخزَّنة في السماتyear
وmonth
وday
وhour
وminute
وsecond
. -
كائن
timedelta
الخاص بالوحدةdatetime
، والذي يمثّل مدة زمنية وليس لحظة مُحدَّدة.
إليك مراجعة لدوال الوقت ومعاملاتها والقيم التي تعيدها:
-
time.time()
: تعيد هذه الدالة القيمة العشرية لعلامة يونيكس الزمنية للحظة الحالية. -
time.sleep(seconds)
:توقِف هذه الدالة البرنامج لعددٍ من الثواني التي يحدّدها الوسيطseconds
. -
datetime.datetime(year, month, day, hour, minute, second)
: تعيد هذه الدالة كائنdatetime
للحظة التي تحدّدها وسطاؤها. إذا لم تتوفّر قيم للوسطاءhour
أوminute
أوsecond
، فستكون قيمها الافتراضية 0. -
datetime.datetime.now()
: تعيد هذه الدالة كائنdatetime
للحظة الحالية. -
datetime.datetime.fromtimestamp(epoch)
: تعيد هذه الدالة كائنdatetime
للحظة التي يمثلها وسيط العلامة الزمنيةepoch
. -
datetime.timedelta(weeks, days, hours, minutes, seconds, milliseconds, microseconds)
: تعيد هذه الدالة كائنtimedelta
الذي يمثل مدة زمنية، وتُعَد وسطاء الكلمات المفتاحية لهذه الدالة اختيارية ولا تتضمنmonth
أوyear
. -
total_seconds()
: يعيد هذا التابع الخاص بكائناتtimedelta
عدد الثواني التي يمثّلها كائنtimedelta
. -
strftime(format)
: يعيد هذا التابع سلسلة نصية للوقت الذي يمثّله كائنdatetime
بتنسيقٍ مخصَّص يعتمد على سلسلة التنسيقformat
. اطّلع على الجدول السابق للحصول على تفاصيل التنسيق. -
datetime.datetime.strptime(time_string, format)
: تعيد هذه الدالة كائنdatetime
للحظة التي يحدّدها الوسيطtime_string
، وتُحلَّل باستخدام وسيط سلسلة التنسيقformat
. اطّلع على الجدول السابق للحصول على تفاصيل التنسيق.
الخلاصة
يُعَد توقيت يونيكس (1 من الشهر الأول من عام 1970 عند منتصف الليل بالتوقيت العالمي المنسَّق) وقتًا مرجعيًا معياريًا للعديد من لغات البرمجة بما في ذلك لغة بايثون. تعيد الوحدة الخاصة بالدالة time.time()
علامة يونيكس الزمنية (أي قيمة عشرية لعدد الثواني منذ توقيت يونيكس)، ولكن تُعَد الوحدة datetime
أفضل لإجراء العمليات الحسابية الرياضية على التاريخ وتنسيق أو تحليل السلاسل النصية باستخدام معلومات التاريخ. ستوقَِف الدالة time.sleep()
التنفيذ (أي لن تعود) لعددٍ معين من الثواني، حيث يمكنك استخدام ذلك لإضافة فترات توقف مؤقتة إلى برنامجك.
ترجمة -وبتصرُّف- للقسم Keeping Time من مقال Keeping Time, Scheduling Tasks, and Launching Programs لصاحبه Al Sweigart.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.