170

ある日付から何年か経過しているかどうかを確認する必要があります。現在、モジュールtimedeltaから取得しdatetimeていますが、それを年に変換する方法がわかりません。

4

21 に答える 21

180

timedelta何年が経過したかを知るには、a 以上のものが必要です。また、開始日 (または終了日) も知っておく必要があります。(うるう年のことです。)

あなたの最善の策はdateutil.relativedelta objectを使用することですが、それはサードパーティのモジュールです。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)

あなたの質問はもともと、ある日付から何年経ったか知りたいと言っていました。整数の年数が必要だと仮定すると、1 年あたり 365.2425 日に基づいて推測し、yearsago上記で定義した関数のいずれかを使用して確認できます。

def num_years(begin, end=None):
    if end is None:
        end = datetime.now()
    num_years = int((end - begin).days / 365.2425)
    if begin > yearsago(num_years, end):
        return num_years - 1
    else:
        return num_years
于 2009-04-19T20:05:15.943 に答える
57

誰かが 18 歳かどうかを確認しようとしているtimedelta場合、閏年が原因で一部のエッジ ケースでは を使用すると正しく機能しません。たとえば、2000 年 1 月 1 日に生まれた人は、2018 年 1 月 1 日からちょうど 6575 日後の 18 歳になりますが (閏年 5 年を含む)、2001 年 1 月 1 日に生まれた人は、ちょうど 6574 日後の 1 月 1 日に 18 歳になります。 2019 年 (うるう年 4 年を含む)。したがって、誰かが正確に 6574 日である場合、生年月日に関する情報をもう少し知らなければ、その人が 17 歳なのか 18 歳なのかを判断することはできません。

これを行う正しい方法は、日付から直接年齢を計算し、2 年を引き、現在の月/日が誕生月/日より前の場合は 1 を引くことです。

于 2009-04-19T18:36:03.257 に答える
10

まず、最も詳細なレベルでは、問題を正確に解決することはできません。年の長さはさまざまであり、年の長さの明確な「正しい選択」はありません。

そうは言っても、「自然な」単位(おそらく秒)で差を取り、それと年の比率で割ります。例えば

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

...または何でも。月は年よりも明確に定義されていないため、月は避けてください。

于 2009-04-19T18:08:08.083 に答える
9

これは更新された 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)))
于 2012-08-10T10:53:50.037 に答える
7

日数を取得し、年数を 365.2425 (グレゴリオ暦の平均年) で割ります。月は 30.436875 (平均グレゴリオ月) で割ります。

于 2009-12-24T21:13:42.023 に答える
5

どのくらい正確である必要がありますか? td.days / 365.25うるう年が心配な場合は、かなり近づくことができます。

于 2009-04-19T18:04:03.020 に答える
3
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
于 2009-11-30T01:51:16.053 に答える
1

ここで言及されていないさらに別のサードパーティ ライブラリは、mxDateTime (pythondatetimeとサードパーティの両方の前身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 つのタスクに依存関係を追加することは、timeutil を使用する場合と比べても間違いなくやり過ぎです (Rick Copeland が提案)。

于 2009-12-24T20:52:12.080 に答える
1

最後に、あなたが持っているのは数学の問題です。4 年ごとに 1 日余分にある場合、timedelta を 365 日ではなく 365*4 + 1 日で割ると、4 年になります。次に、再度 4 で割ります。 timedelta / ((365*4) +1) / 4 = timedelta * 4 / (365*4 +1)

于 2010-07-15T23:20:49.107 に答える
1

このメソッドは、datetime ライブラリのハックです。

def calculate_age(birthday_date, fmt="%Y-%m-%d"):
    birthday = datetime.datetime.strptime(birthday_date, fmt)
    age = datetime.datetime.now() - birthday
    # first datime valid is (1, 1, 1), I use (1, 12, 31) => (2, 0, 0) to hack the lib
    age = (datetime.datetime(1, 12, 31) + age)
    return age.year - 2

この解決策は奇妙なので、共有しました。これはおそらく最も洗練された関数ではありません。

now : 2019-09-21

print(calculate_age("2019-09-21")) => 2 (Done) 

-> age + (1,12,31) = 0004-01-01 23:42:17.767031

print(calculate_age("2020-09-21")) => 0 (Undone)

-> age + (1,12,31) = 0002-12-31 23:46:39.144091

その差は1日。違いの理由は bisextile (閏年) によるものだと理解しています。

この望ましくない動作を修正するには、誕生日の年を使用して結果を追加する必要があります。

于 2021-09-21T21:30:50.553 に答える
0

Pyfdateをお勧めします

pyfdateとは何ですか?

強力で使いやすいスクリプト言語になるというPythonの目標を考えると、日付と時刻を操作するためのPythonの機能は、本来あるべきほどユーザーフレンドリーではありません。pyfdateの目的は、Pythonの他の部分と同じくらい強力で使いやすい日付と時刻を操作するための機能を提供することにより、この状況を改善することです。

チュートリアル_

于 2009-12-01T04:48:56.337 に答える
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
于 2009-07-03T10:51:42.820 に答える
0

この関数は、2 つの日付の年の差を返します (ISO 形式の文字列として取得されますが、任意の形式で取得するように簡単に変更できます)

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
于 2009-09-01T09:29:40.003 に答える
0

私の目的のために、2 つのdatetimeオブジェクト (少なくとも Python 3.8 では)の減算は、属性timedeltaのみを持つ に変換されます。days

>>> admit = datetime.strptime('20130530', '%Y%m%d')
>>> birth = datetime.strptime('20010621', '%Y%m%d')
>>> age = (admit - birth).days/365.2425
>>> age
11.940012457476882
于 2021-06-03T20:15:55.010 に答える
0

パーティーには遅れましたが、これで年齢 (年数) が正確かつ簡単にわかります。

b = birthday
today = datetime.datetime.today()
age = today.year - b.year + (today.month - b.month > 0 or 
                             (today.month == b.month > 0 and 
                              today.day - b.day > 0))
于 2020-12-02T05:19:42.003 に答える