亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

測量兩個日期之間的月份:月份的立法定義

測量兩個日期之間的月份:月份的立法定義

絕地無雙 2022-08-25 14:39:07
我希望構建代碼,代表澳大利亞立法中月份的定義 - 解釋法(1987)。請注意,我仍然是Python的相對新手。法律定義定義如下:(1) 在任何法案中,月是指一個時期:(a)從其中一個日歷月的任何一天的開始開始;(b)結束:(i)在下一個日歷月相應日期開始前一刻結束;或。(ii) 如果沒有這樣的日期,即在下一個日歷月的月底。我被告知,這個定義意味著如果一個月的開始時間從16/07/2019開始,例如,出于a)的目的,相關月份直到11:59:59:59:etc:pm在15/08/2019結束 - 或者從功能上講,16/08/2019。因此,出于 b) 的目的,“月末”的定義與該月相關最后一天的 11:59:59:etc:etc:pm 類似。因此,如果您有兩個日期 - 31 / 08 / 2019和30 / 09 / 2019 - 相關月份直到30 / 09 / 2019的11:59:59:etc:pm為止 - 或者功能上是01 / 10 / 2019。我需要以月為單位輸出兩個日期之間的差異,以反映我正在編碼的立法要求兩個日期之間的差異,特別是以月份為單位。如果可能的話,我希望使用datetime或datetime64對象來執行此操作,以避免不必要地在變量之間進行轉換。到目前為止,我嘗試過什么。我使用以下代碼來查找月份中兩個日期之間的差異,使用相對delta:from datetime import datetimefrom dateutil import relativedeltadate1 = datetime.strptime('2019-08-15', '%Y-%m-%d')date2 = datetime.strptime('2020-02-05', '%Y-%m-%d')r = relativedelta.relativedelta(date2, date1)r.months + (12*r.years)print(r)我的預期產量是5個月,因為有五個完整的月份,然后是一個月的一小部分,而不是在date2之前完成。這將返回預期的結果,并在立法中復制 a) 的功能。但是,當我嘗試使用以下代碼復制b)時:from datetime import datetimefrom dateutil import relativedeltadate1 = datetime.strptime('2019-08-31', '%Y-%m-%d')date2 = datetime.strptime('2019-11-30', '%Y-%m-%d')r = relativedelta.relativedelta(date2, date1)r.months + (12*r.years)print(r)這將返回 4 個月的結果。由于2019-11-30不是相關日歷月的結束,這是不正確的 - 我應該獲得此代碼的3個月結果,因為該月直到11:59:59:etc才完成。預期成果下面是我用來測試此代碼結果的四個測試用例。from datetime import datetimefrom dateutil import relativedeltadate1 = datetime.strptime('2019-08-25', '%Y-%m-%d')date2 = datetime.strptime('2019-09-10', '%Y-%m-%d')r = relativedelta.relativedelta(date2, date1)r.months + (12*r.years)r.months = 0from datetime import datetimefrom dateutil import relativedeltadate1 = datetime.strptime('2019-08-25', '%Y-%m-%d')date2 = datetime.strptime('2019-09-25', '%Y-%m-%d')r = relativedelta.relativedelta(date2, date1)r.months + (12*r.years)r.months = 1
查看完整描述

3 回答

?
幕布斯6054654

TA貢獻1876條經驗 獲得超7個贊

這可以在不轉換為日期類型的情況下進行計算,但邊緣情況除外,其中日期是該月的最后一天(它們實際上對應于下個月的第零天)。


from datetime import date


def isLastDay(y,m,d):

    return date.fromordinal(date(y,m,d).toordinal()+1).month != m


def legalMonthDif(date1,date2):

    y1,m1,d1 = map(int,date1.split("-"))

    y2,m2,d2 = map(int,date2.split("-"))

    if isLastDay(y1,m1,d1): m1,d1 = m1+1,0

    if isLastDay(y2,m2,d2): m2,d2 = m2+1,0

    return y2*12+m2 -y1*12-m1 -(d2<d1)

輸出:


legalMonthDif('2019-08-15','2020-02-05') #5

legalMonthDif('2019-08-31','2019-11-30') #3

legalMonthDif('2019-08-25','2019-09-10') #0

legalMonthDif('2019-08-25','2019-09-25') #1

legalMonthDif('2019-08-31','2019-11-30') #3

legalMonthDif('2019-08-01','2019-12-01') #4 

legalMonthDif('2019-08-31','2019-12-01') #3

legalMonthDif('2019-08-15','2019-12-01') #3

您也可以通過實現daysOfMonth函數來計算任何月份中的天數,完全無需datetime庫即可完成此操作:


def daysOfMonth(y,m):

    return 30+(m+m//8)%2-(m==2)*(2-(y%4==0 and not y%100==0 or y%400==0))


def legalMonthDif(date1,date2):

    y1,m1,d1 = map(int,date1.split("-"))

    y2,m2,d2 = map(int,date2.split("-"))

    if daysOfMonth(y1,m1) == d1: m1,d1 = m1+1,0

    if daysOfMonth(y2,m2) == d2: m2,d2 = m2+1,0

    return y2*12+m2 -y1*12-m1 -(d2<d1)


查看完整回答
反對 回復 2022-08-25
?
收到一只叮咚

TA貢獻1821條經驗 獲得超5個贊

我最終編寫了以下函數,這些函數捕獲了此立法的預期功能:


def find_corresponding_date(start_date):

day = start_date.day

month = start_date.month

year = start_date.year

next_month = month + 1

next_year = year


if month == 12:

    next_month = 1

    next_year = year + 1

try:

    new_date = py_datetime(year=next_year, month=next_month, day=day)

except ValueError:

    next_month = next_month + 1

    if next_month == 13:

        next_month = 1

        next_year = next_year + 1

    new_date = py_datetime(year=next_year, month=next_month, day=1)

    return new_date


else:

    return new_date



def toPyDateTime(numpyDate):

    return py_datetime.strptime(str(numpyDate), "%Y-%m-%d")



def count_months(sdate, edate):

    start_date = toPyDateTime(sdate)

    end_date = toPyDateTime(edate)

    count = 0

    corres_date = start_date

    while(True):

        corres_date = find_corresponding_date(corres_date)

        if(corres_date > end_date):

            return count

            break

        else:

            count = count + 1


查看完整回答
反對 回復 2022-08-25
?
慕村225694

TA貢獻1880條經驗 獲得超4個贊

dates = [('2019-07-16','2019-08-15'),('2019-08-31','2019-09-30'),

         ('2019-08-15','2020-02-05'),('2019-08-31','2019-11-30'),

         ('2019-08-25','2019-09-10'),('2019-08-25','2019-09-25'),

         ('2019-08-31','2019-12-01'),('2019-08-15' , '2019-12-01'),

         ('2019-08-01', '2019-11-30'),('2019-08-01', '2019-12-01')]

使用熊貓日期時間功能。這依賴于這樣一個事實,即如果結果日期不存在,則在時間戳中添加月份將被截斷到月底 - 提供一種測試規范的(b)(ii)部分的方法。


import pandas as pd


def f(a,b):

    earlier,later = sorted((a,b))

    rel_months = later.month - earlier.month

    delta_months = rel_months + (later.year - earlier.year) * 12

    period_end = earlier + pd.DateOffset(months=delta_months)


    # sentinals for implementing logic of (b)(ii) of the definition

    period_end_isEOM = period_end + pd.tseries.offsets.MonthEnd(0)

    later_isEOM = later == later + pd.tseries.offsets.MonthEnd(0)

    next_month = period_end + pd.tseries.offsets.MonthBegin(0)


    # begin with the delta - period_end == later - then adjust

    months = delta_months

    # this is straightforward

    if period_end > later:

        months -= 1


    # did period_end get truncated to the end of a month

    if period_end_isEOM and (period_end.day < earlier.day):

        # actual end of period would be beginning of next month

        if later < next_month:    # probably also means later_isEOM or later == period_end

            months -= 1

    return months 


for a,b in dates:

   a, b = map(pd.Timestamp, (a,b))

   c = f(a,b)

   print(f'{a.date()} - {b.date()} --> {c}')


>>>

2019-07-16 - 2019-08-15 --> 0

2019-08-31 - 2019-09-30 --> 0

2019-08-15 - 2020-02-05 --> 5

2019-08-31 - 2019-11-30 --> 2

2019-08-25 - 2019-09-10 --> 0

2019-08-25 - 2019-09-25 --> 1

2019-08-31 - 2019-12-01 --> 3

2019-08-15 - 2019-12-01 --> 3

2019-08-01 - 2019-11-30 --> 3

2019-08-01 - 2019-12-01 --> 4

>>> 

pd.時間戳是datetime.datetime


這似乎有效 - 只有OP可以判斷 - 但我忍不住想到我仍然沒有利用一些內置功能。應該能夠子類熊貓。日期偏移并自定義它以使計算更容易。


使用 Pandas.DateOffset 子類的解決方案。


from pandas import DateOffset, Timestamp

from pandas.tseries.offsets import MonthBegin


class LegislativeMonth(DateOffset):

    def __init__(self, n=1, normalize=False, months=1):

        # restricted to months

        kwds = {'months':months}

        super().__init__(n=1, normalize=False, **kwds)

    def apply(self,other):

        end_date = super().apply(other)

        if end_date.day < other.day:

            # truncated to month end

            end_date = end_date + MonthBegin(1)

        return end_date


for a,b in dates:

   earlier,later = sorted(map(Timestamp, (a,b)))

   delta_months = later.month - earlier.month

   delta_months += (later.year - earlier.year) * 12

   end_of_period = earlier + LegislativeMonth(months=delta_months)

   if end_of_period > later:

       delta_months -= 1

   print(f'{earlier.date()} - {later.date()} --> {delta_months}')


# another


one_month = LegislativeMonth(months=1)

for a,b in dates:

   earlier,later = sorted(map(Timestamp, (a,b)))

   end_period = earlier

   months = 0

   while later >= end_period + one_month:

       months += 1

       end_period += one_month

   print(f'{earlier.date()} - {later.date()} --> {months}')

最后,如果您確保以較早的日期作為第一項來調用它,它看起來像是會做您想要的 -relativedelta(earlier,later)


from datetime import datetime

from dateutil.relativedelta import relativedelta


for a,b in dates:

##   earlier,later = sorted(map(Timestamp, (a,b)))

    earlier,later = sorted((datetime.strptime(a, '%Y-%m-%d'),

                            datetime.strptime(b, '%Y-%m-%d')))

    rd = relativedelta(earlier,later)

    print(f'{earlier.date()} - {later.date()} --> {abs(rd.months)}')

使用此帖子頂部的日期,所有日期都將打印以下內容:


2019-07-16 - 2019-08-15 --> 0

2019-08-31 - 2019-09-30 --> 0

2019-08-15 - 2020-02-05 --> 5

2019-08-31 - 2019-11-30 --> 2

2019-08-25 - 2019-09-10 --> 0

2019-08-25 - 2019-09-25 --> 1

2019-08-31 - 2019-12-01 --> 3

2019-08-15 - 2019-12-01 --> 3

2019-08-01 - 2019-11-30 --> 3

2019-08-01 - 2019-12-01 --> 4


查看完整回答
反對 回復 2022-08-25
  • 3 回答
  • 0 關注
  • 108 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號