测量两个日期之间的月份:月份的立法定义 [英] Measuring months between two dates : legislative definition of months

查看:63
本文介绍了测量两个日期之间的月份:月份的立法定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找构建代表澳大利亚立法中月份定义的代码-解释法(1987).

I'm looking to build code that represents the definition of months in a piece of Australian legislation - the Interpretations Act (1987).

请注意,我还是Python的相对新手.

Please note that I am still a relative novice to Python.

法律定义

定义如下:

(1)在任何法律中,月份是指以下期间:(a)从一个公历月中任何一天的开始开始;和.(b)结束:(i)紧接在下一日历月的相应日期开始之前;或者.(ii)如果没有这样的日子-在下一个日历月末.

我被告知,此定义意味着,例如,对于a)而言,如果一个月的开始于2019年7月16日,则相关的月份要到11:59:59:etc才结束:pm在15/08/2019-或功能上为16/08/2019.

I've been advised that this definition means that if the start of a month begins on 16/07/2019, for the purposes of a) for example, the relevant month does not conclude until 11:59:59:etc:pm on 15/08/2019 - or functionally, 16/08/2019.

那么,出于b)的目的,月末"的定义类似地在该月的最后一天的11:59:59:etc:pm.因此,如果您有两个日期-31/08/2019和30/09/2019-相关月份直到30/09/2019的11:59:59:etc:pm才结束-或实际上是01/10/2019

For the purpose of b), then, the "end of a month" is defined at similarly 11:59:59:etc:pm on the relevant final day of the month. So if you have two dates - 31/08/2019 and 30/09/2019 - the relevant month does not conclude until 11:59:59:etc:pm on 30/09/2019 - or functionally, 01/10/2019.

我需要输出两个月之间的差异,以反映我正在编写的法规要求两个日期之间的差异,具体来说是几个月.

I need to output the difference between two dates in months in order to reflect that the legislation I'm coding asks for a difference between two dates specifically in months.

我希望尽可能使用datetime或datetime64对象来执行此操作,以避免不必要地在变量之间进行转换.

I'm looking to do this with either datetime or datetime64 objects if possible, to avoid converting between variables unnecessarily.

到目前为止我已经尝试过.

我已经使用下面的代码使用relativedelta来找到两个月中两个日期之间的时差:

I've used the below code to find the difference between two dates in months, using relativedelta:

from datetime import datetime
from dateutil import relativedelta
date1 = 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)的功能.

My expected output for this is 5 months, as there are five complete months and then a fraction of a month that isn't completed by date2. This returns the expected result, and replicates the functionality of a) in the legislation.

但是,当我尝试使用以下代码复制b)时:

However, when I try to replicate b) with the below code:

from datetime import datetime
from dateutil import relativedelta
date1 = 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才完成.

This returns the result of 4 months. Because 2019-11-30 is not the end of the relevant calendar month, this is incorrect - I should be getting a result of 3 months for this code, as the month is not completed until 11:59:59:etc.

预期结果

下面是我用来测试此代码结果的四个测试用例.

Below are four test cases that I've used to test the results of this code.

from datetime import datetime
from dateutil import relativedelta
date1 = 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 = 0

from datetime import datetime
from dateutil import relativedelta
date1 = 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

from datetime import datetime
from dateutil import relativedelta
date1 = 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)
r.months = 3

from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2019-08-31', '%Y-%m-%d')
date2 = datetime.strptime('2019-12-01', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)
r.months = 4

我已经写了后两个测试用例的输入,并且在回顾了Alain T.的回答之后,修改为以下内容.

I've written the inputs for the second two test cases, and after reviewing Alain T.'s response, have revised to the below.

from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2019-08-01', '%Y-%m-%d')
date2 = datetime.strptime('2019-11-30', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)
r.months = 3

from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2019-08-01', '%Y-%m-%d')
date2 = datetime.strptime('2019-12-01', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)
r.months = 4

from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2019-08-31', '%Y-%m-%d')
date2 = datetime.strptime('2019-12-01', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)
r.months = 3

推荐答案

这可以在不转换为日期类型的情况下进行计算,但边缘情况除外,在这种情况下,日期是该月的最后一天(实际上它们对应于日期的零天).下个月).

This can be calculated without converting to date types except for the edge case where dates are the last day of the month (where they actually correspond to day zero of the next month).

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库来完成此操作:

You could also do it completely without the datetime library by implementing a daysOfMonth function to compute the number of days in any month:

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)

这篇关于测量两个日期之间的月份:月份的立法定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆