वर्षों में पायथन टाइमडेल्टा


140

मुझे यह जाँचने की आवश्यकता है कि कुछ संख्या कुछ वर्षों से है। वर्तमान में मुझे मॉड्यूल timedeltaसे मिला है datetimeऔर मुझे नहीं पता कि इसे वर्षों में कैसे बदलना है।


4
इस उत्तर को देखें: stackoverflow.com/a/9754466/65387
एडम

जवाबों:


156

आपको timedeltaयह बताने की ज़रूरत है कि कितने साल बीत चुके हैं; आपको शुरुआत (या समाप्ति) की तारीख जानने की भी आवश्यकता है। (यह एक लीप ईयर की बात है।)

आपका सबसे अच्छा शर्त dateutil.relativedelta ऑब्जेक्ट का उपयोग करना है , लेकिन यह एक 3 पार्टी मॉड्यूल है। यदि आप जानना चाहते हैं datetimeकि nकुछ तारीख से साल था (अभी सही समय पर), तो आप निम्न कार्य कर सकते हैं ::

from dateutil.relativedelta import relativedelta

def yearsago(years, from_date=None):
    if from_date is None:
        from_date = datetime.now()
    return from_date - relativedelta(years=years)

यदि आप मानक पुस्तकालय के साथ रहना चाहते हैं, तो उत्तर थोड़ा और जटिल है ::

from datetime import datetime
def yearsago(years, from_date=None):
    if from_date is None:
        from_date = datetime.now()
    try:
        return from_date.replace(year=from_date.year - years)
    except ValueError:
        # Must be 2/29!
        assert from_date.month == 2 and from_date.day == 29 # can be removed
        return from_date.replace(month=2, day=28,
                                 year=from_date.year-years)

यदि यह 2/29 है, और 18 साल पहले 2/29 नहीं था, तो यह फ़ंक्शन 2/28 पर वापस आ जाएगा। यदि आप 3/1 पर लौटते हैं, तो returnपढ़ने के लिए केवल अंतिम विवरण बदलें ::

    return from_date.replace(month=3, day=1,
                             year=from_date.year-years)

आपका प्रश्न मूल रूप से कहा गया था कि आप जानना चाहते हैं कि कुछ तारीख से कितने साल हो गए हैं। मान लें कि आप वर्षों की एक पूर्णांक संख्या चाहते हैं, तो आप प्रति वर्ष 365.25 दिनों के आधार पर अनुमान लगा सकते हैं और फिर yearsagoऊपर बताए गए कार्यों में से किसी एक का उपयोग करके जांच कर सकते हैं ::

def num_years(begin, end=None):
    if end is None:
        end = datetime.now()
    num_years = int((end - begin).days / 365.25)
    if begin > yearsago(num_years, end):
        return num_years - 1
    else:
        return num_years

26
आप 365.2425 (365.25 के बजाय) के साथ पूरी तरह से सटीक हो सकते हैं, जो ग्रेगोरियन कैलेंडर के लिए 400 साल के अपवाद को ध्यान में रखता है।
21

3
आपका कार्य यूके और हांगकांग जैसे देशों के लिए कानूनी रूप से टूट जाता है, क्योंकि वे लीप वर्षों के लिए 1 मार्च को "गोल" करते हैं।
एंटीहेरो


3
यह भी देखना यह और इस दोनों उस समय के बारे में सच नहीं कर रहे हैं चीजों की उत्कृष्ट सूची नहीं है।
gvoysey

49

यदि आप यह जांचने की कोशिश कर रहे हैं कि कोई व्यक्ति 18 वर्ष का है, तो timedeltaलीप वर्ष के कारण कुछ किनारे के मामलों पर सही ढंग से काम नहीं करेगा। उदाहरण के लिए, 1 जनवरी 2000 को जन्म लेने वाला कोई व्यक्ति 18 जनवरी 6575 दिन बाद 1 जनवरी 2018 (5 लीप ईयर शामिल) हो जाएगा, लेकिन 1 जनवरी 2001 को जन्म लेने वाला कोई व्यक्ति 18 जनवरी को 6574 दिन बाद 1 जनवरी 2001 को जन्म लेगा। 2019 (4 लीप वर्ष शामिल)। इस प्रकार, यदि आप किसी व्यक्ति की उम्र 6574 दिन है, तो आप यह निर्धारित नहीं कर सकते हैं कि क्या वे अपनी जन्मतिथि के बारे में कुछ अधिक जानकारी के बिना 17 या 18 वर्ष के हैं।

ऐसा करने का सही तरीका यह है कि तारीखों से सीधे उम्र की गणना करें, दो साल घटाकर, और फिर एक घटाकर अगर वर्तमान महीना / दिन जन्म के महीने / दिन से पहले हो।


9

सबसे पहले, सबसे विस्तृत स्तर पर, समस्या को बिल्कुल हल नहीं किया जा सकता है। वर्ष लंबाई में भिन्न होते हैं, और वर्ष की लंबाई के लिए एक स्पष्ट "सही विकल्प" नहीं है।

उस ने कहा, जो कुछ भी इकाइयों में "प्राकृतिक" (शायद सेकंड) में अंतर प्राप्त करें और उस और वर्षों के बीच के अनुपात से विभाजित करें। उदाहरण के लिए

delta_in_days / (365.25)
delta_in_seconds / (365.25*24*60*60)

...जो कुछ भी। महीनों से दूर रहें, क्योंकि वे वर्षों से कम अच्छी तरह से परिभाषित हैं।


2
यह नहीं है कि किसी का क्या मतलब है या इसका उपयोग करता है जब यह सवाल है कि कितने साल की सेवा है या किसी व्यक्ति ने एक विशेष आयु प्राप्त की है।
जॉन मैकिन 11

3
ग्रेगोरियन कैलेंडर के 400 वर्ष के अपवाद को ध्यान में रखते हुए आपका 365.25 365.2425 होना चाहिए।
21

1
ठीक है, समस्या को सही ढंग से हल किया जा सकता है - आप समय से पहले बता सकते हैं कि कौन से वर्ष में लीप दिन और छलांग सेकंड हैं और वह सब। यह सिर्फ इतना है कि वर्षों को घटाए बिना इसे करने का कोई बहुत ही सुंदर तरीका नहीं है, फिर महीने, फिर दिन, आदि ... दो स्वरूपित तारीखों में
लेरेम

7

यहां एक अद्यतन DOB फ़ंक्शन है, जो उसी तरह से जन्मदिन की गणना करता है जैसे मनुष्य करते हैं:

import datetime
import locale


# Source: https://en.wikipedia.org/wiki/February_29
PRE = [
    'US',
    'TW',
]
POST = [
    'GB',
    'HK',
]


def get_country():
    code, _ = locale.getlocale()
    try:
        return code.split('_')[1]
    except IndexError:
        raise Exception('Country cannot be ascertained from locale.')


def get_leap_birthday(year):
    country = get_country()
    if country in PRE:
        return datetime.date(year, 2, 28)
    elif country in POST:
        return datetime.date(year, 3, 1)
    else:
        raise Exception('It is unknown whether your country treats leap year '
                      + 'birthdays as being on the 28th of February or '
                      + 'the 1st of March. Please consult your country\'s '
                      + 'legal code for in order to ascertain an answer.')
def age(dob):
    today = datetime.date.today()
    years = today.year - dob.year

    try:
        birthday = datetime.date(today.year, dob.month, dob.day)
    except ValueError as e:
        if dob.month == 2 and dob.day == 29:
            birthday = get_leap_birthday(today.year)
        else:
            raise e

    if today < birthday:
        years -= 1
    return years

print(age(datetime.date(1988, 2, 29)))

यह तब टूटता है जब dob 29 फरवरी होता है और वर्तमान वर्ष लीप वर्ष नहीं होता है।
ट्रे हुनर

4

दिनों की संख्या प्राप्त करें, फिर वर्षों के लिए 365.2425 (मतलब ग्रेगोरियन वर्ष) से ​​विभाजित करें। महीनों के लिए 30.436875 (मतलब ग्रेगोरियन महीने) से विभाजित करें।


2
def age(dob):
    import datetime
    today = datetime.date.today()

    if today.month < dob.month or \
      (today.month == dob.month and today.day < dob.day):
        return today.year - dob.year - 1
    else:
        return today.year - dob.year

>>> import datetime
>>> datetime.date.today()
datetime.date(2009, 12, 1)
>>> age(datetime.date(2008, 11, 30))
1
>>> age(datetime.date(2008, 12, 1))
1
>>> age(datetime.date(2008, 12, 2))
0

29 फरवरी को जन्म लेने वाले व्यक्ति को आगामी 28 फरवरी को 1 वर्ष की आयु के रूप में माना जाएगा।
जॉन मैकिन 12

ठीक। 29 वें दिन पैदा होने वाली 0.08% आबादी को "आज के बाद जन्मदिन है" से "आज जन्मदिन से पहले जन्मदिन है" को समायोजित करने के लिए सही है। क्या इससे हल होता है?
जॉन मी डिक

यह आपके उदाहरण के लिए सही ढंग से काम करता है !? अगर मैंने "आज" को 28 फरवरी 2009 को, और जन्म तिथि 29 फरवरी 2008 को सेट किया, तो यह शून्य-कम से कम मेरे लिए लौटता है; 1 नहीं जैसा कि आप सुझाव देते हैं (अजगर 2.5.2)। श्री मचिन को असभ्य करने की कोई आवश्यकता नहीं है। वास्तव में आप किन दो तारीखों से परेशान हैं?
जॉन मी

मैं फिर से कोशिश करूँगा: 29 फरवरी को जन्म लेने वाले व्यक्ति को अधिकांश लोगों द्वारा अधिकांश कानूनी उद्देश्यों के लिए इलाज किया जाएगा क्योंकि निम्नलिखित 28 फरवरी को 1 वर्ष की आयु प्राप्त होगी। आपका कोड आपके "सुधार" से पहले और बाद में 0 का उत्पादन करता है। वास्तव में, आपके कोड के दो संस्करण सभी 9 इनपुट संभावनाओं (महीने <==> X दिन <==>) के लिए समान रूप से एक ही आउटपुट का उत्पादन करते हैं। BTW, 100.0 / (4 * 365 + 1) 0.068 का उत्पादन करता है, न कि 0.08 का।
जॉन मैकिन

2
आह। (0) 29 फरवरी के मुद्दों को संबोधित करना किसी भी तारीख अंकगणित में आवश्यक है; आपने इसे अनदेखा कर दिया। (१) आपका कोड पहली बार बेहतर नहीं था; क्या आप समझ नहीं "उत्पादन में एक ही उत्पादन"? (2) तीन संभावित परमाणु परिणाम (<, ==,>) की तुलना आज के। महीने और dob.month; आज और दिन की तुलना करने वाले तीन संभावित परमाणु परिणाम; 3 * 3 == 9 (3) stackoverflow.com/questions/2217488/…
जॉन मैकिन

1

कितना सटीक होना चाहिए? td.days / 365.25यदि आप लीप वर्षों के बारे में चिंतित हैं, तो आप बहुत करीब हो जाएंगे।


मैं वास्तव में लीप वर्षों के बारे में चिंतित हूं। यह जांचना चाहिए कि व्यक्ति 18 वर्ष से अधिक उम्र का है या नहीं।
मिगोल

फिर कोई आसान एक-लाइनर नहीं है, आपको दो तारीखों को पार्स करना होगा और यह पता लगाना होगा कि व्यक्ति ने अपना 18 वां जन्मदिन पारित किया है या नहीं।
०१:१३ पर एडफी

1

फिर भी यहां उल्लेखित एक और तीसरे पक्ष के लिबास में mxDateTime (अजगर datetimeऔर तीसरे पक्ष दोनों का पूर्ववर्ती) नहीं हैtimeutil ) का उपयोग इस कार्य के लिए नहीं किया जा सकता है।

उपर्युक्त yearsagoहोगा:

from mx.DateTime import now, RelativeDateTime

def years_ago(years, from_date=None):
    if from_date == None:
        from_date = now()
    return from_date-RelativeDateTime(years=years)

पहला पैरामीटर एक होने की उम्मीद है DateTime उदाहरण ।

साधारण datetimeको DateTimeआप में परिवर्तित करने के लिए 1 सेकंड की सटीकता के लिए इसका इस्तेमाल किया जा सकता है):

def DT_from_dt_s(t):
    return DT.DateTimeFromTicks(time.mktime(t.timetuple()))

या यह 1 माइक्रोसेकंड परिशुद्धता के लिए:

def DT_from_dt_u(t):
    return DT.DateTime(t.year, t.month, t.day, t.hour,
  t.minute, t.second + t.microsecond * 1e-6)

और हाँ, प्रश्न में इस एकल कार्य के लिए निर्भरता को जोड़ना निश्चित रूप से समयसीमा (रिक कोपलैंड द्वारा सुझाए गए) का उपयोग करने की तुलना में भी एक ओवरकिल होगा।


1

अंत में आपके पास एक गणित का मुद्दा है। अगर हर 4 साल में हमारे पास एक अतिरिक्त दिन होता है, तो समय में 365 से नहीं, बल्कि 365 * 4 + 1 से समय पर डाइवेल्ट करें, इससे आपको 4 साल की राशि मिल जाएगी। फिर इसे 4. टाइमलेडल्टा / ((365 * 4) +1) / 4 = टाइमडेल्टा * 4 / (365 * 4 +1) द्वारा फिर से विभाजित करें


लीप वर्ष की बात तब लागू नहीं होती है जब वर्ष 100 से विभाज्य होते हैं, सिवाय जब वे 400 से विभाज्य होते हैं। इसलिए, वर्ष 2000 के लिए: - यह चार से विभाज्य है, इसलिए इसे लीप होना चाहिए लेकिन ... - यह भी विभाज्य है सौ से, इसलिए यह छलांग नहीं होनी चाहिए लेकिन ... - यह 400 से विभाज्य है, इसलिए यह वास्तव में एक लीप वर्ष था। 1900 के लिए: - यह 4 से विभाज्य है इसलिए इसे लीप होना चाहिए। - यह 100 से विभाज्य है, इसलिए इसे लीप नहीं होना चाहिए। - यह 400 से विभाज्य नहीं है, इसलिए यह नियम लागू नहीं होता है। 1900 एक लीप वर्ष नहीं था।
जाब्लास्को

1

यह वह उपाय है जिससे मैंने काम किया, मुझे आशा है कि मदद कर सकता है ;-)

def menor_edad_legal(birthday):
    """ returns true if aged<18 in days """ 
    try:

        today = time.localtime()                        

        fa_divuit_anys=date(year=today.tm_year-18, month=today.tm_mon, day=today.tm_mday)

        if birthday>fa_divuit_anys:
            return True
        else:
            return False            

    except Exception, ex_edad:
        logging.error('Error menor de edad: %s' % ex_edad)
        return True

0

भले ही यह धागा पहले ही मर चुका है, लेकिन मैं सुझाव दे सकता हूं कि इसी समस्या का एक समाधान मैं सामना कर रहा था। यहाँ यह है (तारीख प्रारूप में एक स्ट्रिंग है dd-mm-yyyy):

def validatedate(date):
    parts = date.strip().split('-')

    if len(parts) == 3 and False not in [x.isdigit() for x in parts]: 
        birth = datetime.date(int(parts[2]), int(parts[1]), int(parts[0]))
        today = datetime.date.today()

        b = (birth.year * 10000) + (birth.month * 100) + (birth.day)
        t = (today.year * 10000) + (today.month * 100) + (today.day)

        if (t - 18 * 10000) >= b:
            return True

    return False

0

यह फ़ंक्शन दो तिथियों के बीच के वर्षों में अंतर लौटाता है (आईएसओ प्रारूप में स्ट्रिंग के रूप में लिया जाता है, लेकिन इसे किसी भी प्रारूप में लेने के लिए आसानी से संशोधित किया जा सकता है)

import time
def years(earlydateiso,  laterdateiso):
    """difference in years between two dates in ISO format"""

    ed =  time.strptime(earlydateiso, "%Y-%m-%d")
    ld =  time.strptime(laterdateiso, "%Y-%m-%d")
    #switch dates if needed
    if  ld < ed:
        ld,  ed = ed,  ld            

    res = ld[0] - ed [0]
    if res > 0:
        if ld[1]< ed[1]:
            res -= 1
        elif  ld[1] == ed[1]:
            if ld[2]< ed[2]:
                res -= 1
    return res

0

मैं Pyfdate का सुझाव दूंगा

Pyfdate क्या है?

पाइथन के लक्ष्य को एक शक्तिशाली और आसानी से उपयोग होने वाली स्क्रिप्टिंग भाषा के रूप में देखते हुए, तारीखों और समय के साथ काम करने के लिए इसकी विशेषताएं उतनी उपयोगकर्ता के अनुकूल नहीं हैं जितनी उन्हें होनी चाहिए। Pyfdate का उद्देश्य खजूर और समय के साथ काम करने के लिए सुविधाएँ प्रदान करके उस स्थिति को मापना है जो पाइथन के बाकी हिस्सों की तरह शक्तिशाली और आसानी से उपयोग होने वाली है।

ट्यूटोरियल


0
import datetime

def check_if_old_enough(years_needed, old_date):

    limit_date = datetime.date(old_date.year + years_needed,  old_date.month, old_date.day)

    today = datetime.datetime.now().date()

    old_enough = False

    if limit_date <= today:
        old_enough = True

    return old_enough



def test_ages():

    years_needed = 30

    born_date_Logan = datetime.datetime(1988, 3, 5)

    if check_if_old_enough(years_needed, born_date_Logan):
        print("Logan is old enough")
    else:
        print("Logan is not old enough")


    born_date_Jessica = datetime.datetime(1997, 3, 6)

    if check_if_old_enough(years_needed, born_date_Jessica):
        print("Jessica is old enough")
    else:
        print("Jessica is not old enough")


test_ages()

यह वह कोड है जो लोगन की रन फिल्म में काररोसेल ऑपरेटर चला रहा था;)

https://en.wikipedia.org/wiki/Logan%27s_Run_(film)


0

मुझे यह सवाल आया और एडम्स ने सबसे उपयोगी https://stackoverflow.com/a/765862/2964689 का जवाब दिया

लेकिन उसकी विधि का कोई अजगर उदाहरण नहीं था, लेकिन यहां मैंने जो प्रयोग किया वह समाप्त हो गया।

इनपुट: डेटाटाइम ऑब्जेक्ट

आउटपुट: पूरे वर्षों में पूर्णांक आयु

def age(birthday):
    birthday = birthday.date()
    today = date.today()

    years = today.year - birthday.year

    if (today.month < birthday.month or
       (today.month == birthday.month and today.day < birthday.day)):

        years = years - 1

    return years

0

मुझे अपनी सरलता के लिए जॉन मेई का समाधान पसंद आया, और मैं इस बारे में चिंतित नहीं हूं कि कैसे 28 फरवरी या 1 मार्च को, जब यह एक लीप वर्ष नहीं है, 29 फरवरी को जन्म लेने वाले लोगों की उम्र निर्धारित करने के लिए। लेकिन यहां उनके कोड का एक ट्वीक है जो मुझे लगता है कि शिकायतों को संबोधित करता है:

def age(dob):
    import datetime
    today = datetime.date.today()
    age = today.year - dob.year
    if ( today.month == dob.month == 2 and
         today.day == 28 and dob.day == 29 ):
         pass
    elif today.month < dob.month or \
      (today.month == dob.month and today.day < dob.day):
        age -= 1
    return age
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.