日期范围的通配符表示-附python代码
Posted BJUT赵亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日期范围的通配符表示-附python代码相关的知识,希望对你有一定的参考价值。
本文记录了将给定的日期范围用通配符表示的相关内容,欢迎与我沟通联系(zhaoliang19960421@outlook.com)
如果在使用中发现程序输入与结果不符,欢迎与我沟通
在hdfs中数据以date为分区进行分别保存,采用MapReduce框架进行大数据开发时在路径输入中,没有在hive\\sql中的 date between . and . 的写法,与之对应的是将日期采用通配符的形式进行输入
case1 日期范围是:20220101 20221231
解释:需要输入的是2022年一整年的数据,所以采用通配符的表达方式为2022*
case2 日期范围是 : 20210101 20210331
解释:需要输入的2021年,1月、2月、3月的全部日期,采用通配符的表示方式是 '202101*', '202102*', '202103*'
case3 日起范围是:20200104 20210302
解释:需要输入的是,从1月4号到1月底,2月整月、3月1号,3月2号的日期,采用通配符的表示方式是 ['20200104', '20200105', '20200106', '20200107', '20200108', '20200109', '2020011*', '2020012*', '2020013*', '202002*', '202003*', '202004*', '202005*', '202006*', '202007*', '202008*', '202009*', '202010*', '202011*', '202012*', '202101*', '202102*', '20210301', '20210302']
因为1月4号到1月9号,无法继续采用通配符,所以全部枚举;1月10号到1月19号、1月11号到19号、1月21号到1月29号、1月30号到1月31号,均可以用通配符。
将以上问题抽象为数学问题是,给定一个函数,输入的是2个字符串[start,end]的日期范围,输出一个字符串数组,这个字符串数组是给定日期范围的通配符表示式的最简结果
具体的解法为递归,在给定日期范围种,先判断年,如果年不相同,则将中间的年份抽出来,前后两端分别判单,则成为了递归
20200101 20200101-20201231
=》 2021
20221231 20220101-20221231
中间的日期通过通配符表示,前后两端继续递归,直到最后的日期
def function(start: str, end: str):
def _yyyyMM2dd(yyyy, MM):
if MM in 1, 3, 5, 7, 8, 10, 12:
return 31
if MM != 2:
return 30
if (yyyy % 4 == 0) and (yyyy % 100 != 0) or (yyyy % 400) == 0:
return 29
else:
return 28
if start == end: return [start]
if start > end: return []
res = []
if start[:4] != end[:4]: # 年不相同,中间的年份全部用通配符
for i in range(int(start[:4]) + 1, int(end[:4])):
res.append(":0>4*".format(i))
res.extend(function(start, f"start[:4]1231"))
res.extend(function(f"end[:4]0101", end))
return res
if start[4:6] != end[4:6]: # 月份不一样
for i in range(int(start[4:6]) + 1, int(end[4:6])):
res.append(":0>2*".format(start[:4], i))
res.extend(function(start, f"start[:6]_yyyyMM2dd(int(start[:4]), int(start[4:6]))"))
res.extend(function(f"end[:6]01", end))
if len(res)==12 and len(list(set([i[4:6] for i in res]))) == 12:
res = ["*".format(start[:4])]
return res
if start[6:8] != end[6:8]: # 日期不同
if start[6] != end[6]:
for i in range(int(start[6]) + 1, int(end[6])):
res.append("*".format(start[:6], i))
if start[6] in ["0", "1"]:
start_day_last_num = 9
elif start[6] == "2":
if _yyyyMM2dd(int(start[:4]), int(start[4:6])) == 28:
start_day_last_num = 8
else:
start_day_last_num = 9
elif start[6] == "3":
start_day_last_num = 1
res.extend(function(start, f"start[:7]start_day_last_num"))
if end[6] == "0":
end_day_first_num = 1
else:
end_day_first_num = 0
res.extend(function(f"end[:7]end_day_first_num", end))
# print(res)
if int(start[4:6]) == 2:
if len(res)==3 and len(list(set([i[6] for i in res]))) == 3:
res = ["*".format(start[:6])]
else:
if len(res)==4 and len(list(set([i[6] for i in res]))) == 4:
res = ["*".format(start[:6])]
# print(res)
# print()
return res
if start[7] != end[7]:
for i in range(int(start[7]), int(end[7]) + 1):
res.append("".format(start[:7], i))
# 剪枝合并
# print(res)
if int(start[4:6]) in [1, 3, 5, 7, 8, 10, 12]:
if (start[6] == "0" and len(res) == 9) or (start[6] in ["1", "2"] and len(res) == 10) or (
start[6] == "3" and len(res) == 2):
res = ["*".format(start[:7])]
elif int(start[4:6]) == 2:
if _yyyyMM2dd(int(start[:4]), int(start[4:6])) == 29:
if (start[6] == "0" and len(res) == 9) or (start[6] in ["1", "2"] and len(res) == 10):
res = ["*".format(start[:7])]
else:
if (start[6] == "0" and len(res) == 9) or (start[6] == "1" and len(res) == 10) or (
start[6] == "2" and len(res) == 9):
res = ["*".format(start[:7])]
else:
if (start[6] == "0" and len(res) == 9) or (start[6] in ["1", "2"] and len(res) == 10) or (
start[6] == "3" and len(res) == 1):
res = ["*".format(start[:7])]
# print(res)
# print()
return res
res = function("20201227", "20210302")
res.sort()
print(res)
function("20210101", "20210331") => ['202101*', '202102*', '202103*']
function("20210101", "20211231") => ['2021*']
function("20200101", "20211231") => ['2020*', '2021*']
function("20200104", "20210302") => ['20200104', '20200105', '20200106', '20200107', '20200108', '20200109', '2020011*', '2020012*', '2020013*', '202002*', '202003*', '202004*', '202005*', '202006*', '202007*', '202008*', '202009*', '202010*', '202011*', '202012*', '202101*', '202102*', '20210301', '20210302']
function("20210104", "20210302") => ['20210104', '20210105', '20210106', '20210107', '20210108', '20210109', '2021011*', '2021012*', '2021013*', '202102*', '20210301', '20210302']
以上是关于日期范围的通配符表示-附python代码的主要内容,如果未能解决你的问题,请参考以下文章
使用具有相对日期范围和标准 SQL 的 Bigquery Table 通配符 [重复]