pandas.date_range笔记以及日期闭合的坑

前言

前几天给别人开发一个数据统计小程序,需要根据出入库时间统计返库天数,他们统计的要求是不计时间的,只看日期就可以,但是他的原始数据是从公司系统导出的,默认是带有时间的,结果统计的结果是在同一天出库同一天返库的订单返库天数不一样!问题出在pandas.date_range上。

pandas.date_range介绍

pandas.date_range官方文档:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.date_range.html
语法:

pandas.date_range(start=None, end=None, periods=None, freq=None, tz=None, normalize=False, name=None, closed=None, **kwargs) → pandas.core.indexes.datetimes.DatetimeIndex

注意:start=None, end=None, periods=None 虽然这三个参数都有默认值,但是必须填写其中的两个参数,否则报错!
参数说明:
start:str 或 datetime,日期左边界
end:str 或 datetime, 日期右边界
periods:int,固定时期,取值为整数或None
freq:日期偏移量,取值为str或DateOffset,默认为’D’,取值参考文档;取值可以是多个,比如5H,1D10min/1D10T
tz:str 或 tzinfo;返回本地化 时间索引对象的时区名称, 比如 ‘Asia/Hong_Kong’. 默认情况下生成的时间索引对象是与时区无关的.
normalize:bool, 默认为 False;若赋值为True表示在生成日期范围之前,将开始/结束日期规范化为午夜时间
name:str, 默认为 None;生成时间索引对象的名称,取值为string或None
closed:{None, ‘left’, ‘right’}, 三个选项,默认None(两边闭合),closed=‘left’左闭右开,closed='right’左开右闭
**kwargs:为了兼容性,对结果没有影响
例如:

import pandas as pd
In [1]:
pd.date_range('2011-01-03', periods=5, freq='B')
Out[1]:
DatetimeIndex(['2011-01-03', '2011-01-04', '2011-01-05', '2011-01-06',
               '2011-01-07'],
              dtype='datetime64[ns]', freq='B')
In [2]:
pd.date_range('2011-01-03', periods=5, freq=pd.offsets.BDay())
Out[2]:
DatetimeIndex(['2011-01-03', '2011-01-04', '2011-01-05', '2011-01-06',
               '2011-01-07'],
              dtype='datetime64[ns]', freq='B')
In [3]:
pd.date_range('2011-01-01 00:00:00', periods=10, freq='2h20min')
Out[3]:
DatetimeIndex(['2011-01-01 00:00:00', '2011-01-01 02:20:00',
               '2011-01-01 04:40:00', '2011-01-01 07:00:00',
               '2011-01-01 09:20:00', '2011-01-01 11:40:00',
               '2011-01-01 14:00:00', '2011-01-01 16:20:00',
               '2011-01-01 18:40:00', '2011-01-01 21:00:00'],
              dtype='datetime64[ns]', freq='140T')
In [4]:
pd.date_range('2011-01-01 00:00:00', periods=10, freq='1D10U')
Out[4]:
DatetimeIndex(['2011-01-01 00:00:00', '2011-01-02 00:00:00.000010',
               '2011-01-03 00:00:00.000020', '2011-01-04 00:00:00.000030',
               '2011-01-05 00:00:00.000040', '2011-01-06 00:00:00.000050',
               '2011-01-07 00:00:00.000060', '2011-01-08 00:00:00.000070',
               '2011-01-09 00:00:00.000080', '2011-01-10 00:00:00.000090'],
              dtype='datetime64[ns]', freq='86400000010U')
In [8]:
pd.date_range(start='1/1/2018', periods=5, tz='Asia/Hong_Kong')
Out[8]:
DatetimeIndex(['2018-01-01 00:00:00+08:00', '2018-01-02 00:00:00+08:00',
               '2018-01-03 00:00:00+08:00', '2018-01-04 00:00:00+08:00',
               '2018-01-05 00:00:00+08:00'],
              dtype='datetime64[ns, Asia/Hong_Kong]', freq='D')
In [9]:
pd.date_range(start='2017-01-01', end='2017-01-04', closed=None)
Out[9]:
DatetimeIndex(['2017-01-01', '2017-01-02', '2017-01-03', '2017-01-04'], dtype='datetime64[ns]', freq='D')
In [10]:

pd.date_range(start='2017-01-01', end='2017-01-04', closed='left')
Out[10]:
DatetimeIndex(['2017-01-01', '2017-01-02', '2017-01-03'], dtype='datetime64[ns]', freq='D')
In [11]:

pd.date_range(start='2017-01-01', end='2017-01-04', closed='right')
Out[11]:
DatetimeIndex(['2017-01-02', '2017-01-03', '2017-01-04'], dtype='datetime64[ns]', freq='D')

日期闭合的坑

上面最后三个例子分别使用 closed=‘right’ closed=‘left’ closed=None 演示了三种闭合情况,没发现有坑,但是问题出在日期格式上。演示的日期格式都是’YYYY-mm-dd’,但我们应用中经常遇到的是 ‘YYYY-mm-dd HH:MM:SS’,好,我们再来看个例子:

In [12]:
pd.date_range(start='2020-01-17 09:00:00', end='2020-01-19 08:59:59', closed=None)
Out[12]:
DatetimeIndex(['2020-01-17 09:00:00', '2020-01-18 09:00:00'], dtype='datetime64[ns]', freq='D')

咦?closed=None是两边闭合,返回的日期应该是包含2020-01-19才对呀?再试一下右闭合看是不是更好用:

In [13]:
pd.date_range(start='2020-01-17 09:00:00', end='2020-01-19 08:59:59', closed=None)
Out[13]:
DatetimeIndex(['2020-01-18 09:00:00'], dtype='datetime64[ns]', freq='D')

咦?右闭合2020-01-17没有了正常,仍然没有2020-01-19?右闭没有闭合???
其实不是右边没有闭合,我们再来试一下:

In [14]:
pd.date_range(start='2020-01-17 09:00:00', end='2020-01-19 09:00:00', closed=None)
Out[14]:
DatetimeIndex(['2020-01-18 09:00:00', '2020-01-19 09:00:00'], dtype='datetime64[ns]', freq='D')

正常闭合了!!仔细的朋友看出来了,开始的时间都是 09:00:00,不闭合的原因是结束日期的时间是08:59:59,改成大于 09:00:00 就会闭合!原来闭合的前提条件是满足24小时!!!

解决方案:

其实很简单,只有知道了这个问题所在,那么在使用pd.date_range的时候,使用参数normalize = True就可以了 比如:

In [15]:
pd.date_range(start='2020-01-17 09:00:00', end='2020-01-19 08:59:59', normalize=True,closed=None)
Out [15]:
DatetimeIndex(['2020-01-17', '2020-01-18', '2020-01-19'], dtype='datetime64[ns]', freq='D')
原创文章 12 获赞 20 访问量 1473

猜你喜欢

转载自blog.csdn.net/wuwei_201/article/details/104876897