python生成时间序列(date_range)

P--K 2018-09-29 原文

python生成时间序列(date_range)

介绍

自己写了一个用python内置模块实现的生成时间序列的函数

支持自动推断字符串到datetime的转换, 但对格式有一定要求, 其它格式可手动指定格式化方式, 格式化方式与python内置格式化格式完全一致

支持输出格式化

以下是方法的源代码(python环境3.5以上, 没做更多版本的支持, 需要的自己稍作调整即可)

源代码

import re
import calendar
import datetime


class FormatError(ValueError):
    pass


class Date(object):
    @classmethod
    def date_range(cls, start=None, end=None, periods=None, freq=None, input_format=None, out_format=None):
        """
        生成时间序列
        :param start: 序列开始时间
        :param end: 序列结束时间, 给定start时, 结束时间不包含end
        :param periods: int, 生成的时间序列长度
        :param freq: 要生成时间序列的时间间隔
        :param out_format: 是否输出格式化后的字符串, 若要输出可指定输出格式. "%Y-%m-%d %H:%M:%S"
        :param input_format: 若start或end是字符串且无法自动推断时间格式则需指定格式
        :return: [date or date_str]
        """
        start = cls.str_to_date(start, input_format)
        end = cls.str_to_date(end, input_format)
        out = []
        if start is None and end and periods:
            for i in range(periods-1):
                old, end = cls.date_replace(end, cls._freq(freq), mod="-")
                if i == 0:
                    out.append(old)
                out = [end] + out
        elif end is None and start and periods:
            for i in range(periods-1):
                old, start = cls.date_replace(start, cls._freq(freq), mod="+")
                if i == 0:
                    out.append(old)
                out.append(start)
        elif periods is None and start and end:
            i = 0
            while True:
                old, start = cls.date_replace(start, cls._freq(freq), mod="+")
                if i == 0:
                    out.append(old)
                    i += 1
                if start < end:
                    out.append(start)
                else:
                    break
        else:
            raise ValueError("start, end, periods 须且只能指定其中两个")
        if out_format is True:
            out = [str(i) for i in out]
        elif out_format is not None:
            out = [i.strftime(out_format) for i in out]
        return out

    @staticmethod
    def date_replace(date, freq=(0, )*6, mod="+"):
        timedelta = datetime.timedelta(days=freq[2], hours=freq[3], minutes=freq[4], seconds=freq[5])
        if mod == "+":
            if sum(freq[:2]) == 0:
                old = date
                date = date + timedelta
            elif sum(freq[2:]) == 0:
                y = date.year + freq[0] + (date.month + freq[1] - 1) // 12
                m = (date.month + freq[1] - 1) % 12 + 1
                old = date.replace(day=calendar.monthrange(date.year, date.month)[1])
                date = date.replace(year=y, month=m, day=calendar.monthrange(y, m)[1])
            else:
                raise ValueError(" '年月' 不能同时和 '日时分秒' 作为间隔")
        elif mod == "-":
            if sum(freq[:2]) == 0:
                old = date
                date = date - timedelta
            elif sum(freq[2:]) == 0:
                y = date.year - freq[0] + (date.month - freq[1] - 1) // 12
                m = (date.month - freq[1] - 1) % 12 + 1
                old = date.replace(day=calendar.monthrange(date.year, date.month)[1])
                date = date.replace(year=y, month=m, day=calendar.monthrange(y, m)[1])
            else:
                raise ValueError(" '年月' 不能同时和 '日时分秒' 作为间隔")
        else:
            raise ValueError("mod值只能是 '+' 或 '-' ")
        return old, date

    @staticmethod
    def _freq(freq=None):
        """
        设置时间间隔
        :param freq: "Y2m3d4H5M6S" 表示间隔 1年2月3日4时5分6秒
        :return: [年, 月, 日, 时, 分, 秒]
        """
        freq_ = [0] * 6
        if freq is None:
            freq_[2] = 1
            return freq_
        for n, i in enumerate(["Y", "m", "d", "H", "M", "S"]):
            r = f'((\d*){i})'
            s = re.search(r, freq)
            if s:
                freq_[n] = int(s.group(2)) if s.group(2) else 1
        return freq_

    @staticmethod
    def str_to_date(string, format_=None):
        """
        字符串转时间, 默认自动推断格式
        :param string: 时间字符串
        :param format_: 格式
        :return: 对应的时间类型, 输入非字符串则原值输出
        """
        if not isinstance(string, str):
            return string
        if format_:
            return datetime.datetime.strptime(string, format_)
        s = re.match(r'(\d{4})\D+(\d{1,2})\D+(\d{1,2})(?:\D+(\d{1,2}))?(?:\D+(\d{1,2}))?(?:\D+(\d{1,2}))?\D*$', string)
        if s:
            result = [int(i) for i in s.groups() if i]
            return datetime.datetime(*result)
        s = re.match(r'(\d{4})\D*(\d{2})\D*(\d{2})\D*(\d{2})?\D*(\d{2})?\D*(\d{2})?\D*$', string)
        if s:
            result = [int(i) for i in s.groups() if i]
            return datetime.datetime(*result)
        else:
            raise FormatError("自动推断失败, 请指定format_")

使用方式

print(Date.date_range(datetime.datetime(2018, 9, 18), periods=10))
print()
print(Date.date_range('20180918', '2018-09-28'))
print()
print(Date.date_range(end='20180927', periods=10))
print()
print(Date.date_range('20180918', '2018-09-28', out_format=True))
print()
print(Date.date_range('2018/09/18', '2018-09-28', out_format="%Y-%m-%d"))
print()
print(Date.date_range('2018年9月18日', '2019-09-28', freq="m", out_format="%Y-%m-%d"))
print()
print(Date.date_range('2018/9/18', '2018-9-19', freq="3H", out_format=True))

对应结果

[datetime.datetime(2018, 9, 18, 0, 0), datetime.datetime(2018, 9, 19, 0, 0), datetime.datetime(2018, 9, 20, 0, 0), datetime.datetime(2018, 9, 21, 0, 0), datetime.datetime(2018, 9, 22, 0, 0), datetime.datetime(2018, 9, 23, 0, 0), datetime.datetime(2018, 9, 24, 0, 0), datetime.datetime(2018, 9, 25, 0, 0), datetime.datetime(2018, 9, 26, 0, 0), datetime.datetime(2018, 9, 27, 0, 0)]

[datetime.datetime(2018, 9, 18, 0, 0), datetime.datetime(2018, 9, 19, 0, 0), datetime.datetime(2018, 9, 20, 0, 0), datetime.datetime(2018, 9, 21, 0, 0), datetime.datetime(2018, 9, 22, 0, 0), datetime.datetime(2018, 9, 23, 0, 0), datetime.datetime(2018, 9, 24, 0, 0), datetime.datetime(2018, 9, 25, 0, 0), datetime.datetime(2018, 9, 26, 0, 0), datetime.datetime(2018, 9, 27, 0, 0)]

[datetime.datetime(2018, 9, 18, 0, 0), datetime.datetime(2018, 9, 19, 0, 0), datetime.datetime(2018, 9, 20, 0, 0), datetime.datetime(2018, 9, 21, 0, 0), datetime.datetime(2018, 9, 22, 0, 0), datetime.datetime(2018, 9, 23, 0, 0), datetime.datetime(2018, 9, 24, 0, 0), datetime.datetime(2018, 9, 25, 0, 0), datetime.datetime(2018, 9, 26, 0, 0), datetime.datetime(2018, 9, 27, 0, 0)]

['2018-09-18 00:00:00', '2018-09-19 00:00:00', '2018-09-20 00:00:00', '2018-09-21 00:00:00', '2018-09-22 00:00:00', '2018-09-23 00:00:00', '2018-09-24 00:00:00', '2018-09-25 00:00:00', '2018-09-26 00:00:00', '2018-09-27 00:00:00']

['2018-09-18', '2018-09-19', '2018-09-20', '2018-09-21', '2018-09-22', '2018-09-23', '2018-09-24', '2018-09-25', '2018-09-26', '2018-09-27']

['2018-09-30', '2018-10-31', '2018-11-30', '2018-12-31', '2019-01-31', '2019-02-28', '2019-03-31', '2019-04-30', '2019-05-31', '2019-06-30', '2019-07-31', '2019-08-31']

['2018-09-18 00:00:00', '2018-09-18 03:00:00', '2018-09-18 06:00:00', '2018-09-18 09:00:00', '2018-09-18 12:00:00', '2018-09-18 15:00:00', '2018-09-18 18:00:00', '2018-09-18 21:00:00']

 

发表于 2018-09-29 12:08 _殇 阅读() 评论() 编辑 收藏

 

版权声明:本文为P--K原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/P--K/p/9723050.html

python生成时间序列(date_range)的更多相关文章

  1. 『无为则无心』Python序列 — 19、Python列表的其他操作(切片和遍历)

    目录 1、通过切片对列表的操作 (1)通过切片对列表进行修改 (2)通过切片对列表进行删除 (3)注意 2、列 […]...

  2. 一篇文章教会你使用Python定时抓取微博评论

    【Part1——理论篇】 试想一个问题,如果我们要抓取某个微博大V微博的评论数据,应该怎么实现呢?最简单的做法 […]...

  3. python基础

    第一模块知识总结: python3中有六个标准的数据类型 Number(数字) int 定义:用来描述/标识类 […]...

  4. Python字典

    1. 字典概述    字典是Python基本数据结构——映射。字典包含了一个索引的集合,被称为键 (keys) […]...

  5. python week08 并发编程之多线程–实践部分

    python week08 并发编程之多线程–实践部分 一. threading模块介绍   mu […]...

  6. python基础

    404...

  7. pycharm2021永久激活

    Pycharm破解版地址: 链接: https://pan.baidu.com/s/1dEkzKRFMaeNj […]...

  8. 手把手教你使用Python生成图灵智能小伙伴,实现工作助手/闲聊功能

    /1 前言/ 在家闲着,做个小项目,基于Python,实现一个语聊小机器人,分享给大家。项目整体比较简单,官方 […]...

随机推荐

  1. 如何查看mac系统是32位还是64位的操作系统

    (一)点击工具栏左上角点击 (苹果Logo)标志,关于本机  –>  更多信息 ̵ […]...

  2. AJAX 基础,简单的实例:计算器 – 赤色火焰

    AJAX 基础,简单的实例:计算器 AJAX 组成 1.表示      XHTML+CSS 2.动态显示和交互 […]...

  3. C#.Net与MATLAB集成

    在数学分析工具方面,MATLAB无疑是佼佼者,除了作为软件工具外,MATLAB的自定义编程语言以及混合编程的支 […]...

  4. Linux 修改本地时间 (centos为例)

    1.  tzselect  [root@xxxx etc]# tzselect --- 选择时区命令 Plea […]...

  5. SpringBoot开发案例之分布式集群共享Session

    前言 在分布式系统中,为了提升系统性能,通常会对单体项目进行拆分,分解成多个基于功能的微服务,如果有条件,可能 […]...

  6. MSSQL如何将查询结果拼接成字符串

    在博问上看到一个提问“MSSQL如何将查询结果拼接成字符串” ,想了一下应该怎么实现呢,在c#等语言下好实现, […]...

  7. win8.1 pro-64位下安装配置MinGW—64位

    1.下载MinGW-w64位;http://mingw-w64.org/doku.php 点击Download […]...

  8. Java入门 手把手教你配置环境变量

    很多人觉得配置Java开发的环境变量很麻烦,很容易忘记,时常被它搞得晕头转向。如果出现这样的情况,那么原因只有 […]...

展开目录

目录导航