金融量化学习---Python, MySQL, Pandas

这里用来记录一些在金融领域,尤其是银行相关的资金、债券、票据中应用到的数据管理与分析, 编程等心得或笔记,以及个人的一点小小兴趣(易经八卦、藏密禅修)等

导航

Date运算之一 -- datetime 相关及str转date等运算

python 中 date与str转化及date之间的运算

获取当前日期

获取今天(现在时间)

import datetime

# 创建日期对象
date = datetime.date(2023, 6, 11)
print(date)      # 2023-06-11

# 创建时间对象
time = datetime.time(13, 25, 45)
print(time)      # 13:25:45

# 创建时间对象
dt = datetime.datetime(2023, 6, 11, 13, 25, 45)
print(dt)        # 2023-06-11 13:25:45
 
# 获取今天(现在时间)
today = datetime.datetime.today()
today = datetime.date.today()

# 昨天
yesterday = today - datetime.timedelta(days=1)
# 明天
tomorrow = today + datetime.timedelta(days=1)

Python获取当前年/月/日

import datetime
datetime.datetime.now().year
datetime.datetime.now().month
datetime.datetime.now().day

从0.15.0开始(2014年9月底发布),现在可以使用新的.dt访问器进行以下操作:

df['Year'] = df['Date'].dt.year
df['Month'] = df['Date'].dt.month
df['Day'] = df['Date'].dt.day

str、timestamp 和datetime转换

str转datetime

import datetime

str = "20180805"
str2date = datetime.datetime.strptime(str,"%Y%m%d")  #字符串转化为date形式
date2str=str2date.strftime("%Y%m%d") #date形式转化为str

str = '2012-11-19'
date_time = datetime.datetime.strptime(str,'%Y-%m-%d') #注意str的格式要与'%Y-%m-%d'相匹配。

#因为import datetime,而 datetime下面还有一个 datetime,所以要引用它,就得用datetime.datetime
#如果用 from datetime import datetime, 就可以写成datetime.strptime(str,"%Y%m%d")

datetime转str

date_time = datetime.datetime(2012,11,19,0,0)
str = date_time.strftime('%Y-%m-%d')
#得到:'2012-11-19'

str转为timestamp (pandas里的日期时间数据格式)

settle_date = '2021-06-02' 
pd.to_datetime(settle_date) 直接将字符格式的日期,转化为timestamps格式

datetime格式转为timestamps格式

date0 = datetime.strptime(settle_date, "%Y-%m-%d")  #转为datetime格式
date0 = pd.Timestamp(date0)  #datetime格式转为timestamps格式

#或者:把一列datetime型数字转为timestamp
date_col = pd.to_datetime(date_col) 

timestamps转为datetime

month_list =  pd.date_range('2020-01-01','2020-06-30',freq='M')

DatetimeIndex(['2020-01-31', '2020-02-29', '2020-03-31', '2020-04-30',
               '2020-05-31', '2020-06-30'],
              dtype='datetime64[ns]', freq='M')

list(month_list)
Out: 
[Timestamp('2020-01-31 00:00:00', freq='M'),
 Timestamp('2020-02-29 00:00:00', freq='M'),
 Timestamp('2020-03-31 00:00:00', freq='M'),
 Timestamp('2020-04-30 00:00:00', freq='M'),
 Timestamp('2020-05-31 00:00:00', freq='M'),
 Timestamp('2020-06-30 00:00:00', freq='M')]

list(month_list.values)
Out: 
[numpy.datetime64('2020-01-31T00:00:00.000000000'),
 numpy.datetime64('2020-02-29T00:00:00.000000000'),
 numpy.datetime64('2020-03-31T00:00:00.000000000'),
 numpy.datetime64('2020-04-30T00:00:00.000000000'),
 numpy.datetime64('2020-05-31T00:00:00.000000000'),
 numpy.datetime64('2020-06-30T00:00:00.000000000')]

list(month_list.date)
Out: 
[datetime.date(2020, 1, 31),
 datetime.date(2020, 2, 29),
 datetime.date(2020, 3, 31),
 datetime.date(2020, 4, 30),
 datetime.date(2020, 5, 31),
 datetime.date(2020, 6, 30)]

list(month_list)[0]
Out: Timestamp('2020-01-31 00:00:00', freq='M')

list(month_list.values)[0]
Out[: numpy.datetime64('2020-01-31T00:00:00.000000000')

list(month_list)[0].date()
Out: datetime.date(2020, 1, 31)

date与datetime互转

from datetime import datetime, date

# 获取datetime
now = datetime.now()

# 获取date
today = date.today()

# date 转 datetime
print('date 转 datetime:',datetime.combine(today, datetime.min.time()))

# datetime转date
print('datetime转date:',now.date())

将pandas的一列从datetime格式更改为date格式:

df[col] = pd.to_datetime(df[col]).dt.date

timestamp类型的特性

settle_date = '2021-06-02' 
#方法一
date0 = datetime.strptime(settle_date, "%Y-%m-%d")  #转为datetime格式
date0 = pd.Timestamp(date0)  #datetime格式转为timestamps格式
#方法二
date0 = pd.to_datetime(settle_date) 直接将字符格式的日期,转化为timestamps格式

date0
Out: Timestamp('2021-06-02 00:00:00')

print(date0)
2021-06-02 00:00:00

dir(date0)
Out:
['asm8', 'astimezone', 'ceil', 'combine', 'ctime', 'date', 'day', 'day_name', 'day_of_week', 'day_of_year', 'dayofweek', 'dayofyear', 'days_in_month', 'daysinmonth', 'dst', 'floor', 
'fold', 'freq', 'freqstr', 'fromisocalendar', 'fromisoformat', 'fromordinal', 'fromtimestamp', 'hour', 'is_leap_year', 'is_month_end', 'is_month_start', 'is_quarter_end', 'is_quarter_start',
 'is_year_end', 'is_year_start', 'isocalendar', 'isoformat', 'isoweekday', 'max', 'microsecond', 'min', 'minute', 'month', 'month_name', 'nanosecond', 'normalize', 'now', 'quarter', 
'replace', 'resolution', 'round', 'second', 'strftime', 'strptime', 'time', 'timestamp', 'timetuple', 'timetz', 'to_datetime64', 'to_julian_date', 'to_numpy', 'to_period', 'to_pydatetime',
 'today', 'toordinal', 'tz', 'tz_convert', 'tz_localize', 'tzinfo', 'tzname', 'utcfromtimestamp', 'utcnow', 'utcoffset', 'utctimetuple', 'value', 'week', 'weekday', 'weekofyear', 'year']

#其中常用的:
date0.date()
Out[0]: datetime.date(2021, 6, 2)

date0.day_name()
Out[1]: 'Wednesday'

date0.year
Out[2]: 2021

date0.month_name()
Out[3]: 'June'

date0.week
Out[4]: 22

date0.today()
Out[5]: Timestamp('2021-06-03 10:53:14.977925')

date0.to_datetime64()
Out[6]: numpy.datetime64('2021-06-02T00:00:00.000000000')

date0.isocalendar()
Out[7]: (2021, 22, 3)

date0.to_julian_date()
Out[8]: 2459367.5

date0.value
Out[9]: 1622592000000000000

date0.to_pydatetime()
Out[10]: datetime.datetime(2021, 6, 2, 0, 0)

date0.isoformat()
Out[11]: '2021-06-02T00:00:00'

date0.is_month_end
Out[12]: False

date0.is_leap_year
Out[11]: False

date之间的运算

pre_date = date + datetime.datetime.timedelta(days=-1)

datetime 两个日期的计算

在当前日期上加一天

tom = today + datetime.timedelta(days=1)
tom
Out[2]: datetime.date(2020, 11, 3)

指定两日,计算差

from datetime import datetime
cur_day = datetime(2019, 7, 30)
next_day = datetime(2019, 7, 31)
print((next_day - cur_day).days) 

import datetime
# 计算日期的差值
d1 = datetime.date(2023, 6, 11) 
d2 = datetime.date(1990, 6, 8)
delta = d1 - d2
print(delta.days)    # 12056

# 计算时间的差值
t1 = datetime.datetime(2023, 6, 11, 19, 25)
t2 = datetime.datetime(2023, 6, 11, 17, 30)
delta = t1 - t2
print(delta.seconds)    # 6900

d1=datetime.datetime.strptime(starttime,"%Y%m%d")
d2=datetime.datetime.strptime(endtime,"%Y%m%d")
diff_days=d1-d2
print diff_days

Calendar模块

获取某月日历

Calendar模块有很广泛的方法用来处理年历和月历,例如打印某月的月历:

import calendar
cal = calendar.month(2016, 1)
print "以下输出2016年1月份的日历:"
print cal

以上实例输出结果:

以下输出2016年1月份的日历:

January 2016

Mo Tu We Th Fr Sa Su
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

monthrange()计算当月天数

以下代码通过导入 calendar 模块来计算每个月的天数:

import calendar
monthRange = calendar.monthrange(2016,9)
print(monthRange)

执行以上代码输出结果为:
(3, 30)

输出的是一个元组,第一个元素是所查月份的第一天对应的是星期几(0-6),第二个元素是这个月的天数。以上实例输出的意思为 2016 年 9 月份的第一天是星期四,该月总共有 30 天。

mdays计算当月天数

想知道每个月的天数,可用calendar.mdays:

import calendar
print(calendar.mdays[9])

执行以上代码输出结果为:
[0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

时间处理 dateutil 模块

dateutil模块主要有两个函数,parser和rrule。
其中parser是根据字符串解析成datetime,而rrule则是根据定义的规则来生成datetime。

1、 parser

parser是根据字符串解析成datetime,字符串可以很随意,可以用时间日期的英文单词,可以用横线、逗号、空格等做分隔符。
没指定时间默认是0点,没指定日期默认是今天,没指定年份默认是今年。

from dateutil.parser import parse

parse("2018-10-21")
datetime.datetime(2018, 10, 21, 0, 0)

parse("20181021")
datetime.datetime(2018, 10, 21, 0, 0)

parse("2018/10/21")
datetime.datetime(2018, 10, 21, 0, 0)

parse("10-21")
datetime.datetime(2018, 10, 21, 0, 0)

parse("10/21")
datetime.datetime(2018, 10, 21, 0, 0)

只有月日时,parser会将分隔符前面的数字解析为月份,后面的为日
当有年份时,在前面的月份超出范围时,会自动判断哪个是月哪个是日

parse("3/8")
datetime.datetime(2018, 3, 8, 0, 0)

parse("8/3")
datetime.datetime(2018, 8, 3, 0, 0)

parse("3-8")
datetime.datetime(2018, 3, 8, 0, 0)

parse("8-3")
datetime.datetime(2018, 8, 3, 0, 0)

parse("21/10")
ValueError: month must be in 1..12

parse("3/8/2018")
datetime.datetime(2018, 3, 8, 0, 0)

parse("8/3/2018")
datetime.datetime(2018, 8, 3, 0, 0)

parse("2018/3/8")
datetime.datetime(2018, 3, 8, 0, 0)

parse("3/15/2018")
datetime.datetime(2018, 3, 15, 0, 0)

当前面的月份超过12时,parser会自动识别月和日

parse("15/3/2018")
datetime.datetime(2018, 3, 15, 0, 0)

分隔符改成"-"也一样

parse("15-3-2018")
datetime.datetime(2018, 3, 15, 0, 0)

但是当年份放在前面时,只能按年-月-日的顺序

parse("2018/15/3")
ValueError: month must be in 1..12

当分隔符为逗号时,只有月-日时,要把月放在前面
有年份时,年份要放在后面

parse("3,15")
datetime.datetime(2018, 3, 15, 0, 0)

只识别到了前面的日,月将本月11月作为默认月

parse("15,3")
datetime.datetime(2018, 11, 15, 0, 0)

parse("3,15,2018")
datetime.datetime(2018, 3, 15, 0, 0)

parse("2018,3,15")
ValueError: ('Unknown string format:', '2018,3,15')

parser还可以识别英文的月、日

parse("Mar 15")
datetime.datetime(2018, 3, 15, 0, 0)

没有空格也可以

parse("Mar15")
datetime.datetime(2018, 3, 15, 0, 0)

parse("15 Mar")
datetime.datetime(2018, 3, 15, 0, 0)

parse("Mar 1st")
datetime.datetime(2018, 3, 1, 0, 0)

parse("Mar 15 2018")
datetime.datetime(2018, 3, 15, 0, 0)

parse("2018 Mar15")
datetime.datetime(2018, 3, 15, 0, 0)

2、rrule

rrule(self, freq, dtstart=None, interval=1, wkst=None,count=None, until=None, bysetpos=None,bymonth=None, bymonthday=None, byyearday=None, byeaster=None,byweekno=None, byweekday=None, byhour=None, byminute=None, bysecond=None,cache=False)

freq:可以理解为单位。可以是 YEARLY, MONTHLY, WEEKLY,DAILY, HOURLY, MINUTELY, SECONDLY。即年月日周时分秒
dtstart,until:是开始和结束时间
wkst:周开始时间
interval:间隔
count:指定生成多少个
byxxx:指定匹配的周期。比如byweekday=(MO,TU)则只有周一周二的匹配。byweekday可以指定MO,TU,WE,TH,FR,SA,SU。即周一到周日。
from dateutil import rrule

生成一个连续的日期列表
list(rrule.rrule(rrule.DAILY,dtstart=parse('2018-11-1'),until=parse('2018-11-5')))
[datetime.datetime(2018, 11, 1, 0, 0), 
datetime.datetime(2018, 11, 2, 0, 0), 
datetime.datetime(2018, 11, 3, 0, 0), 
datetime.datetime(2018, 11, 4, 0, 0), 
datetime.datetime(2018, 11, 5, 0, 0)]

间隔一天
list(rrule.rrule(rrule.DAILY,interval=2,dtstart=parse('2018-11-1'),until=parse('2018-11-5')))
[datetime.datetime(2018, 11, 1, 0, 0), 
datetime.datetime(2018, 11, 3, 0, 0), 
datetime.datetime(2018, 11, 5, 0, 0)]

只保留前3个元素
list(rrule.rrule(rrule.DAILY,count=3,dtstart=parse('2018-11-1'),until=parse('2018-11-5')))
[datetime.datetime(2018, 11, 1, 0, 0), 
datetime.datetime(2018, 11, 2, 0, 0), 
datetime.datetime(2018, 11, 3, 0, 0)]

只要周一的
list(rrule.rrule(rrule.DAILY,byweekday=rrule.MO,dtstart=parse('2018-11-1'),until=parse('2018-11-5')))
[datetime.datetime(2018, 11, 5, 0, 0)]

只要周六和周日的
list(rrule.rrule(rrule.DAILY,byweekday=(rrule.SA,rrule.SU),dtstart=parse('2018-11-1'),until=parse('2018-11-5')))
[datetime.datetime(2018, 11, 3, 0, 0), 
datetime.datetime(2018, 11, 4, 0, 0)]

以月为间隔
list(rrule.rrule(rrule.MONTHLY,dtstart=parse('2018-3-15'),until=parse('2018-7-30')))
[datetime.datetime(2018, 3, 15, 0, 0), 
datetime.datetime(2018, 4, 15, 0, 0), 
datetime.datetime(2018, 5, 15, 0, 0), 
datetime.datetime(2018, 6, 15, 0, 0), 
datetime.datetime(2018, 7, 15, 0, 0)]

计算时间差
rrule可计算出两个datetime对象间相差的年月日等时间数量

两个日期相差10天

rrule.rrule(rrule.DAILY,dtstart=parse('2018-11-1'),until=parse('2018-11-10')).count()
10

某个日期到今天相差多少天
rrule.rrule(rrule.DAILY,dtstart=parse('2018-11-1'),until=datetime.date.today()).count()
10
两个日期相差几个月
前一个月为m月,后一个月为n月,当日期不满整月时,差的月数按n-m算,当日期满整月后,差的月数按n-m+1算。
差的年数同月数的情况一样。
例子如下:

rrule.rrule(rrule.MONTHLY,dtstart=parse('2018-3-15'),until=parse('2018-11-10')).count()
8
rrule.rrule(rrule.MONTHLY,dtstart=parse('2018-3-15'),until=parse('2018-11-20')).count()
9

rrule.rrule(rrule.YEARLY,dtstart=parse('2016-3-15'),until=parse('2018-2-10')).count()
2
rrule.rrule(rrule.YEARLY,dtstart=parse('2016-3-15'),until=parse('2018-3-15')).count()
3

使用 dateutil 之 rrule

计算间隔月

import datetime
from dateutil import rrule

month_sep = rrule.rrule(rrule.MONTHLY, dtstart=datetime.date(2020, 6, 29), until=datetime.date(2021, 1, 1))
for sep_date in list(month_sep):
    print(sep_date) # 打印间隔的每个月
print(month_sep.count()) # 计数,看之间有多少个月份

计算间隔日

import datetime
from dateutil import rrule

day_sep = rrule.rrule(rrule.DAILY, dtstart=datetime.date(2020, 6, 29), until=datetime.date(2021, 1, 1))
for sep_date in list(day_sep):
    print(sep_date)
print(day_sep.count())

计算间隔年

import datetime
from dateutil import rrule

year_sep = rrule.rrule(rrule.YEARLY, dtstart=datetime.date(2020, 6, 29), until=datetime.date(2021, 1, 1))
for sep_date in list(year_sep):
    print(sep_date)
print(year_sep.count())

再来看一个汇总的例子:

import datetime as dt
from dateutil import parser
from dateutil import rrule
######################################## date形式天数差
d1 = '2019-07-26'
d2 = '2020-08-01'
######## 法1
# (1)先将字符串-->时间格式date
date1 = dt.datetime.strptime(d1, "%Y-%m-%d").date()  ##datetime.date(2018, 1, 6)
date2 = dt.datetime.strptime(d2, "%Y-%m-%d").date()  ##datetime.date(2018, 1, 9)
# (2)计算两个日期date的天数差
Days = (date2 - date1).days
######## 法2
Days = (parser.parse(d2) - parser.parse(d1)).days
######## 法3
Days = rrule.rrule(rrule.DAILY, dtstart = date1, until = date2).count()

######################################## datetime形式天数差
date1 = dt.datetime(2019, 7, 26, 15, 35, 10)  
date2 = dt.datetime(2020, 8, 1, 18, 30, 20) 
######## 法1
Days = (date2 - date1).days
######## 法2
Days = (parser.parse(d2) - parser.parse(d1)).days
######## 法3
Days = rrule.rrule(rrule.DAILY, dtstart = date1, until = date2).count() 

# 秒数差 
Seconds = (date2 - date1).seconds  
# 毫秒数
Microseconds = (date2 - date1).microseconds  

#周数差
Weeks = rrule.rrule(rrule.WEEKLY, dtstart = date1, until = date2).count() 
#月数差
Months = rrule.rrule(rrule.MONTHLY, dtstart = date1, until = date2).count()  
#年数差
Years = rrule.rrule(rrule.YEARLY, dtstart = date1, until = date2).count()  

有需要的直接?️复制下列代码

#!/usr/bin/env python
#-*-coding:utf-8
# author zhaoli

import datetime
import time


def str2date(str,date_format="%Y%m%d"):
    date = datetime.datetime.strptime(str, date_format)
    return date

def date2str(date,date_formate = "%Y%m%d"):
    str = date.strftime(date_formate)
    return str

def date_delta(date,gap,formate = "%Y%m%d"):
    date = str2date(date)
    pre_date = date + datetime.timedelta(days=-gap)
    pre_str = date2str(pre_date,formate)  # date形式转化为str
    return pre_str

def str2timestamp(str,timestamp_len=10):
    date_array = time.strptime(str,"%Y-%m-%d %H:%M:%S")
    timestamp = int(time.mktime(date_array))
    if timestamp_len==13:
        timestamp *=1000
    return timestamp

posted on 2020-10-27 17:08  chengjon  阅读(6531)  评论(0编辑  收藏  举报