日期范围的通配符表示-附python代码

日期范围的通配符表示-附python代码,第1张

本文记录了将给定的日期范围用通配符表示的相关内容,欢迎与我沟通联系(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']

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/568815.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-09
下一篇 2022-04-09

发表评论

登录后才能评论

评论列表(0条)

保存