前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >盘一盘 Python 特别篇 16 - DateTime

盘一盘 Python 特别篇 16 - DateTime

作者头像
用户5753894
发布2020-06-24 11:40:10
6680
发布2020-06-24 11:40:10
举报
文章被收录于专栏:王的机器王的机器

本文含 4064 字,10 图表截屏

建议阅读 22 分钟

0

引言

在 Python 中有一个内置的专门处理“日期时间”的工具包叫做 datetime,而日期 (date) 和时间 (time) 在金融工程中的处处都用得到。

一看日期还不简单,人人都会啊有什么可学的,来来来,先看看下面几个问题。

  1. 为什么美股有时候在北京时间晚上 21:30 开市,有时候在 22:30 开市呢?
  2. 为什么两个相同的日期在不同金融产品 (债券或利率掉期) 计算出来的年限会不一样呢?

第一个问题涉及到时区 (timezone) 和夏令时 (day saving time) 的知识。

第二个问题涉及到日期计数惯例 (daycount convention) 的知识。

这些都是日期中非常细节而又很难捋清的知识点,不在本帖打好日期时间的基础怎么能进一步学习以上知识点呢?

1

日期

和 Python 中其他变量类型一样,日期也可以看成是一种变量。

在没接触过 date 对象之前,日期通常写成字符串形式,如下例用字符串定义了两个现金流日,放在列表中。

代码语言:javascript
复制
cashflow_dates = ["20/3/2020", "20/6/2020"]

日期对象

创建日期很简单,首先从 datetime 包中引入 date 对象。

代码语言:javascript
复制
from datetime import date

用 date() 加上年、月、日三个参数即可定义日期。

代码语言:javascript
复制
cashflow_dates = [ date(2020, 3, 20), date(2020, 6, 20) ]
cashflow_dates
代码语言:javascript
复制
[ datetime.date(2020, 3, 20),
  datetime.date(2020, 6, 20) ]

Python 中万物皆对象,查看对象里的字段和方法 (属性) 用 dir()。

代码语言:javascript
复制
print(dir(cashflow_dates[0]))

对于日期,用字段 .year, .month 和 .day 可获取年、月、日信息,用方法 weekday() 可获取星期几的信息。

代码语言:javascript
复制
print(cashflow_dates[1].year)
print(cashflow_dates[1].month)
print(cashflow_dates[1].day)
print(cashflow_dates[1].weekday())
代码语言:javascript
复制
2020
6
20
5

在 Python 中,星期几和数字的对应关系如下:

  • 0: 星期一 (Monday)
  • 1: 星期二 (Tuesday)
  • 2: 星期三 (Wednesday)
  • 3: 星期四 (Thursday)
  • 4: 星期五 (Friday)
  • 5: 星期六 (Saturday)
  • 6: 星期日 (Sunday)

而 2020 年 6 月 20 日是星期五,对应的数字是 5。

日期运算

日期也可以做一些算术和比较运算,操作的时候把它当作一个数值。

代码语言:javascript
复制
d1 = date(2020, 3, 20)
d2 = date(2020, 6, 20)

我们可以比较两个日期谁前谁后

代码语言:javascript
复制
d1 < d2
代码语言:javascript
复制
True

也可以计算它们之间的“距离”,差多少天或者多少秒。

代码语言:javascript
复制
print(d2 - d1)
代码语言:javascript
复制
92 days, 0:00:00

两个日期对象相减得到的是一个 timedelta 对象,

代码语言:javascript
复制
type(d2 - d1)
代码语言:javascript
复制
datetime.timedelta

看着 timedelta 顾名思义写成数学符号就是 Δt,如果将日期用符号 t 表示,那么 Δt 不就代表日期差吗?用 .days 字段查看具体的天数差。

代码语言:javascript
复制
(d2 - d1).days
代码语言:javascript
复制
92

日期 d2 减去日期 d1 得到 timedelta,那么把 timedelta 加回 d1 应该得到 d2。

首先从 datetime 包中引入 timedelta 对象。

代码语言:javascript
复制
from datetime import timedelta

从上面结果可知 d1 和 d2 相差 92 天,用 timedelta() 对象并设定 days=92 来定义 td,加回 d1 得到 d2。

代码语言:javascript
复制
td = timedelta(days=92)
print(d1 + td)
代码语言:javascript
复制
2020-06-20

日期格式

日期的格式有很多种,在展示中如果不确定用哪种格式,建议用标准格式 .isoformat()。

代码语言:javascript
复制
d = date(2014, 1, 11)
print( type(d), d )
代码语言:javascript
复制
<class 'datetime.date'> 2014-01-11

如果需要特定格式,那么用 strftime(),从其函数名 str-f-time 就可以猜到它是用一个字符串 (are) 来代表时间 (time) 的格式 (f)。

代码语言:javascript
复制
print( d.isoformat() )
代码语言:javascript
复制
2014-01-11

调整日期格式可去 https://strftime.org/ 查看详细信息,比如

  • %Y - 年的全称 (如 2020)
  • %m - 月份的数字形式 (个位数用零填充, 比如 1 填充成 01)
  • %b - 月份的简称 (如 Mar)
  • %d - 天数 (个位数用零填充)
  • %a - 日期的简称 (Wed)

还原 ISO 格式。

代码语言:javascript
复制
print( d.strftime('%Y-%m-%d') )
代码语言:javascript
复制
2014-01-11

自定义格式。

代码语言:javascript
复制
print( d.strftime('%b %d, %Y (%a)') )
代码语言:javascript
复制
Jan 11, 2014 (Sat)

2

日期时间

年、月、日可以组成日期,时、分、秒可以组成时间。日期加上时间才是完整的信息。Python 里对日期时间定义的更细,还带微秒时区

时间对象

和上面 date 对象相对应的是 time 对象,还是从 datetime 包里引入。

代码语言:javascript
复制
from datetime import time

回想上面

date(year, month, day)

类比

time(hour, minute ,second)

来创建时间。

代码语言:javascript
复制
t = time(8, 32, 21)
print( type(t), t )
代码语言:javascript
复制
<class 'datetime.time'> 08:32:21

日期时间对象

但单单一个时间对象没什么还实用价值,一般是联合日期定义一个日期时间 datetime 对象。

datetime 对象里的参数包括年、月、日、时、分、秒、微秒和时区。微秒在高频交易才用得到,时区在下贴细讲。

datetime( year, month, day,

hour, minute, second,

macrosecond, tzinfo )

代码如下:

代码语言:javascript
复制
dt = datetime(2014, 1, 11, 8, 32, 21, 1031)
print( type(dt), dt )
代码语言:javascript
复制
<class 'datetime.datetime'> 2014-01-11 08:32:21.001031

可在 replace() 函数设置年、月、日、时、分、秒、微秒来重设时间。记着重设完要做赋值动作,因为 replace 不是一个原地 (in-place) 动作。

代码语言:javascript
复制
dt_hr = dt.replace(minute=0, second=0, microsecond=0)
print(dt_hr)

日期时间之差

上节已介绍过两个日期对象相减得到一个 timedelta 对象,延伸一下,两个日期时间对象相减得到也是一个 timedelta 对象。

用 datetime 对象来创建女儿和儿子 (姐弟俩) 的生日 (精确到秒)。

代码语言:javascript
复制
daughter_bday = datetime(2014, 1, 11, 8, 32, 21)
son_bday = datetime(2018, 12, 2, 21, 58, 52)

计算他们生日相隔的 timedelta 对象。

代码语言:javascript
复制
duration = son_bday - daughter_bday
type(duration)
代码语言:javascript
复制
datetime.timedelta

姐弟俩相隔 1500000 多秒,1786 天,4.89 年。

代码语言:javascript
复制
print(duration.total_seconds())
print(duration.days)
print(duration.total_seconds()/(3600*24*365))
代码语言:javascript
复制
154358791.0
1786
4.894685153475393

在弟弟生日上加一秒,用 timedelta 对象并设置 seconds=1。

代码语言:javascript
复制
delta1 = timedelta(seconds=1)
print(son_bday)
print(son_bday+delta1)
代码语言:javascript
复制
2018-12-02 21:58:52
2018-12-02 21:58:53

在弟弟生日上加一小时一秒,用 timedelta 对象并设置 hours=2, seconds=1。

代码语言:javascript
复制
delta2 = timedelta(hours=2, seconds=1)
print(son_bday)
print(son_bday+delta2)
代码语言:javascript
复制
2018-12-02 21:58:52
2018-12-02 23:58:53

用 timedelta 对象不仅可以加在日期得到未来的时间,还可以将里面的参数定义复制得到过去的时间。

代码语言:javascript
复制
delta3 = timedelta(weeks=-1)
print(son_bday+delta3)
print(son_bday)
print(son_bday-delta3)
代码语言:javascript
复制
2018-11-25 21:58:52
2018-12-02 21:58:52
2018-12-09 21:58:52

3

总结

Python 中有日期对象 date,时间对象 time,和日期时间对象 datetime。

本帖讲的东西很基础,但它们都是为了理解之后的时区 (timezone)、 夏令时 (day saving time) 和日期计数惯例 (daycount convention) 这些难点。

哦,对了,如果你想知道当前的日期时间,用 .now() 或者 .today()。

代码语言:javascript
复制
print( datetime.now() )
print( datetime.today() )
代码语言:javascript
复制
2020-06-23 15:17:40.522769
2020-06-23 15:17:40.522769

Stay Tuned!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 王的机器 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档