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']
python生成时间序列(date_range)的更多相关文章
- JavaScript 解析 Django Python 生成的 datetime 数据 时区问题解决
JavaScript 解析 Django/Python 生成的 datetime 数据 当Web后台使用Django时,后台生成的时间数据类型就是Python类型的. 项目需要将几个时间存储到数据库中 ...
- 【python】【转】Python生成随机数的方法
如果你对在Python生成随机数与random模块中最常用的几个函数的关系与不懂之处,下面的文章就是对Python生成随机数与random模块中最常用的几个函数的关系,希望你会有所收获,以下就是这篇文 ...
- Python生成随机数的方法
这篇文章主要介绍了Python生成随机数的方法,有需要的朋友可以参考一下 如果你对在Python生成随机数与random模块中最常用的几个函数的关系与不懂之处,下面的文章就是对Python生成随机数与 ...
- Python 生成的页面中文乱码问题
第一 保证 程序源文件里的中文的编码格式,如我们把 源文件的编码设置成utf8的. reload(sys) sys.setdefaultencoding('utf-8') 第二, 告诉浏览器,我们须要 ...
- 如何使用python生成xml
最近要用python生成一个xml格式的文件.因为有一些内容是中文,原来的xml文件中使用了CDATA 的部分. 而之前的python程序所用的库中没有 创建这个区域的方法.无奈研究了大半天. 最后用 ...
- python生成随机图形验证码
使用python生成随机图片验证码,需要使用pillow模块 1.安装pillow模块 pip install pillow 2.pillow模块的基本使用 1.创建图片 from PIL impor ...
- Python 生成随机验证码
Python生成随机验证码 Python生成随机验证码,需要使用PIL模块. 安装: 1 pip3 install pillow 基本使用 1. 创建图片 1 2 3 4 5 6 7 8 9 fro ...
- Python生成随机验证码
Python生成随机验证码,需要使用PIL模块. 安装: pip3 install pillow 基本使用 1.创建图片 from PIL import Image img = Image.new(m ...
- python 生成18年写过的博客词云
文章链接:https://mp.weixin.qq.com/s/NmJjTEADV6zKdT--2DXq9Q 回看18年,最有成就的就是有了自己的 博客网站,坚持记录,写文章,累计写了36篇了,从一开 ...
随机推荐
- 正则表达式-固定XML格式提取内容
(?<=(<(?<a>([A-Za-z]*?))>)).*?(?=(</\k<a>>))
- 字节跳动Android实习面试难吗,应该如何应对?
字节跳动的面试难不难其实很难去非常准确的定义,但是能肯定的一点是,字节跳动的面试题都很有水平,真正考察了该岗位在以后工作中需要的能力. 大学学的Java后面又自学Android方向,跟着老师在实验室做 ...
- 面试必备:Android Activity启动流程源码分析
最近大致分析了一把 Activity 启动的流程,趁着今天精神状态好,把之前记录的写成文章. 开门见山,我们直接点进去看 Activity 的 startActivity , 最终,我们都会走到 st ...
- 10 个超棒的 JavaScript 简写技巧
今天我要分享的是10个超棒的JavaScript简写方法,可以加快开发速度,让你的开发工作事半功倍哦. 开始吧! 1. 合并数组 普通写法: 我们通常使用Array中的concat()方法合并两个数组 ...
- Java程序员的推荐阅读书籍
作为Java程序员来说,最痛苦的事情莫过于可以选择的范围太广,可以读的书太多,往往容易无所适从.我想就我自己读过的技术书籍中挑选出来一些,按照学习的先后顺序,推荐给大家,特别是那些想不断提高自己技术水 ...
- shell趣味实验——图形
目录 一.直线 二.矩形 2.1.镂空矩形 三.直角三角形 3.1.倒直角三角形 3.2.反直角三角形 3.3.等腰三角形 3.4.倒等腰三角形 3.5.菱形 四.平行四边形 五.梯形 5.1.等腰梯 ...
- 轻松上手SpringBoot+SpringSecurity+JWT实RESTfulAPI权限控制实战
前言 我们知道在项目开发中,后台开发权限认证是非常重要的,springboot 中常用熟悉的权限认证框架有,shiro,还有就是springboot 全家桶的 security当然他们各有各的好处,但 ...
- Linux搭建Radius服务器
安装环境介绍 以下服务器信息为该文档安装Radius服务环境 服务器信息:CentOS7 内核版本:3.10.0-1062.el7.x86_64 安装软件版本 freeradius-utils-3.0 ...
- Set重写hashCode和equals方法实现引用对象去重
运作原理: 首先判断hashCode是否相同,如果不同,直接判定为两个不同的对象.如果hashCode相同,再去比较equals是否一样,如果一样,则为同一个对象.如果不一样,则是两个不同对象. 那么 ...
- Maven解决依赖冲突
依赖冲突 若项目中多个Jar同时引用了相同的Jar时,会产生依赖冲突,但Maven采用了两种避免冲突的策略,因此在Maven中是不存在依赖冲突的. 短路优先 本项目-->A.jar-->B ...