الوقت والتاريخ في بايثون

من موسوعة حسوب
مراجعة 12:06، 16 سبتمبر 2021 بواسطة Mohammed Taher (نقاش | مساهمات)
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)

تقدّم وحدة datetime عددًا من الأصناف التي تعالج التاريخ والوقت بطرق مبسّطة وأخرى معقدة، وتدعم بايثون إجراء العمليات الحسابية على التواريخ والأوقات.

>>> from datetime import date
>>> now = date.today()
>>> now
datetime.date(2018, 3, 24)
>>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.")
'03-24-18. 24 Mar 2018 is a Saturday on the 24 day of March.'

>>> # تدعم التواريخ العمليات الحسابية
>>> birthday = date(1964, 7, 31)
>>> age = now - birthday
>>> age.days
14368

هناك نوعان من كائنات الوقت والتاريخ: "الواعي aware" و "البسيط naive" .

يمتلك الكائن الواعي معرفة كافية بالعمليات الحسابية والتعديلات الدولية على الأوقات، كالمناطق الزمنية والتوقيت الصيفي، وتعديل القيمة الخاصّة به بصورة تتناسب مع الكائنات الواعية الأخرى. يستخدم الكائن الواعي لتمثيل فترة زمنية معيّنة غير مفتوحة للتفسير.

أما الكائن البسيط فلا يمتلك المعلومات الكافية ليضع نفسه في المكان الصحيح نسبة إلى كائنات الوقت أو التاريخ الأخرى. تعتمد القيمة التي يمثّلها الكائن البسيط.

عندما يستخدم برنامج عددًا معيّنًا فإنّ ما يمثّله هذا العدد يُحدّد بواسطة البرنامج، فقد يمثّل العدد كتلة أو مسافة بالأمتار أو الأميال، وكذلك الأمر بالنسبة إلى كائنات الوقت والتاريخ البسيطة، فسواء أكان الكائن يصف التوقيت العالمي المنسق (Universal Coordinated Time يعرف اختصارًا UTC) أو التوقيت المحلي، أو التوقيت في منطقة زمنية أخرى، فإنّ ما يمثّله الكائن أو يصفه هو مسؤولية البرنامج فقط.

إنّ العمل على الكائنات البسيطة وفهمها أمر سهل للغاية، ولكن على حساب تجاهل بعض الجوانب الواقعية.

إن كان التطبيق يتطلب استخدام الكائنات الواعية، فإنّ الكائنين datetime و time يمتلكان الخاصية tzinfo ووظيفتها تعيين المنطقة الزمنية كنسخة صنف فرعي من الصنف المجرّد tzinfo. تجمع كائنات tzinfo المعلومات المتعلقة بمقدار الإزاحة عن التوقيت العالمي المنسّق واسم المنطقة الزمنية والتوقيت الصيفي. 

تدعم الوحدة datetime الصنف timezone فقط، والذي يمكن أن يمثل مناطق زمنيّة ذات إزاحة ثابتة عن التوقيت العالمي المنسق، مثل التوقيت العالمي نفسه أو توقيت شمال أمريكا EST و EDT. تحدد التطبيقات طبيعة المعلومات المتوفّرة عن كل منطقة زمنية، وقواعد تعديل الوقت حول العالم تخضع لظروف سياسية أكثر منها منطقية وهي عرضة للتغيير باستمرار، ولا يوجد معيار ملائم لجميع التطبيقات باستثناء التوقيت العالمي المنسق.

أنواع البيانات في وحدة datetime

تقدم وحدة datetime أنواع البيانات التالية:

الصنف datetime.date

يمثّل هذا الصنف التاريخ بصيغة مثالية وهو من النوع البسيط، ويفترض أنّ التقويم الميلادي هو المستخدم للتعبير عن التاريخ، ويضمّ هذا الصنف الخصائص: year و month و day.

from datetime import date
>>> now = date.today()
>>> now.day
24
>>> now.year
2018
>>> now.month
3

الصنف datetime.time

يمثّل هذا الصنف الوقت وهو مستقلّ عن الأيام، ويفترض أنّ كل يوم يمتدّ 24*60*60 ثانية، ويضم الخصائص التالية: hour و minute و second و microsecond و tzinfo.

>> from datetime import time
>>> time(hour=12, minute=34, second=56, microsecond=123456).isoformat(timespec='minutes')
'12:34'

الصنف datetime.datetime

يمثّل هذا الصنف مزيجًا بين الصنفين date و time، ويضمّ الخصائص التالية: year و month و day و hour و minute و second و microsecond و tzinfo.

>>>from datetime import datetime
>>> datetime.now().isoformat(timespec='minutes')
'2002-12-25T00:00'
>>> dt = datetime(2015, 1, 1, 12, 30, 59, 0)
>>> dt.isoformat(timespec='microseconds')
'2015-01-01T12:30:59.000000'

الصنف datetime.timedelta

هو عبارة عن مدّة زمنية تمثّل الفرق بين نسختين لصنفي date أو time أو datetime وبدقّة تصل إلى أجزاء الثانية.

>>> from datetime import timedelta
>>> year = timedelta(days=365)
>>> another_year = timedelta(weeks=40, days=84, hours=23, minutes=50, seconds=600)  # المجموع 365 يومًا
>>> year.total_seconds()
31536000.0
>>> year == another_year
True
>>> ten_years = 10 * year
>>> ten_years, ten_years.days // 365
(datetime.timedelta(3650), 10)
>>> nine_years = ten_years - year
>>> nine_years, nine_years.days // 365
(datetime.timedelta(3285), 9)
>>> three_years = nine_years // 3;
>>> three_years, three_years.days // 365
(datetime.timedelta(1095), 3)
>>> abs(three_years - ten_years) == 2 * three_years + year
True

الصنف datetime.tzinfo

صنف مجرّد أساسي يختصّ بالمعلومات المرتبطة بالمناطق الزمنية والتي تستخدم من طرف الأصناف datetime و time لعرض الوقت والتاريخ حسب المنطقة الزمنية أو مع مراعاة التوقيت الصيفي.

الصنف datetime.timezone

وهو صنف يستخدم الصنف المجرد الأساسي tzinfo كإزاحة ثابتة عن التوقيت العالمي المنسّق UTC.

ترتبط هذه الأصناف ببعضها البعض حسب المخطط التالي:

object
    timedelta
    tzinfo
        timezone
    time
    date
        datetime

التابعان strftime()‎ و strptime()

تدعم كائنات date و datetime و time التابع strftime()‎ والذي يُنشئ سلسلة نصية تتضمّن التاريخ  الذي يجري التعامل معه. أما التابع strptime()‎ فينشئ كائن datetime من سلسلة نصية تمثّل الوقت والتاريخ بواسطة علامات تنسيق خاصة يوضّحها الجدول التالي.

يجب عدم استخدام علامات التنسيق الخاصة بالسنة والشهر واليوم مع كائنات time، وفي حال استخدامها تأخذ السنة القيمة 1900 ويأخذ الشهر واليوم القيمة 1.

كذلك يجب عدم استخدام علامات التنسيق الخاصة بالساعة والدقيقة والثانية وجزء الثانية مع كائنات date، وفي حال استخدامها تأخذ جميعها القيمة 0.

الموجه المعنى مثال ملاحظات
‎%a الاسم المختصر لليوم حسب الإعدادات المحلية. Sun, Mon, …, Sat (en_US)‎

So, Mo, …, Sa (de_DE)‎

(1)
‎%A الاسم الكامل لليوم حسب الإعدادات المحلية. Sunday, Monday, …, Saturday (en_US)‎،

Sonntag, Montag, …, Samstag (de_DE)‎

(1)
‎%w اليوم كعدد عشري، يمثل الرقم 0 يوم الأحد والرقم 6 يوم السبت. 6, ..., 1, 0
‎%d اليوم في الشهر كعدد عشري يسبقه 0. 31, ..., 02, 01
‎%b الاسم المختصر للشهر حسب الإعدادات المحلية. Jan, Feb, …, Dec (en_US)‎،

Jan, Feb, …, Dez (de_DE)‎

(1)
‎%B الاسم الكامل للشهر حسب الإعدادات المحلية. January, February, …, December (en_US)‎،

Januar, Februar, …, Dezember (de_DE)‎

(1)
‎%m الشهر كعدد عشري يسبقه 0. 12, ..., 02, 01
‎%y الصيغة المختصرة للسنة (مرتبتا الآحاد والعشرات فقط دون ذكر القرن الحالي). 99, ..., 02, 01
‎%Y الصيغة الكاملة للسنة (مع ذكر القرن الحالي). 9999, 9998, ...., 2018, 2017, ...., 0002, 0001 (2)
‎%H الساعة كعدد عشري (بنظام 24 ساعة) يسبقه 0. 23, ..., 01, 00
‎%I الساعة كعدد عشري (بنظام 12 ساعة) يسبقه 0. 12, ..., 02, 01
‎%p ما يكافئ AM (قبل الظهر) و PM (بعد الظهر) في الإعدادات المحلية. AM, PM (en_US)‎،

am, pm (de_DE)‎

(3) و (1)
‎%M الدقائق كعدد عشري يسبقه 0. 59, ..., 01, 00
‎%S الثواني كعدد عشري يسبقه 0. 59, ..., 01, 00 (4)
‎%f أجزاء الثانية كعدد عشري تسبقه الأصفار من جهة اليسار. 999999, ..., 000001, 000000 (5)
‎%z الإزاحة من التوقيت العالمي المنسق UTC بالصيغة ‎+HHMM أو ‎-HHMM (سلسلة نصية فارغة إن كان الكائن بسيطًا naive). ‎(empty), +0000, -0400, +1300‎ (6)
‎%Z اسم المنطقة الزمنية (سلسلة نصية فارغة كان الكائن بسيطًا) ‎(empty), UTC, EST, CST‎
‎%j اليوم في السنة كعدد عشري تسبقه الأصفار. 366, ..., 002, 001
‎%U رقم الأسبوع في السنة (يوم الأحد هو اليوم الأول في الأسبوع) كعدد عشري تسبقه الأصفار. تعدّ جميع الأيام التي تسبق أوّل يوم أحد في السنة الجديدة ضمن الأسبوع 0. 53, ..., 02, 01 (7)
‎%W رقم الأسبوع في السنة (يوم الاثنين هو اليوم الأول في الأسبوع) كعدد عشري تسبقه الأصفار. تعدّ جميع الأيام التي تسبق أوّل يوم اثنين في السنة الجديدة ضمن الأسبوع 0. 53, ..., 02, 01 (7)
‎%c التمثيل المناسب للتاريخ والوقت حسب الإعدادات المحلية. Tue Aug 16 21:30:00 1988 (en_US)‎،

Di 16 Aug 21:30:00 1988 (de_DE)‎

(1)
‎%x التمثيل المناسب للتاريخ حسب الإعدادات المحلية. ‎08/16/88 (None)‎،

‎08/16/1988 (en_US)‎،

‎16.08.1988 (de_DE)‎

(1)
‎%X التمثيل المناسب للوقت حسب الإعدادات المحلية. ‎21:30:00 (en_US)‎،

‎21:30:00 (de_DE)‎

(1)
‎%% الحرف %. %

الملاحظات:

  1. يعتمد تنسيق السلسلة النصية على الإعدادات المحلية لنظام التشغيل، ونظرًا لذلك يجب الانتباه إلى هذا الأمر عند عرض المخرجات. فقد يتغير ترتيب الحقول (مثلًا: الشهر/اليوم/السنة مقابل اليوم/الشهر/السنة) وقد تتضمن المخرجات حروف يونيكود وتستخدم الترميز الافتراضي المحلي (مثلًا، إن كانت الإعدادات المحلية هي ja_JP فإنّ الترميز الافتراضي سيكون إمّا eucJP أو SJIS أو utf-8. يمكن استخدام التابع locale.getlocale()‎ لتحديد ترميز الإعداد المحلية).
  2. يمكن للتابع strptime()‎ أن يتعامل مع السنوات بصيغتها الكاملة [1, 9999] ولكن يجب إضافة الأصفار إلى يسار رقم السنة إن كانت أقل من 1000تغيير في الإصدار 3.2: كان التابع strftime()‎ في الإصدارات السابقة مقيدًا بالسنة التي تتجاوز أو تساوي 1900. تغيير في الإصدار 3.3: كان التابع في الإصدار 3.2 مقيدًا بالسنة التي تتجاوز أو تساوي 1000.
  3. عند استخدام الموجّه ‎%p مع التابع strptime()‎ فإنّه يؤثّر على حقل الساعة فقط في المخرجات إن كان الموجّه ‎%I مستخدمًا لعرض الساعة.
  4. وحدة datetime وعلى العكس من وحدة time لا تدعم الثواني الكبيسة.
  5. عند استخدام الموجّه ‎%f مع التابع strptime()‎ فإنّه يقبل الأعداد من مرتبة واحدة إلى ست مراتب مع إضافة الأصفار إلى اليمين. 
  6. بالنسبة للكائنات البسيطة يحلّ محل الموجّهين ‎%z و ‎%Z سلسلة نصية. أما بالنسبة للكائنات الواعية: عند استخدام الموجّه ‎%z: تحوّل قيمة utcoffset()‎ إلى سلسلة نصية ذات 5 أحرف على هيئة ‎+HHMM أو ‎-HHMM إذ تمثل HH سلسلة نصية ذات حرفين فيها عدد ساعات الإزاحة عن UTC وتمثّل MM سلسلة نصية ذات حرفين فيها عدد دقائق الإزاحة عن UTC. فمثلًا لو أعاد التابع utcoffset()‎ القيمة timedelta(hours=-3, minutes=-30)‎ فإنّ السلسلة النصية '‎-0330' ستحلّ محل ‎الموجه ‎%z. عند استخدام الموجّه ‎%Z: إن أعاد التابع tzname()‎ القيمة None فإنّ سلسلة نصية تحلّ محلّ الموجّه ‎%Z. وإلا فإنّ القيمة المعادة (والتي يجب أن تكون سلسلة نصية) ستحلّ محلّ الموجّه. تغيير في الإصدار 3.2: ينتج عن تقديم الموجه ‎%z إلى التابع strptime()‎ كائن datetime واعٍ، وستعيّن tzinfo في النتيجة المستحصلة إلى نسخة timezone.
  7. عند استخدام الموجّهين ‎%U و ‎%W في التابع strptime()‎ فإنّهما لا يدخلان في الحسابات إلا إذا عيّن اليوم في الأسبوع والسنة (‎%Y).

مصادر