تحويل السلاسل إلى تاريخ ووقت في بايثون

المُقدّمة

يمكن تمثيل البيانات في أشكال مختلفة - وطريقة مناسبة لتمثيل التواريخ والأوقات سلاسل. ومع ذلك ، للعمل مع هذه التواريخ والأوقات بطريقة حسابية (مثل حساب الفروق الزمنية ، وإضافة الوقت أو إزالته ، وما إلى ذلك) - نحتاج إلى تحويلها إلى datetime موضوع.

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

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

في هذا الدليل - سنلقي نظرة على كيفية تحويل تاريخ / وقت السلسلة إلى ملف datetime كائن في Python ، باستخدام المدمج في datetime ، ولكن أيضًا وحدات الطرف الثالث مثل dateutil, arrow ومايا ، تمثل المناطق الزمنية.

تحويل السلاسل باستخدام التاريخ والوقت

التاريخ والوقت تتكون الوحدة النمطية من ثلاثة أنواع مختلفة من الكائنات: date, timeو datetime. date الكائن يحمل التاريخ ، time تمسك بالوقت ، و datetime يحمل التاريخ والوقت!

import datetime
print(f'Current date/time: {datetime.datetime.now()}')

سيؤدي تشغيل هذا الرمز إلى:

Current date/time: 2022-12-01 10:27:03.929149

في حالة عدم تقديم تنسيق مخصص ، يتم استخدام تنسيق السلسلة الافتراضي ، أي أن تنسيق "2022-12-01 10: 27: 03.929149" في إعتماد ISO-8601 شكل (YYYY-MM-DDTHH: MM: SS.mmmmmm). إذا كانت سلسلة الإدخال لدينا لإنشاء ملف datetime الكائن بنفس تنسيق ISO 8601 أو إذا كنت تعرف التنسيق الذي ستتلقاه مقدمًا ، فيمكننا بسهولة تحليله إلى datetime موضوع:

import datetime

date_time_str = '2022-12-01 10:27:03.929149'

date_time_obj = datetime.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S.%f')

print('Date:', date_time_obj.date())
print('Time:', date_time_obj.time())
print('Date-time:', date_time_obj)

سيؤدي تشغيله إلى طباعة التاريخ والوقت والتاريخ - الوقت:

Date: 2022-12-01
Time: 10:27:03.929149
Date-time: 2022-12-01 10:27:03.929149

هنا ، نستخدم strptime() الطريقة التي تقبل وسيطين:

  • التاريخ المنسق بسلسلة
  • شكل الوسيطة الأولى

تحديد تنسيق مثل هذا يجعل التحليل أسرع بكثير منذ ذلك الحين datetime لا يحتاج إلى محاولة تفسير التنسيق من تلقاء نفسه ، وهو أغلى بكثير من الناحية الحسابية. القيمة المعادة من النوع datetime.

في مثالنا ، "2022-12-01 10:27:03.929149" هي سلسلة الإدخال و "%Y-%m-%d %H:%M:%S.%f" هو تنسيق سلسلة التاريخ لدينا. عاد datetime يتم تخزين القيمة على شكل date_time_obj.

لأن هذا هو datetime كائن ، يمكننا استدعاء date() و time() طرق مباشرة عليه. كما ترى من الإخراج ، فإنه يطبع جزء "التاريخ" و "الوقت" من سلسلة الإدخال!

تنسيق الرموز

الأمر يستحق أن نتوقف لحظة لفهمه رموز التنسيق - في "%Y-%m-%d %H:%M:%S.%f" من قبل.

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

  • %Y: سنة (4 أرقام)
  • %m: شهر
  • %d: يوم من الشهر
  • %H: ساعة (24 ساعة)
  • %M: الدقائق
  • %S: ثواني
  • %f: نانو ثانية

ملحوظة: من المتوقع أن تكون جميع هذه الرموز المميزة ، باستثناء العام ، غير مبطن (أي أغسطس هو الشهر الثامن ، وهو غير مبطن حتى 08).

استخدام strptime () تنسيق الرموز المميزة لتحويل سلسلة إلى تنسيق تاريخ ووقت مختلف

إذا كان تنسيق السلسلة معروفًا ، فيمكن تحليله بسهولة إلى ملف datetime الكائن باستخدام strptime(). دعنا نلقي نظرة على مثال غير تافه يترجم من تنسيق إلى آخر:

import datetime

date_time_str = 'Jul 17 2022 9:20AM'
date_time_obj = datetime.datetime.strptime(date_time_str, '%b %d %Y %I:%M%p')

print('Date:', date_time_obj.date())
print('Time:', date_time_obj.time())
print('Date-time:', date_time_obj)

كانت سلسلة الإدخال من تنسيق واحد - "17 يوليو 2022 9:20 ص". بمعرفة هذا التنسيق ، قمنا بتعيين العناصر المكونة إلى تنسيق ISO 8601 وقمنا بتحويله إلى تنسيق datetime موضوع:

Date: 2022-07-17
Time: 09:20:00
Date-time: 2022-07-17 09:20:00

فيما يلي قائمة مختصرة بأوقات تنسيق السلسلة الشائعة والتنسيقات المقابلة لها لـ strptime():

"Jun 28 2018 at 7:40AM" -> "%b %d %Y at %I:%M%p"
"September 18, 2017, 22:19:55" -> "%B %d, %Y, %H:%M:%S"
"Sun,05/12/99,12:30PM" -> "%a,%d/%m/%y,%I:%M%p"
"Mon, 21 March, 2015" -> "%a, %d %B, %Y"
"2018-03-12T10:12:45Z" -> "%Y-%m-%dT%H:%M:%SZ"

يمكنك تحليل سلسلة التاريخ والوقت بأي تنسيق - طالما أنك تستخدم السلسلة الصحيحة من الرموز المميزة للتنسيق للإدخال الذي تتلقاه.

تحويل سلسلة إلى Datetime مع المناطق الزمنية

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

ومع ذلك، فإن datetime كائنات تحتوي على حقل مخصص بالضبط لتخزين البيانات المتعلقة بالمنطقة الزمنية - tzinfo:

import datetime as dt
dtime = dt.datetime.now()

print(dtime) 
print(dtime.tzinfo) 

tzinfo من المفترض أن يكون المجال datetime.timezone كائن ، للدلالة على معلومات المنطقة الزمنية. إنه None بشكل افتراضي ، ويشير إلى أن كائن التاريخ والوقت هو منطقة زمنية ساذجة. مكتبة خارجية شائعة جدًا للتعامل مع المناطق الزمنية هي pytz. يمكنك ضبط بيتز كائنات مثل tzinfo المجال أيضا.

إذا لم يكن لديك بالفعل - قم بتثبيته عبر:

$ pip install pytz

باستخدام PyTz ، يمكننا إنشاء نقطة ارتساء لأوقات معرفة المنطقة الزمنية ، مثل التوقيت العالمي المنسق (UTC):

import datetime as dt
import pytz

dtime = dt.datetime.now(pytz.utc)

print(dtime)
print(dtime.tzinfo)

الإخراج:

2022-12-01 02:07:41.960920+00:00
UTC

لم تعد الساعة 11 صباحًا ، ولكن الساعة 2 صباحًا ، لأننا حددنا المنطقة الزمنية قبل بضع ساعات! هذا يغير المنطقة الزمنية من التاريخ والوقت.

+00:00 هو الفرق بين الوقت المعروض والتوقيت العالمي المنسق (UTC) باعتباره نقطة ارتكاز التنسيق العالمي. لقد حددنا الوقت ليكون بالتوقيت العالمي المنسق ، لذا فإن الإزاحة هي 00:00. هذا هو كائن يدرك المنطقة الزمنية.

وبالمثل ، يمكننا تبديل تفسير نفس التاريخ والوقت بين المناطق الزمنية. دعنا نحول سلسلة ، مثل "2022-06-29 17:08:00" إلى تاريخ ووقت وبعد ذلك تعريب إلى المنطقة الزمنية "America / New_York":

import datetime as dt
import pytz

date_time_str = '2022-06-29 17:08:00'
date_time_obj = dt.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S')

timezone = pytz.timezone('America/New_York')
timezone_date_time_obj = timezone.localize(date_time_obj)

print(timezone_date_time_obj)
print(timezone_date_time_obj.tzinfo)

ملحوظة: التعريب يحول التاريخ والوقت الساذج للمنطقة الزمنية إلى تاريخ ووقت مدركين للمنطقة الزمنية ، ويعامل المنطقة الزمنية على أنها المنطقة الزمنية المحلية. وهكذا ، فإن datetime يبقى كما هو، ولكن نظرًا لاختلاف المنطقة الزمنية ، لم تعد تمثل نفس النقطة الزمنية غير المرتبطة بالمناطق الزمنية.

نحصل على نفس الشيء قيمة التاريخ والوقت، تم التعديل بواسطة -04: 00 مقارنة بوقت UTC:

2022-06-29 17:08:00-04:00
America/New_York

الساعة 17:08 في طوكيو ليس نفس النقطة الزمنية الساعة 17:08 في نيويورك. الساعة 17:08 في طوكيو الساعة 3:08 بتوقيت نيويورك.

كيف تجد كل رموز المنطقة الزمنية / الأسماء المستعارة؟

للعثور على جميع المناطق الزمنية المتاحة ، قم بفحص ملف all_timezones ، وهي قائمة بجميع المناطق الزمنية المتاحة:

print(f'There are {len(pytz.all_timezones)} timezones in PyTzn')
for time_zone in pytz.all_timezones:
   print(time_zone)

تحقق من دليلنا العملي العملي لتعلم Git ، مع أفضل الممارسات ، والمعايير المقبولة في الصناعة ، وورقة الغش المضمنة. توقف عن أوامر Googling Git وفي الواقع تعلم ذلك!

There are 594 timezones in PyTz

Africa/Abidjan
Africa/Accra
Africa/Addis_Ababa
Africa/Algiers
Africa/Asmara
Africa/Asmera
...

تغيير المنطقة الزمنية للتاريخ والوقت

يمكننا تحويل المنطقة الزمنية للمنطقة الزمنية datetime من منطقة إلى أخرى ، بدلاً من تحديد موقع وقت وتاريخ ساذج من منطقة زمنية من خلال عدسة بعض المنطقة الزمنية.

هذا يختلف عن التوطين ، حيث يمثل التوطين نقطة زمنية مختلفة ، لكن تحويل المنطقة الزمنية لكائن ما يمثل نفس النقطة الزمنية ، من خلال عدسة مختلفة:

import datetime as dt
import pytz

timezone_nw = pytz.timezone('America/New_York')
nw_datetime_obj = dt.datetime.now(timezone_nw)

timezone_london = pytz.timezone('Europe/London')
london_datetime_obj = nw_datetime_obj.astimezone(timezone_london)


print('America/New_York:', nw_datetime_obj)
print('Europe/London:', london_datetime_obj)

أولاً ، أنشأنا كائنًا واحدًا للوقت والوقت باستخدام الوقت الحالي وقمنا بتعيينه على أنه المنطقة الزمنية "America / New_York". ثم استخدم ملف astimezone() الطريقة ، لقد قمنا بتحويل هذا datetime إلى المنطقة الزمنية "أوروبا / لندن". كلاهما datetimeستطبع s قيمًا مختلفة ، باستخدام تعويض UTC كحلقة وصل مرجعية بينهما:

America/New_York: 2022-11-30 21:24:30.123400-05:00
Europe/London: 2022-12-01 02:24:30.123400+00:00

2:24 في اليوم التالي في لندن is نفس النقطة الزمنية كما في الساعة 21:24 في اليوم السابق في نيويورك لأن لندن تتقدم بخمس ساعات.

كما هو متوقع ، تختلف أوقات التاريخ حيث تفصل بينهما حوالي 5 ساعات.

تحويل سلسلة إلى Datetime باستخدام مكتبات الطرف الثالث

بيثون datetime يمكن للوحدة النمطية تحويل جميع أنواع السلاسل المختلفة إلى ملف datetime هدف. لكن المشكلة الرئيسية هي أنه من أجل القيام بذلك ، تحتاج إلى إنشاء سلسلة كود التنسيق المناسبة strptime() يمكن أن يفهم. يستغرق إنشاء هذه السلسلة وقتًا ويجعل قراءة الكود أكثر صعوبة.

بدلاً من ذلك ، يمكننا استخدام مكتبات الطرف الثالث الأخرى لتسهيل الأمر.

في بعض الحالات ، تتمتع مكتبات الجهات الخارجية هذه أيضًا بدعم مدمج أفضل لمعالجة ومقارنة أوقات التاريخ ، وبعضها يحتوي على مناطق زمنية مدمجة ، لذلك لا تحتاج إلى تضمين حزمة PyTz إضافية.

دعنا نلقي نظرة على بعض هذه المكتبات في الأقسام التالية.

تحويل String إلى Datetime باستخدام dateutil

وحدة داتوتيل هو امتداد ل datetime وحدة. ميزة واحدة هي أننا لسنا بحاجة إلى تمرير أي كود تحليل لتحليل سلسلة!

لتحويل سلسلة تلقائيًا إلى تاريخ ووقت بدون رمز تنسيق باستخدام Python dateutil:

from dateutil.parser import parse
datetime = parse('2018-06-29 22:21:41')

print(datetime)

هذه parse ستعمل الوظيفة على تحليل السلسلة تلقائيًا! ليس عليك تضمين أي سلسلة تنسيق. دعنا نحاول تحليل أنواع مختلفة من السلاسل باستخدام dateutil:

from dateutil.parser import parse

date_array = [
    '2018-06-29 08:15:27.243860',
    'Jun 28 2018 7:40AM',
    'Jun 28 2018 at 7:40AM',
    'September 18, 2017, 22:19:55',
    'Sun, 05/12/1999, 12:30PM',
    'Mon, 21 March, 2015',
    '2018-03-12T10:12:45Z',
    '2018-06-29 17:08:00.586525+00:00',
    '2018-06-29 17:08:00.586525+05:00',
    'Tuesday , 6th September, 2017 at 4:30pm'
]

for date in date_array:
    print('Parsing: ' + date)
    dt = parse(date)
    print(dt.date())
    print(dt.time())
    print(dt.tzinfo)
    print('n')

الإخراج:

Parsing: 2018-06-29 08:15:27.243860
2018-06-29
08:15:27.243860
None

Parsing: Jun 28 2018 7:40AM
2018-06-28
07:40:00
None

Parsing: Jun 28 2018 at 7:40AM
2018-06-28
07:40:00
None

Parsing: September 18, 2017, 22:19:55
2017-09-18
22:19:55
None

Parsing: Sun, 05/12/1999, 12:30PM
1999-05-12
12:30:00
None

Parsing: Mon, 21 March, 2015
2015-03-21
00:00:00
None

Parsing: 2018-03-12T10:12:45Z
2018-03-12
10:12:45
tzutc()

Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29
17:08:00.586525
tzutc()

Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29
17:08:00.586525
tzoffset(None, 18000)

Parsing: Tuesday , 6th September, 2017 at 4:30pm
2017-09-06
16:30:00
None

يمكنك أن ترى أنه يمكن تحليل أي نوع من الخيوط تقريبًا بسهولة باستخدام امتداد dateutil وحدة.

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

تحويل String إلى Datetime باستخدام Maya

مايا كما أنه يجعل من السهل جدًا تحليل سلسلة وتغيير المناطق الزمنية. لتحويل سلسلة بسهولة باستخدام Python Maya:

import maya

dt = maya.parse('2018-04-29T17:45:25Z').datetime()
print(dt.date())
print(dt.time())
print(dt.tzinfo)

الإخراج:

2018-04-29
17:45:25
UTC

لتحويل الوقت إلى منطقة زمنية مختلفة:

import maya

dt = maya.parse('2018-04-29T17:45:25Z').datetime(to_timezone='America/New_York', naive=False)
print(dt.date())
print(dt.time())
print(dt.tzinfo)

الإخراج:

2018-04-29
13:45:25
America/New_York

الآن أليس هذا سهل الاستخدام؟ دعنا نجرب maya بنفس مجموعة السلاسل التي استخدمناها مع dateutil:

import maya

date_array = [
    '2018-06-29 08:15:27.243860',
    'Jun 28 2018 7:40AM',
    'Jun 28 2018 at 7:40AM',
    'September 18, 2017, 22:19:55',
    'Sun, 05/12/1999, 12:30PM',
    'Mon, 21 March, 2015',
    '2018-03-12T10:12:45Z',
    '2018-06-29 17:08:00.586525+00:00',
    '2018-06-29 17:08:00.586525+05:00',
    'Tuesday , 6th September, 2017 at 4:30pm'
]

for date in date_array:
    print('Parsing: ' + date)
    dt = maya.parse(date).datetime()
    print(dt)
    
    
    
    

الإخراج:

Parsing: 2018-06-29 08:15:27.243860
2018-06-29 08:15:27.243860+00:00

Parsing: Jun 28 2018 7:40AM
2018-06-28 07:40:00+00:00

Parsing: Jun 28 2018 at 7:40AM
2018-06-28 07:40:00+00:00

Parsing: September 18, 2017, 22:19:55
2017-09-18 22:19:55+00:00

Parsing: Sun, 05/12/1999, 12:30PM
1999-05-12 12:30:00+00:00

Parsing: Mon, 21 March, 2015
2015-03-21 00:00:00+00:00

Parsing: 2018-03-12T10:12:45Z
2018-03-12 10:12:45+00:00

Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29 17:08:00.586525+00:00

Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29 12:08:00.586525+00:00

Parsing: Tuesday , 6th September, 2017 at 4:30pm
2017-09-06 16:30:00+00:00

كما ترى ، تم تحليل جميع تنسيقات التاريخ بنجاح!

إذا لم نقدم معلومات المنطقة الزمنية ، فسيحولها تلقائيًا إلى التوقيت العالمي المنسق (UTC). لذا ، من المهم أن نلاحظ أننا يجب توفير to_timezone و naive المعلمات إذا لم يكن الوقت بالتوقيت العالمي المنسق (UTC).

تحويل سلسلة إلى Datetime مع Arrow

سهم هي مكتبة أخرى للتعامل مع التاريخ والوقت في بايثون. ومثل مع maya، فإنه يحدد أيضًا تنسيق التاريخ والوقت تلقائيًا. بمجرد تفسيره ، فإنه يعيد Python datetime الكائن من arrow موضوع.

لتحويل سلسلة بسهولة إلى datetime باستخدام Python arrow:

import arrow

dt = arrow.get('2018-04-29T17:45:25Z')
print(dt.date())
print(dt.time())
print(dt.tzinfo)

الإخراج:

2018-04-29
17:45:25
tzutc()

وهنا كيف يمكنك استخدام arrow لتحويل المناطق الزمنية باستخدام to() الأسلوب:

import arrow

dt = arrow.get('2018-04-29T17:45:25Z').to('America/New_York')
print(dt)
print(dt.date())
print(dt.time())

الإخراج:

2018-04-29T13:45:25-04:00
2018-04-29
13:45:25

كما ترى ، يتم تحويل سلسلة التاريخ والوقت إلى منطقة "America / New_York".

الآن ، دعنا نستخدم نفس مجموعة السلاسل التي استخدمناها أعلاه:

import arrow

date_array = [
    '2018-06-29 08:15:27.243860',
    
    
    
    
    
    '2018-03-12T10:12:45Z',
    '2018-06-29 17:08:00.586525+00:00',
    '2018-06-29 17:08:00.586525+05:00',
    
]

for date in date_array:
    dt = arrow.get(date)
    print('Parsing: ' + date)
    print(dt)
    
    
    
    

ستفشل هذه الشفرة في سلاسل التاريخ والوقت التي تم التعليق عليها ، والتي تعد أكثر من نصف أمثلةنا. سيكون إخراج السلاسل الأخرى كما يلي:

Parsing: 2018-06-29 08:15:27.243860
2018-06-29T08:15:27.243860+00:00

Parsing: 2018-03-12T10:12:45Z
2018-03-12T10:12:45+00:00

Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29T17:08:00.586525+00:00

Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29T17:08:00.586525+05:00

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

وفي الختام

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

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

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

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

الطابع الزمني:

اكثر من ستاكابوز