专栏首页王的机器盘一盘 Python 特别篇 16 - DateTime

盘一盘 Python 特别篇 16 - DateTime

本文含 4064 字,10 图表截屏

建议阅读 22 分钟

0

引言

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

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

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

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

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

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

1

日期

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

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

cashflow_dates = ["20/3/2020", "20/6/2020"]

日期对象

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

from datetime import date

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

cashflow_dates = [ date(2020, 3, 20), date(2020, 6, 20) ]
cashflow_dates
[ datetime.date(2020, 3, 20),
  datetime.date(2020, 6, 20) ]

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

print(dir(cashflow_dates[0]))

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

print(cashflow_dates[1].year)
print(cashflow_dates[1].month)
print(cashflow_dates[1].day)
print(cashflow_dates[1].weekday())
2020
6
20
5

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

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

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

日期运算

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

d1 = date(2020, 3, 20)
d2 = date(2020, 6, 20)

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

d1 < d2
True

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

print(d2 - d1)
92 days, 0:00:00

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

type(d2 - d1)
datetime.timedelta

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

(d2 - d1).days
92

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

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

from datetime import timedelta

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

td = timedelta(days=92)
print(d1 + td)
2020-06-20

日期格式

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

d = date(2014, 1, 11)
print( type(d), d )
<class 'datetime.date'> 2014-01-11

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

print( d.isoformat() )
2014-01-11

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

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

还原 ISO 格式。

print( d.strftime('%Y-%m-%d') )
2014-01-11

自定义格式。

print( d.strftime('%b %d, %Y (%a)') )
Jan 11, 2014 (Sat)

2

日期时间

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

时间对象

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

from datetime import time

回想上面

date(year, month, day)

类比

time(hour, minute ,second)

来创建时间。

t = time(8, 32, 21)
print( type(t), t )
<class 'datetime.time'> 08:32:21

日期时间对象

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

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

datetime( year, month, day,

hour, minute, second,

macrosecond, tzinfo )

代码如下:

dt = datetime(2014, 1, 11, 8, 32, 21, 1031)
print( type(dt), dt )
<class 'datetime.datetime'> 2014-01-11 08:32:21.001031

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

dt_hr = dt.replace(minute=0, second=0, microsecond=0)
print(dt_hr)

日期时间之差

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

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

daughter_bday = datetime(2014, 1, 11, 8, 32, 21)
son_bday = datetime(2018, 12, 2, 21, 58, 52)

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

duration = son_bday - daughter_bday
type(duration)
datetime.timedelta

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

print(duration.total_seconds())
print(duration.days)
print(duration.total_seconds()/(3600*24*365))
154358791.0
1786
4.894685153475393

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

delta1 = timedelta(seconds=1)
print(son_bday)
print(son_bday+delta1)
2018-12-02 21:58:52
2018-12-02 21:58:53

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

delta2 = timedelta(hours=2, seconds=1)
print(son_bday)
print(son_bday+delta2)
2018-12-02 21:58:52
2018-12-02 23:58:53

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

delta3 = timedelta(weeks=-1)
print(son_bday+delta3)
print(son_bday)
print(son_bday-delta3)
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()。

print( datetime.now() )
print( datetime.today() )
2020-06-23 15:17:40.522769
2020-06-23 15:17:40.522769

Stay Tuned!

本文分享自微信公众号 - 王的机器(MeanMachine1031),作者:王圣元

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 听说你会玩 Python 系列 2 - 99% 人会做错的题

    题目:在不运行下面代码(Python 3 不是 Python 2)的情况下选择答案。

    用户5753894
  • 盘一盘 Python 系列特别篇 - Collection

    我们在【盘一盘 Python 下】一贴介绍过 5 种类型的容器型(container)数据,分别是字符串(string)、列表(list)、元组(tuple)、...

    用户5753894
  • 盘一盘 Python 系列 1 - 入门篇 (上)

    昨晚见到大神 Aurélien Géron 真人讲 Tensorflow 2.0 的 autograph,会后和他聊天得知他已经搬到新加坡了,而且在这边也有一个...

    用户5753894
  • 3个非常好用的JavaScript日期库

    在写项目的时候,遇到对一些时间的处理,代码写起来是相当的不方便,处理起来很纠结,于是借用JavaScript日期库,用一些前面的大牛总结好的东西,如同锦上添花一...

    王小婷
  • 基础学习python(3)活动是否开始

    原题目是手动输入:星期、时间判断是否活动开始,我在想是不是能够自动获取时间判断是否活动开始

    adventureisoutthere
  • cmake用法

    示例源码 在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:

    用户2929716
  • python: time模块、datetime模块

    JNingWei
  • Python进阶(一)

    MiChong
  • 一日一技:如何在Python项目中挖坑害人

    现在,函数 anyfunc正常运行,但是你会发现, datetime.datetime.now()报错了,如下图所示。

    青南
  • SpringBoot系列之切换log4j日志框架

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明...

    SmileNicky

扫码关注云+社区

领取腾讯云代金券