python datetime 模块_定义 一个timedelta-程序员宅基地

技术标签: python  datetime  

timedelta

timedelta的实例化

一个timedalta对象代表了一个时间差,当两个datedatetime进行相减操作时会返回一个timedelta对象,或者,我们也可以手动对其进行实例化,其构造函数的原型如下:

class datetime.timedelta([days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]])

其中,所有的参数都是可选的,并且默认为0,一般情况下,我们常用的是其中三个参数dayssecondsmicroseconds,如果我们传递了其他的几个参数值,python会帮助我们自动转换成上面三个参数,转换的规则是:

  • 1 millisecond(毫秒) 转换成 1000 microseconds(微秒)
  • 1 minute 转换成 60 seconds
  • 1 hour 转换成 3600 seconds
  • 1 week转换成 7 days

如果我们在实例化的时候直接传递的是上面三个参数值,那么也要注意下它们的取值范围:

  • 0 <= microseconds < 1000000
  • 0 <= seconds < 3600*24 (一天的秒数)
  • -999999999 <= days <= 999999999

那么,如果我们在传递这三个参数的时候超出了这个范围会有什么问题吗,答案是不一定,例如:

>>> tmp = datetime.timedelta(seconds=86400)
>>> tmp.days
1
>>> tmp.seconds
0

可以看到,如果超过范围,python是会帮我们自动转换的,但是如果days参数超出范围会有什么结果呢?

>>> ee = datetime.timedelta(days=1000000000)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: days=1000000000; must have magnitude <= 999999999

所以,只有days是不能超出范围的,否则会抛出OverflowError异常。

在实例化的时候,参数不仅仅可以是整数,也可以是浮点数、正数或者负数,当参数为负数的时候,要特别注意,因为生成的样式也许与我们设想的不太一致

>>> tmp = datetime.timedelta(microseconds=-1)
>>> tmp.days, tmp.seconds, tmp.microseconds
(-1, 86399, 999999)

所以,我们传递参数的时候,尽量避免传递负数的情况,同样,我们也应该极力避免传递的参数为浮点数,我们在使用的时候一般以秒作为单位就能满足99%的需求了。

timedelta的运算

+ 操作

>>> t1 = datetime.timedelta(seconds=60)
>>> t2 = datetime.timedelta(seconds=30)
>>> t3 = t1 + t2
>>> t3.seconds
90

- 操作

>>> t4 = t1 -t2
>>> t4.seconds
30

* 操作

>>> t5 = t1 * 2
>>> t5
datetime.timedelta(0, 120)
>>> t6 = t1 * 0
>>> t6
datetime.timedelta(0)

///操作

>>> t7 = t1 / 3
>>> t7
datetime.timedelta(0, 20)
>>> t7 = t1 / 7
>>> t7
datetime.timedelta(0, 8, 571428)
>>> t7 = t1 // 7
>>> t7
datetime.timedelta(0, 8, 571428)

注意这里的被除数不能是0,否则会抛出ZeroDivisionError

比较操作

>>> t1 > t2
True
>>> t1 < t2
False
>>> t1 == t2
False
>>> t1 == 60
False
>>> t1 != 60
True
>>> t1 > 60
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't compare datetime.timedelta to int

可以看到,两个timedelta对象可以直接进行比较操作,而一个timedelta对象与一个非timedelta对象进行==!=操作时总是返回False,而进行><操作则会抛出TypeError

其他操作

>>> +t1
datetime.timedelta(0, 60)
>>> -t1
datetime.timedelta(-1, 86340)

// 返回的格式为[D day[s], ][H]H:MM:SS[.UUUUUU]
>>> str(t1)
'0:01:00'
>>> t1
datetime.timedelta(0, 60)
>>> str(-t1)
'-1 day, 23:59:00'

>>> repr(t1)
'datetime.timedelta(0, 60)'

其他

在2.7版本后,新增了一个方法timedelta.total_seconds()用于计算秒数,它等价于(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6

>>> t1
datetime.timedelta(0, 60)
>>> t1.total_seconds()
60.0

date

一个date对象代表使用年、月、日表示的时间,我们可以只用年、月、日三个值直接构造一个date对象,且这三个参数缺一不可,它们的取值范围如下

  • MINYEAR <= year <= MAXYEAR
  • 1 <= month <= 12
  • 1 <= day <= 给定年月的天数

如果我们传递的参数超出这个范围,将会抛出ValueError异常。除了手动传入年、月、日来构造date对象外,系统还提供了静态方法,我们可以使用这些静态方法来方便的得到一个date对象

  • date.today()
    返回当前的本地时间,等价于date.fromtimestamp(time.time())

  • date.fromtimestamp(timestamp)

当得到date对象后,就可以直接访问它的年、月、日属性了

>>> today = date.today()
>>> today
datetime.date(2016, 9, 1)
>>> today.year
2016
>>> today.month
9
>>> today.day
1

运算与比较操作

>>> delta = timedelta(days=7)
>>> future = today + delta
>>> future
datetime.date(2016, 9, 8)
>>> future - delta
datetime.date(2016, 9, 1)
>>> future - today
datetime.timedelta(7)
>>> future > today
True

date可以作为字典的key,并且,所有的date对象都会被认为是True的,也就是 if date 这个判断永远是成立的。

实例方法

  • date.replace(year, month, day)
>>> d = date(2002, 12, 31)
>>> d
datetime.date(2002, 12, 31)
>>> d.replace(day=26)
datetime.date(2002, 12, 26)
  • date.weekday()
    返回一周的礼拜几,用int值表示,从0开始
  • date.isoweekday()
    返回一周的礼拜几,用int值表示,从1开始
  • date.isoformat()
>>> d.isoformat()
'2002-12-31'

datetime

datetime从字面意思上看是datetime的结合,而实际上也是包含了这两个对象的全部信息,我们可以手动构造datetime对象,也可以使用系统提供的静态方法,当我们手动构造的时候,必须要传入yearmonthday三个参数,他们的取值范围与上面讲到的date对象一致。

我们在处理时间问题时,始终无法回避的是时区问题,在python中,使用datetime.tzinfo来表示时区,但这是一个抽象基类,python也并没帮我们实现任意的时区,因此,我们首先来看下在不涉及时区的时候datetime都有哪些用法,然后我们会创建一个本地时区,也就是东八区,来说明datetime如何与tzinfo结合使用。

datetime对象的创建

我们可以通过指定年月日的形式来手动创建一个datetime实例

>>> cur = datetime(year=2016, month=9, day=2)
>>> cur
datetime.datetime(2016, 9, 2, 0, 0)

也可以直接通过静态方法来获的

>>> datetime.today()
datetime.datetime(2016, 9, 2, 17, 50, 21, 810692)
>>> datetime.now()
datetime.datetime(2016, 9, 2, 17, 50, 34, 89763)

这两个方法都会返回一个本地当前时间,也就是上面的两个写法是等效的,但是要注意的是,now()方法可以传入时区信息,我们稍后再一起讨论。

除了上面的方法,我们还可以通过时间戳来获取一个对象

>>> datetime.fromtimestamp(time.time())
datetime.datetime(2016, 9, 2, 17, 54, 56, 65907)

我们这里同样暂不考虑时区的问题。
除了通过时间戳获取datetime实例外,我们还可以通过一个格式化的时间字符串来获得实例,这个方法同样是不带时区信息的

>>> datetime.strptime('2016-09-02 18:00:00', '%Y-%m-%d %H:%M:%S')
datetime.datetime(2016, 9, 2, 18, 0)

既然一个datetime对象包含了datetime的所有信息,那么能不能通过这两对象来生成一个datetime实例呢,答案是肯定的

>>> d = date(year=2016, month=9, day=2)
>>> d
datetime.date(2016, 9, 2)
>>> t = time(hour=18, minute=14)
>>> t
datetime.time(18, 14)
>>> datetime.combine(d, t)
datetime.datetime(2016, 9, 2, 18, 14)

现在datetime也有了,我们总要在它身上做点什么吧,能做什么呢?

常用方法介绍

有了datetime对象之后,我们就可以获得对应的datetime对象了

>>> today = datetime.today()
>>> today.date()
datetime.date(2016, 9, 2)
>>> today.time()
datetime.time(18, 30, 10, 304536)

那如果我希望得到下个月的今天,该怎么做呢?方法有多种,但是最方便的是直接把月份进行加一操作(不考虑跨年和日期超过月份最大值的情况),这个时候replace函数就派上用场了

>>> next_month = today.replace(month=today.month+1)
>>> next_month
datetime.datetime(2016, 10, 2, 18, 30, 10, 304536)

replace()方法允许我们对datetime的任意字段进行替换,并返回一个新的datetime对象,这个新的对象在其他字段上与原有对象保持一致。

除此之外,还有一个比较常用的方法strftime(),通过它可以格式化成我们希望的样式

>>> next_month.strftime('%Y-%m-%d %H:%M:%S')
'2016-10-02 18:30:10'

还有一种情况,是我们希望将一个datetime对象转成时间戳,很遗憾的是python并没直接提供这个方法,但是提供了一个timetuple()方法,它返回一个time.struct_time对象,通过它我们可以构造出时间戳了

>>> dd = datetime.today()
>>> tt = time.mktime(dd.timetuple())
>>> print int(tt)
1472816083

时区的定义

python中给我们提供了datetime.tzinfo这一抽象的基类,如果我们想使用时区,则必须继承这个类来实现自己的时区定义。我们先来看下都有哪些方法可能需要我们来实现

  • tzinto.utcoffset(self, dt)

这个方法返回本地时间与UTC时间的时差,我们知道,我们国家使用的是东八区,也就是比世界协调时间(UTC)/格林尼治时间(GMT)快8小时的时区,因此我们可以如下实现这个方法

def utcoffset(self, dt):
    return timedelta(hours=8)
  • tzinfo.dst(self, dt)

这个方法主要是考虑到一些采用夏令时的国家,在固定月份来调整时间,而我们国家是没有采用夏令时,所以直接返回0

def dst(self, dt):
    return timedelta(0)

而对于采纳了夏令时的国家,则需要把夏令时考虑进去

def dst(self, dt):
    # Code to set dston and dstoff to the time zone's DST
    # transition times based on the input dt.year, and expressed
    # in standard local time.  Then

    if dston <= dt.replace(tzinfo=None) < dstoff:
        return timedelta(hours=1)
    else:
        return timedelta(0)

对于这些国家,我还要修改utcoffset函数,将夏令时的偏移量考虑进去

def utcoffset(self, dt):
    return timedelta(hours=N) + self.dst(dt)
  • tzinfo.tzname(self, dt)

这个方法用来返回时区的名称,没有太多可说的

一般情况下,我们只要实现上面三个方法就可以了,例如我们可以这样定义一个UTC时区和我们所在的东八区

ZERO = timedelta(0)
HOUR = timedelta(hours=1)

class UTC(tzinfo):
    """UTC"""

    def utcoffset(self, dt):
        return ZERO

    def tzname(self, dt):
        return "UTC"

    def dst(self, dt):
        return ZERO


class GMT8(tzinfo):
    """东八区""

    def utcoffset(self, dt):
        return HOUR * 8

    def tzname(self, dt):
        return 'GMT-8'

    def dst(self, dt):
        return ZERO

除了我们自己来定义时区外,我们还可以使用pytz这个模块,通过easy_install命令直接安装即可。

datetime与时区的结合使用

我们上面已经介绍了在不考虑时区因素的时候,datetime的一些简单用法,接下来看下加入时区后,有哪些不一样的地方,以及我们需要注意的地方。

我们在上面提到了类方法now,在不考虑时区的时候,它的作用和类方法today基本是一致的,我们也可以在使用now的时候传递一个tzinfo,如下的两种方式是等效的

today = datetime.today()
today = today.replace(tzinfo=GMT8())
// 等效于
today = datetime.now(GMT8())

除了now()方法外,系统还提供了utcnow()方法,这个方法没有参数,返回的是UTC的时间,但是要注意的是,这个方法创建的datetime对象同样是不带时区信息的。

到目前为止,我们都还不知道时区到底有什么作用,假设说我们现在有这样的需求:在数据库中记录的时间全部采用UTC时间,而在展示的时候需要转换成本地时间。我们在查库后,一些ORM(例如:SQLAlchemy)会自动帮我们将时间值转化成datetime对象,但这些datetime都是不带时区信息的,如果我们想转化成本地时间则必须要创建本地的时区

today = datetime.utcnow()
today = today.replace(tzinfo=UTC())
print today //2016-09-06 06:47:42.665574+00:00

today = today.astimezone(GMT8())
print today //2016-09-06 14:47:42.665574+08:00

如上所示,系统提供了datetime.astimezone(tz)方法,使用这个方法可以在各个时区之间来回转换时间。这里有两点需要注意:

  • 如果datetime对象本身没有包含时区信息,调用这个方法会抛出ValueError,并提示astimezone() cannot be applied to a naive datetime
  • replace(tzinfo=...)方法只会替换tzinfo的值,并不会更改时分秒等时间信息

最后,还有两个通过时间戳获取datetime的类方法,datetime.fromtimestamp(timestamp[, tz])datetime.utcfromtimestamp(timestamp)utcfromtimestamp得到的是一个UTC时间,并且不带tzinfo信息,除此之外,两者并无太大区别。

到这里,datetime模块的大部分方法就介绍完了,还有一些我们不是很常用的方法,大家可以自行看看文档了解下就好。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/aiyaya2/article/details/96893726

智能推荐

Cadence 16.3 手记(2012/08/25再次验证_orcad capture16.3环境变量-程序员宅基地

文章浏览阅读106次。破解方法百度搜索吧,一搜一大堆,此处简要记述我安装的要点:注意:安装前禁止杀毒软件和防火墙1:首先安装lm,遇到license,取消,结束;2:建立环境变量:注意格式,temp什么的云云不需要调整win7系统建立环境变量:computer-properties-advancedsystemsetting--Env-Vari..._orcad capture16.3环境变量

linux usb摄像头驱动程序,Linux系统下USB摄像头驱动开发-程序员宅基地

文章浏览阅读251次。Linux系统下USB摄像头驱动开发摘要:介绍了在Iinux系统下开发符合Video for Linux标准的USB摄像头驱动的方法,并对该标准提出“不间断采集”的改进思路,配合双URB、双帧缓冲等方法,提高采集速度。关键词:Linux设备驱动 USB摄像头 Video for Linux 不间断采集USB摄像头以其良好的性能和低廉的价格得到广泛应用。同时因其灵活、方便的特性,易于集成到嵌入式系统..._嵌入式linux usb摄像头驱动使能

Android6.0自带文件管理器无法打开apk_android documentui 无法打开apk文件-程序员宅基地

文章浏览阅读9.7k次。Android从6.0开始在设置中自带了一个文件浏览器,在6.0之前系统是不自带的,但是这个文件管理器不能打开apk文件,不能安装app。那是因为代码里面没有对APK文件做识别处理,下面这个补丁可以帮你搞定.diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/package_android documentui 无法打开apk文件

ListView中item删除动画效果_android 动态删除指定的listview的item-程序员宅基地

文章浏览阅读1.8w次。在android中listview控件使用的比较多,dans_android 动态删除指定的listview的item

MVC过滤器介绍_php mvc 过滤器-程序员宅基地

文章浏览阅读256次。MVC过滤器:是一种面向切面的编程思想编写逻辑的时候不会影响到主逻辑面向切面的编程主要是为了降低耦合度过滤器的使用与否,修改配置就行,非常方便,不会影响原有的逻辑MVC的作用域:全局过滤器: FilterConfig里边去添加一条控制器级别 使用特性方式加入控制器上面 action级别 使用特性方式加入Action上面MVC过滤器的分类:Action级别的过滤器:请求所有的action都会进入该过滤器,继承IActio..._php mvc 过滤器

OpenHarmony/HarmonyOS三方库使用指导_ohpm三方库的包依赖在-程序员宅基地

文章浏览阅读590次,点赞10次,收藏10次。1 方式一:在Terminal窗口中,执行如下命令安装三方包,DevEco Studio会自动在工程的oh-package.json5中自动添加三方包依赖、1:通过访问Gitee网站获取。_ohpm三方库的包依赖在

随便推点

invalid command ‘bdist_wheel‘_invalid license command 'bdist_wheel-程序员宅基地

文章浏览阅读620次。在linux ubuntu中安装uwsgi时报error: invalid command ‘bdist_wheel’解决方案:pip install wheel然后再安装uwsgi即可pip install uwsgi_invalid license command 'bdist_wheel

Acunetix WVS11安装和扫描_allow remote access to acunetix-程序员宅基地

文章浏览阅读3k次。任务一 、Acunetix WVS安装1、双击下载的安装包进行安装,点击“next”下一步2、同意授权点击“next”下一步3、输入邮箱和密码,点击“next”下一步4、勾选“Allow remote access to Acunetix” 点击“next”下一步5、勾选“Create a desktop icon” 点击“next”下一步6、点击“install”进行安装..._allow remote access to acunetix

qt如何修改文本编辑器字体及颜色_qt编辑器修改字体-程序员宅基地

文章浏览阅读4.9k次。qt如何修改文本编辑器字体及颜色 菜单栏 工具-> 选项->文本编辑器。_qt编辑器修改字体

计算机组成原理解读——CPU_cup芯片是由门电路组成的吗-程序员宅基地

文章浏览阅读1.5k次。计算机原理解读——CPUCPU全名Central Processing Unit,又叫中央处理器,主要由运算器和控制器组成1、门电路CPU属于超大规模集成电路,CPU就是电路1.1、基础门电路基础门电路是实现基础逻辑运算的门电路基础门电路主要有:与、或、非、或非、异或、与非1.2、算术逻辑单元(ALU)也叫操作元件(组合逻辑元件),他是在执行指令阶段,进行算数运算和逻辑运算的组合逻辑电路ALU包括基础门电路实现的逻辑运算,以及由基础门电路组合成的算术运算,如:半加器:与+异或全加器_cup芯片是由门电路组成的吗

OpenCL学习笔记——整体流程(向量相加)_opencl 向量相加-程序员宅基地

文章浏览阅读465次。该函数把要执行的 Kernel 函数放在指定的命令队列中,global_work_size大小(线程索引空间)必须指定,local_work_size大小可以指定,也可以为空。命令队列中的命令 (kernel 函数)可能是同步的,也可能是异步的,它们的执行顺序可以是有序的,也可以是乱序的。大家可以去网上下载一下“GPU-Z”这个软件,这个软件可以查看电脑的显卡对OpenCL的支持性,以及支持的版本,我的电脑的如下图可见,有√就是支持的(当你把鼠标移动到单词周围会有适配版本提示)。..._opencl 向量相加

通俗理解LightGBM算法_lightgbm的learning rate怎么影响结果-程序员宅基地

文章浏览阅读3.8k次,点赞3次,收藏16次。什么是 LightGBM,如何实现它? 如何微调参数?_lightgbm的learning rate怎么影响结果

推荐文章

热门文章

相关标签