המרת מחרוזות לתאריך-שעה ב-Python

מבוא

נתונים יכולים להיות מיוצגים בצורות שונות - ודרך נוחה לייצג תאריכים ושעות מחרוזות. עם זאת, כדי לעבוד עם התאריכים והשעות הללו בצורה אריתמטית (כגון חישוב הפרשי זמן, הוספה או הסרה של זמן וכו') - עלינו להמיר אותם ל- datetime אובייקט.

אחד המקורות הנפוצים ביותר של תאריכים בפורמט מחרוזת הם REST APIs שמחזירים מחרוזות אגנוסטיות, שאותן נוכל להמיר לפורמטים אחרים.

בנוסף - אזורי זמן הם כאב ראש נפוץ כשמדובר בעבודה עם אובייקטים של תאריך תאריך, אז נצטרך לחשוב על זה גם בזמן ההמרה.

במדריך זה – נסקור כיצד להמיר תאריך/שעה מחרוזת ל-a datetime אובייקט ב-Python, באמצעות המובנה datetime מודול, אלא גם מודולים של צד שלישי כגון dateutil, arrow ומאיה, אחראית על אזורי זמן.

המרת מחרוזות באמצעות תאריך ושעה

אל האני datetime מודול מורכב משלושה סוגי אובייקטים שונים: 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: מיקרו שניות

הערה: כל האסימונים הללו, למעט השנה, צפויים להיות מרופדים באפס (כלומר, אוגוסט הוא החודש ה-8, והוא מרופד אפס עד 08).

שימוש ב-strptime() Format Tokens כדי להמיר מחרוזת לפורמט DateTime שונה

אם הפורמט של מחרוזת ידוע, ניתן לנתח אותה בקלות ל-a 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 AM". הכרנו את הפורמט הזה, מיפינו את הרכיבים המרכיבים לפורמט 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 אובייקטים מכילים שדה בדיוק לאחסון נתונים הקשורים לאזור זמן - tzinfo:

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

print(dtime) 
print(dtime.tzinfo) 

אל האני tzinfo שדה נועד להיות א datetime.timezone אובייקט, המציין את מידע אזור הזמן. שֶׁלָה None כברירת מחדל, ומציין שאובייקט ה-datetime הוא נאיבי באזור הזמן. ספרייה חיצונית נפוצה מאוד לטיפול באזורי זמן היא pytz. אתה יכול להגדיר 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, אלא XNUMX:XNUMX, כי קבענו את אזור הזמן כמה שעות אחורה! זֶה משנה את אזור הזמן של התאריך ושעה.

+00:00 הוא ההבדל בין הזמן המוצג לזמן UTC כעוגן התיאום הגלובלי. קבענו את הזמן להיות ב-UTC, אז הקיזוז הוא 00:00. זה אובייקט מודע לאזור זמן.

באופן דומה, אנו יכולים לשנות את הפרשנות של אותו תאריך ושעה בין אזורי זמן. בואו נמיר מחרוזת, כגון "2022-06-29 17:08:00" לתאריך ושעה ולאחר מכן לְמַקֵם זה לאזור הזמן "אמריקה/ניו_יורק":

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)

הערה: לוקליזציה הופך תאריך תאריך נאיבי לאזור זמן לתאריך שעון מודע לאזור זמן, ומתייחס לאזור הזמן כאל המקומי. לפיכך, ה תאריך השעה נשאר זהה, אך בהינתן אזור הזמן השונה, הוא כבר לא מייצג את אותה נקודת זמן שאינה קשורה מאזורי זמן.

אנחנו מקבלים אותו דבר ערך תאריך ושעה, מקוזז על ידי -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, עם שיטות עבודה מומלצות, סטנדרטים מקובלים בתעשייה ודף רמאות כלול. תפסיק לגוגל פקודות Git ולמעשה ללמוד זה!

There are 594 timezones in PyTz

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

שנה את אזור הזמן של Datetime

אנו יכולים להמיר אזור זמן של מודע לאזור זמן 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)

ראשית, יצרנו אובייקט תאריך-שעה אחד עם השעה הנוכחית והגדרנו אותו כאזור הזמן "אמריקה/ניו_יורק". לאחר מכן באמצעות astimezone() השיטה, המרנו את זה datetime לאזור הזמן "אירופה/לונדון". שניהם datetimes ידפיס ערכים שונים, תוך שימוש ב-UTC offset כקישור ייחוס ביניהם:

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 שעות.

כצפוי, מועדי התאריכים שונים מכיוון שהם מפרידים בערך 5 שעות.

המרת מחרוזת לתאריך תאריך באמצעות ספריות צד שלישי

פיתון datetime מודול יכול להמיר את כל הסוגים השונים של מחרוזות ל-a datetime לְהִתְנַגֵד. אבל הבעיה העיקרית היא שכדי לעשות זאת אתה צריך ליצור את מחרוזת קוד העיצוב המתאימה strptime() יכול להבין. יצירת מחרוזת זו לוקחת זמן והיא הופכת את הקוד לקשה יותר לקריאה.

במקום זאת, נוכל להשתמש בספריות אחרות של צד שלישי כדי להקל.

בחלק מהמקרים לספריות צד שלישי אלו יש גם תמיכה מובנית טובה יותר למניפולציה והשוואה של תאריכים ושעות, ולחלקן אפילו אזורי זמן מובנים, כך שאינך צריך לכלול חבילת PyTz נוספת.

בואו נסתכל על כמה מהספריות הללו בסעיפים הבאים.

המר מחרוזת ל-Datetime עם dateutil

אל האני מודול dateutil הוא הרחבה ל- datetime מודול. יתרון אחד הוא שאנחנו לא צריכים להעביר שום קוד ניתוח כדי לנתח מחרוזת!

להמיר מחרוזת אוטומטית לתאריך תאריך ללא אסימון פורמט באמצעות Python's 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 מודול.

למרות שזה נוח, זכור מקודם שצורך לחזות את הפורמט הופך את הקוד לאיטי בהרבה, כך שאם אתה קוד דורש ביצועים גבוהים, ייתכן שזו לא הגישה הנכונה עבור היישום שלך.

המר מחרוזת ל-Datetime עם Maya

מאיה גם מקל מאוד לנתח מחרוזת ולשנות אזורי זמן. כדי להמיר מחרוזת בקלות עם Maya של Python:

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.

המר מחרוזת לתאריך תאריך עם החץ

חץ היא ספרייה נוספת להתמודדות עם תאריך ושעה ב-Python. וכמו קודם עם maya, הוא גם מגלה את פורמט התאריך והשעה באופן אוטומטי. לאחר הפירוש, הוא מחזיר פייתון datetime חפץ מה arrow אובייקט.

להמיר בקלות מחרוזת לתאריך תאריך באמצעות Python's 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

כפי שאתה יכול לראות, מחרוזת התאריך-שעה מומרת לאזור "אמריקה/ניו_יורק".

כעת, בואו נשתמש שוב באותה קבוצת מחרוזות שהשתמשנו בהן לעיל:

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

על מנת לנתח נכון את מחרוזות התאריך-שעה המופיעות בהערות, תצטרך להעביר את המחרוזות המתאימות פורמט אסימונים לתת לספרייה רמזים כיצד לנתח אותה.

סיכום

במאמר זה הראינו דרכים שונות לנתח מחרוזת ל-a datetime אובייקט ב- Python. אתה יכול לבחור ברירת המחדל של Python datetime הספרייה או כל אחת מספריות הצד השלישי המוזכרות במאמר זה, בין רבים אחרים.

הבעיה העיקרית עם ברירת המחדל datetime החבילה היא שעלינו לציין את קוד הניתוח באופן ידני עבור כמעט כל הפורמטים של מחרוזת תאריך-שעה. לכן, אם פורמט המחרוזת שלך ישתנה בעתיד, סביר להניח שתצטרך לשנות גם את הקוד שלך. אבל ספריות רבות של צד שלישי, כמו אלו שהוזכרו כאן, מטפלות בזה באופן אוטומטי.

בעיה נוספת שעומדת בפנינו היא התמודדות עם אזורי זמן. הדרך הטובה ביותר לטפל בהם היא תמיד לאחסן את השעה במסד הנתונים שלך כפורמט UTC ולאחר מכן להמיר אותו לאזור הזמן המקומי של המשתמש בעת הצורך.

ספריות אלה לא רק טובות לניתוח מחרוזות, אלא הן יכולות לשמש להרבה סוגים שונים של פעולות הקשורות לתאריך-שעה. אני ממליץ לך לעבור על המסמכים כדי ללמוד את הפונקציונליות בפירוט.

בול זמן:

עוד מ Stackabuse