ما هي أفضل طريقة للعثور على عكس datetime.isocalendar ()؟

StackOverflow https://stackoverflow.com/questions/304256

  •  08-07-2019
  •  | 
  •  

سؤال

datetime.isocalendar() الأسلوب بإرجاع (ISO_year, ISO_week_number, ISO_weekday) الصفوف (tuple) لكائن datetime معين. هل هناك وظيفة عكسية المقابلة؟ إذا لم يكن كذلك، هناك طريقة سهلة لحساب تاريخ معين في السنة، رقم الأسبوع ويوم من أيام الأسبوع؟

هل كانت مفيدة؟

المحلول

وكان لي مؤخرا لحل هذه المشكلة بنفسي، وجاء مع هذا الحل:

import datetime

def iso_year_start(iso_year):
    "The gregorian calendar date of the first day of the given ISO year"
    fourth_jan = datetime.date(iso_year, 1, 4)
    delta = datetime.timedelta(fourth_jan.isoweekday()-1)
    return fourth_jan - delta 

def iso_to_gregorian(iso_year, iso_week, iso_day):
    "Gregorian calendar date for the given ISO year, week and day"
    year_start = iso_year_start(iso_year)
    return year_start + datetime.timedelta(days=iso_day-1, weeks=iso_week-1)

وهناك عدد قليل من حالات الاختبار:

>>> iso = datetime.date(2005, 1, 1).isocalendar()
>>> iso
(2004, 53, 6)
>>> iso_to_gregorian(*iso)
datetime.date(2005, 1, 1)

>>> iso = datetime.date(2010, 1, 4).isocalendar()    
>>> iso
(2010, 1, 1)
>>> iso_to_gregorian(*iso)
datetime.date(2010, 1, 4)

>>> iso = datetime.date(2010, 1, 3).isocalendar()
>>> iso
(2009, 53, 7)
>>> iso_to_gregorian(*iso)
datetime.date(2010, 1, 3)

نصائح أخرى

import datetime

def iso_to_gregorian(iso_year, iso_week, iso_day):
    "Gregorian calendar date for the given ISO year, week and day"
    fourth_jan = datetime.date(iso_year, 1, 4)
    _, fourth_jan_week, fourth_jan_day = fourth_jan.isocalendar()
    return fourth_jan + datetime.timedelta(days=iso_day-fourth_jan_day, weeks=iso_week-fourth_jan_week)

وكان تكييف هذا من @ الجواب BenJames الجيدة جدا. لم يكن لديك لمعرفة اليوم الأول من السنة. عليك أن تعرف مثالا على التاريخ الذي هو بالتأكيد في نفس العام ISO، وتقويم أسبوع ISO ويوم من ذلك التاريخ.

وو4 يناير هو مجرد مثال واحد، لأنه، كما أشار بن بها، و4 يناير ينتمي دائما إلى نفس العام ISO وسنة ميلادية، وهو اليوم الأول من السنة للقيام بذلك.

ومنذ أسابيع كلها بنفس الطول، يمكنك ببساطة طرح الأيام والأسابيع بين ISO من التاريخ الذي تريد، وISO من التاريخ الذي تعرف في كل من الأشكال، وإضافة على هذا العدد من الأيام والأسابيع . (لا يهم ما إذا كانت هذه الأرقام الإيجابية أو السلبية، لذلك يمكن اختيار بعض الآخرين اليوم المحدد "مثل 28 ديسمبر).

تحرير

وأنا تصحيح هذا لأنه، كما أشير من قبل مفيدJoSo، في اليوم الأول من السنة الميلادية التي تنتمي أيضا إلى السنة ISO هو 4 يناير ليس 5 يناير. كما يقول التفسير، فإنه لا يهم أي تاريخ يتم اختيار كنقطة مرجعية، ولكن اختيار 4 يناير يجعل هذا الخيار أقل "السحر".

واعتبارا من بيثون 3.6، يمكنك استخدام %G، %u و%V توجيهات جديدة. انظر القضية 12006 و في تحديث الوثائق :

<اقتباس فقرة>   

و%G
  ISO 8601 عام مع القرن تمثيل السنة الذي يحتوي على الجزء الأكبر من الأسبوع ISO (%V).

     

و%u
  ISO 8601 يوم من أيام الأسبوع كرقم عشري حيث 1 هو يوم الاثنين.

     

و%V
  ISO 8601 الأسبوع كرقم عشري مع الاثنين مع أول يوم من أيام الأسبوع. الأسبوع 01 والأسبوع تحتوي على 4 يناير.

وبالنظر إلى سلسلة مع السنة، weeknumber وعدد أيام الأسبوع، فمن السهل تحليل أولئك الذين يسعون لموعد مع:

from datetime import datetime

datetime.strptime('2002 01 1', '%G %V %u').date()

وأو بوصفها وظيفة مع مدخلات صحيح:

from datetime import datetime

def date_from_isoweek(iso_year, iso_weeknumber, iso_weekday):
    return datetime.strptime(
        '{:04d} {:02d} {:d}'.format(iso_year, iso_weeknumber, iso_weekday),
        '%G %V %u').date()

والبدء في بيثون 3.6، سوف datetime.strptime() دعم %G، %V و%u توجيهات، حتى تتمكن من القيام ببساطة datetime.strptime('2015 1 2', '%G %V %u').date(). انظر: https://hg.python.org/cpython/rev/acdebfbfbdcf

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

def iso_to_gregorian(iso_year, iso_week, iso_day):
    jan4 = datetime.date(iso_year, 1, 4)
    start = jan4 - datetime.timedelta(days=jan4.isoweekday()-1)
    return start + datetime.timedelta(weeks=iso_week-1, days=iso_day-1)

لاحظ أن٪ W هو الاسبوع # (0-53) وهو NOT THE SAME كما الأسبوع ISO (1-53). سوف تكون هناك حالات حافة حيث سيتم٪ W لا تعمل.

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

import datetime
def getDateFromWeek(year,week,day):
    """Method to retrieve the date from the specified week, year and weekday"""

    year_start = datetime.date(year,1,1)
    ys_weekday =  year_start.weekday()
    delta = (week*7)+(day-ys_weekday)
    if ys_weekday<4:
        delta -= 7

    return  year_start  + datetime.timedelta(days=delta)

وأنا اختبرت بها مع القيم الحدية مثل الأسبوع الأخير من عام 2020، والأسبوع الأول من 2021، وعملت بشكل جيد جدا.

تحرير: تجاهل ذلك، فإن الحالات حافة هي الألم. الذهاب مع الحل بن ل.

وطيب، على توثيق التفتيش لاحظت أن strptime يحتوي على معلمات %W و%w، وبالتالي فإن الأعمال التالية:

def fromisocalendar(y,w,d):
   return datetime.strptime( "%04dW%02d-%d"%(y,w-1,d), "%YW%W-%w")

وزوجان من gotchas: يبدأ رقم الأسبوع ISO في 1، في حين يبدأ %W في 0. يبدأ الأسبوع يوم ISO في 1 (الاثنين)، والذي هو نفس %w، حتى الأحد من المحتمل أن يكون 0، وليس 7 ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top