python datetime.date 和数据库date_Python成为专业人士笔记-date 对象、time 对象及datetime用法深度剖析...
“專業(yè)人士筆記”系列目錄:創(chuàng)帆云:Python成為專業(yè)人士筆記--強(qiáng)烈建議收藏!每日持續(xù)更新!?zhuanlan.zhihu.com
將字符串解析為對(duì)應(yīng)時(shí)區(qū)的datetime對(duì)象
Python 3.2+在將字符串解析為datetime對(duì)象時(shí)支持%z格式:
import datetime
dt = datetime.datetime.strptime("2016-04-15T08:27:18-0500", "%Y-%m-%dT%H:%M:%S%z")
# 其中時(shí)間字符串中最后的 -0500 ,為UTC的偏移量(如果時(shí)區(qū)是本地的,則是空字符串),其格式一般是+HHMM 或 -HHMM 格式
對(duì)于Python2x版本(版本已停止維護(hù)),可以使用諸如dateutil這樣的外部庫,這使得將帶時(shí)區(qū)的字符串解析為datetime對(duì)象變得很方便:
注:如python云環(huán)境中沒有下面的包,請(qǐng)登錄SSH并使用命令安裝:
python -m pip install python-dateutil
#然后運(yùn)行代碼:
import dateutil.parser
dt = dateutil.parser.parse("2016-04-15T08:27:18-0500")
dt變量現(xiàn)在是一個(gè)帶有以下值的datetime對(duì)象:
datetime.datetime(2016, 4, 15, 8, 27, 18, tzinfo=tzoffset(None, -18000))
從中文對(duì)話中提取datetime
注:如python3云環(huán)境中沒有下面的包,請(qǐng)登錄SSH并使用命令安裝:
python -m pip install python-dateutil
可以使用dateutil解析器以“模糊”模式從文本中提取日期 , 不被識(shí)別為日期一部分的字符串的組件將被忽略
from dateutil.parser import parse
dt = parse("截止2012-12-31日,上午8:21", fuzzy=True)
print(dt)
# 輸出2012-12-31 08:21:00
# 其它的可以自己嘗試
構(gòu)建對(duì)應(yīng)時(shí)區(qū)的datetimes
默認(rèn)情況下,所有的datetime對(duì)象都是本地的,但是對(duì)于程序開發(fā)尤其面向用戶可能包含國際用戶時(shí),往往的做法是,在程序數(shù)據(jù)庫里存儲(chǔ)標(biāo)準(zhǔn)的世界時(shí)區(qū)(UTC),然后針對(duì)不同地區(qū)用戶的訪問動(dòng)態(tài)根據(jù)當(dāng)?shù)貢r(shí)區(qū)生成當(dāng)?shù)貢r(shí)間。
要使它們強(qiáng)制對(duì)應(yīng)特定的時(shí)區(qū),必須附加一個(gè)tzinfo對(duì)象,該對(duì)象提供UTC偏移量和時(shí)區(qū)的函數(shù)
補(bǔ)充:什么是UTC時(shí)間,UTC時(shí)間和本地時(shí)區(qū)的區(qū)別
世界協(xié)調(diào)時(shí)間(Universal Time Coordinated,UTC),GPS 系統(tǒng)中有兩種時(shí)間區(qū)分,一為UTC,另一為LT(地方時(shí))兩者的區(qū)別為時(shí)區(qū)不同,UTC就是0時(shí)區(qū)的時(shí)間,(LocalTime)地方時(shí)為本地時(shí)間,如北京為早上八點(diǎn)(東八區(qū)),UTC時(shí)間就為零點(diǎn),時(shí)間比北京時(shí)晚八小時(shí),以此計(jì)算即可.
—時(shí)區(qū)偏移的修正
相對(duì)UTC有固定偏移量的時(shí)區(qū),在Python 3.2+中,datetime模塊提供了 timezone 類,即 tzinfo的具體實(shí)現(xiàn),它帶有一個(gè)timedelta和一個(gè)可選的name參數(shù):
from datetime import datetime, timedelta, timezone
JST = timezone(timedelta(hours=+9))
#timedelta函數(shù)用做對(duì)時(shí)間增減,這里相對(duì)UTC加了9個(gè)小時(shí),即UTC+9的日本時(shí)間
dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=JST)
print(dt)
#tzinfo參數(shù)指定時(shí)區(qū)為日本UTC+9
#輸出對(duì)象:2015-01-01 12:00:00+09:00
print(dt.tzname())
#輸出UTC+09:00
dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=timezone(timedelta(hours=9), 'JST'))
print(dt.tzname)
#輸出'JST'
對(duì)于Python 3.2之前的版本,需要使用第三方庫,比如dateutil,這里不做詳細(xì)介紹
計(jì)算兩個(gè)日期的時(shí)間差
timedelta模塊可以方便地計(jì)算時(shí)間差:
from datetime import datetime, timedelta
now = datetime.now()
then = datetime(2016, 5, 23)
# 和 datetime.datetime(2016, 05, 23, 0, 0, 0) 效果一樣, 在創(chuàng)建新的datetime對(duì)象時(shí),指定時(shí)間是可選的
delta = now-then
#輸出:1436 days, 12:43:25.994771,即時(shí)間間隔1436天
#注意:delta這時(shí)已經(jīng)是datetime.timedelta的數(shù)據(jù)類型
也可以只輸出局部:
print(delta.days)
#輸出60天
print(delta.seconds)
#輸出40826秒
如果要基于當(dāng)前日期得到n天后、n天前的日期,我們可以使用:
n天之后獲取函數(shù):
def get_n_days_after_date(date_format="%d %B %Y", add_days=120):
date_n_days_after = datetime.datetime.now() + timedelta(days=add_days)
return date_n_days_after.strftime(date_format)
n天之前獲取函數(shù):
def get_n_days_before_date(self, date_format="%d %B %Y", days_before=120):
date_n_days_ago = datetime.datetime.now() - timedelta(days=days_before)
return date_n_days_ago.strftime(date_format)
datetime對(duì)象的基本用法
datetime模塊包含三種主要的對(duì)象類型:date、time和datetime
import datetime
#Date 對(duì)象
today = datetime.date.today()
new_year = datetime.date(2017, 01, 01) #datetime.date(2017, 1, 1)也可以
#Time 對(duì)象
noon = datetime.time(12, 0, 0) #datetime.time(12, 0)也可以
#Datetime 對(duì)象
millenium_turn = datetime.datetime(2000, 1, 1, 0, 0, 0) #datetime.datetime(2000, 1, 1, 0, 0)也可以
#獲取當(dāng)前時(shí)間 datetime
now = datetime.datetime.now()
#注意:這些日期及時(shí)間對(duì)象的算術(shù)操作只在相同的數(shù)據(jù)類型中受支持,對(duì)不同類型的實(shí)例執(zhí)行簡單的算術(shù)操作將導(dǎo)致數(shù)據(jù)類型錯(cuò)誤
#如用中午減去今天操作:
noon-today
報(bào)錯(cuò):
Traceback (most recent call last):
File "", line 1, in
TypeError: unsupported operand type(s) for -: 'datetime.time' and 'datetime.date'
However, it is straightforward to convert between types.
解析: datetime.time和datime.date兩個(gè)數(shù)據(jù)類型不能互減
#像這樣處理(兩個(gè)都是datatime對(duì)象了)
datetime.datetime(today.year, today.month, today.day) - millenium_turn)
或者:
datetime.datetime.combine(today, noon) - millenium_turn)
簡單的日期計(jì)算
日期不是孤立存在的,通常情況下,你需要找出日期之間的間隔時(shí)間,或者確定明天的日期,而這些都可以使用timedelta對(duì)象來完成
import datetime
today = datetime.date.today()
#print('今天:', today)
yesterday = today - datetime.timedelta(days=1)
#print('昨天:', yesterday)
tomorrow = today + datetime.timedelta(days=1)
#print('明天:', tomorrow)
#print('明天和昨天的時(shí)間差是:', tomorrow - yesterday)
#在你的python3云環(huán)境中試一下,看是什么效果
打印的結(jié)果是:
今天 : 2016-04-15
昨天 : 2016-04-14
明天 : 2016-04-16
明天和昨天的時(shí)間差是: 2 days, 0:00:00
從timestamp 時(shí)間戳轉(zhuǎn)到datetime
import time
from datetime import datetime
seconds_since_epoch=time.time()
#這是一個(gè)時(shí)間戳 如,1469182681.709
utc_date=datetime.utcfromtimestamp(seconds_since_epoch) #返回一個(gè)datetime對(duì)象,datetime.datetime(2016, 7, 22, 10, 18, 1,
709000)
用日歷模塊精確的增減月份
使用日歷模塊 calendar 可以很好的處理:
#精確獲取下一個(gè)月的日期
import calendar
from datetime import date
#定義函數(shù),傳入日期及需要增加幾個(gè)月的參數(shù)
def monthdelta(date, delta):
m, y = (date.month+delta) % 12, date.year + ((date.month)+delta-1) // 12
#注:代碼使用了內(nèi)聯(lián)代碼賦值 , 其中 % 為取余數(shù) ,//為相除后取整數(shù)
if not m:
m = 12
d = min(date.day, calendar.monthrange(y, m)[1])
return date.replace(day=d,month=m, year=y)
#調(diào)用函數(shù)獲取
next_month = monthdelta(date.today(), 1)
#打印輸出下一個(gè)月的日期
當(dāng)然,其實(shí)有一種很簡單計(jì)算下一個(gè)月日期的方法,只是不精確:
from datetime import date
next_month =date.today()+datetime.timedelta(days=30)
#這個(gè)原理是直接用timedelta將當(dāng)前日期向后延長30天后日期并返回,只能用于粗略計(jì)算場景
使用最少的庫解析任意的ISO 8601時(shí)間戳
Python只對(duì)解析ISO 8601時(shí)間戳提供有限的支持,對(duì)于strptime,你需要確切地知道它的格式。一個(gè)復(fù)雜的情況是,datetime轉(zhuǎn)化字符串后是一個(gè)ISO 8601時(shí)間戳,并用空格作為分隔符和6位分?jǐn)?shù) ,如下:
str(datetime.datetime(2016, 7, 22, 9, 25, 59, 555555))
#輸出'2016-07-22 09:25:59.555555'
但秒后面時(shí)間戳如果為0,則沒有小數(shù)部分輸出:
str(datetime.datetime(2016, 7, 22, 9, 25, 59, 0))
#輸出'2016-07-22 09:25:59'
這兩個(gè)時(shí)間的解析需要不同的strptime格式,strptime根本不支持解析中包含符號(hào)為“ : ”的分鐘時(shí)區(qū),因此可以解析(2016-07-22 09:25:59+0300),但標(biāo)準(zhǔn)格式(2016-07-22 09:25:59+03:00)則不能。
有一個(gè)名為iso8601的專用庫,它可以正確地解析ISO 8601時(shí)間戳
import iso8601
iso8601.parse_date('2016-07-22 09:25:59')
#datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=)
iso8601.parse_date('2016-07-22 09:25:59+03:00')
#datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=)
iso8601.parse_date('2016-07-22 09:25:59Z')
#datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=)
iso8601.parse_date('2016-07-22T09:25:59.000111+03:00')
#datetime.datetime(2016, 7, 22, 9, 25, 59, 111, tzinfo=)
如果沒有設(shè)置時(shí)區(qū),則使用iso8601,解析日期默認(rèn)為UTC。可以使用默認(rèn)區(qū)域關(guān)鍵字參數(shù)更改默認(rèn)區(qū)域。值得注意的是,如果這是None而不是缺省值,那么那些沒有顯式時(shí)區(qū)的時(shí)間戳將作為原始日期時(shí)間返回 :
iso8601.parse_date('2016-07-22T09:25:59', default_timezone=None)
datetime.datetime(2016, 7, 22, 9, 25, 59)
iso8601.parse_date('2016-07-22T09:25:59Z', default_timezone=None)
datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=)
補(bǔ)充: ISO 8601
ISO 8601是日期和時(shí)間的表示方法,全稱為《數(shù)據(jù)存儲(chǔ)和交換形式·信息交換·日期和時(shí)間的表示方法》。目前最新為第三版ISO8601:2004,第一版為ISO8601:1988,第二版為ISO8601:2000。 它規(guī)定了日期時(shí)間的各種表示方法,它的一般原則:日期和時(shí)間值按從最大到最小的時(shí)間單位排序:年,月(或周),日,小時(shí),分鐘,秒和秒的分?jǐn)?shù)。因此,表示的字典順序?qū)?yīng)于時(shí)間順序,除了涉及負(fù)年份的日期表示。這允許日期自然地由例如文件系統(tǒng)排序。
每個(gè)日期和時(shí)間值都有一個(gè)固定的位數(shù),必須用前導(dǎo)零填充。
日期時(shí)間表示只能有數(shù)字或少數(shù)特殊字符組成(如“ – ”,“:”,“T”,“W”和“Z”),不允許出現(xiàn)地方寫法,如“1月”或“星期四”等。
表示可以采用兩種格式之一完成 – 具有最少數(shù)量分隔符的基本格式或添加了分隔符的擴(kuò)展格式以增強(qiáng)人類可讀性。該標(biāo)準(zhǔn)指出“應(yīng)以純文本形式避免使用基本格式”。日期值(年,月,周和日)之間使用的分隔符是連字符,而冒號(hào)用作時(shí)間值(小時(shí),分鐘和秒)之間的分隔符。例如,2009年第1個(gè)月的第6天可以以擴(kuò)展格式寫為“2009-01-06”,或者以基本格式簡稱為“20090106”而不含糊不清。
為了降低準(zhǔn)確度,可以從任何日期和時(shí)間表示中刪除任意數(shù)量的值,但是從最小到最重要的順序。例如,“2004-05”是有效的ISO 8601日期,表示2004年5月(第5個(gè)月)。此格式永遠(yuǎn)不會(huì)代表2004年未指定月份的第5天,也不代表從2004年進(jìn)入2005年。
ISO 8601使用24小時(shí)制。HH:MM:SS.SSS,HH:MM:SS,HH:MM,HH為合規(guī)的時(shí)間格式。
如果沒有指定與UTC關(guān)系則假定是本地時(shí)間,為安全的跨時(shí)區(qū)通訊,應(yīng)制定與UTC關(guān)系。若時(shí)間是UTC則在時(shí)間后面加Z表示,如“09:30UTC”表示為09:30Z”或“0930Z”。其它時(shí)區(qū)時(shí)間則將與UTC的偏移量附加到時(shí)間后面,格式為±[hh]:[mm],±[hh] [mm]或±[hh],如“北京時(shí)間09:30”表示為”09:30+08:00”或“ 09:30+0800 ” 或“ 09:30+08 ”。
用字母T分割日期和時(shí)間。如20180703T224426Z或2018-07-03T22:44:26Z 。
獲取 ISO 8601 timestamp 時(shí)間戳
沒有時(shí)區(qū),只有微秒
from datetime import datetime
datetime.now().isoformat()
輸出: '2016-07-31T23:08:20.886783'
有時(shí)區(qū),有微秒
from datetime import datetime
from dateutil.tz import tzlocal
datetime.now(tzlocal()).isoformat()
輸出: '2016-07-31T23:09:43.535074-07:00'
有時(shí)區(qū),沒有微秒
from datetime import datetime
from dateutil.tz import tzlocal
datetime.now(tzlocal()).replace(microsecond=0).isoformat()
輸出: '2016-07-31T23:10:30-07:00'
遍歷日期對(duì)象
有時(shí),你希望迭代從開始日期到某個(gè)結(jié)束日期的日期范圍,可以使用datetime庫和timedelta對(duì)象來實(shí)現(xiàn) :
import datetime
#每次迭代以天為單位
day_delta = datetime.timedelta(days=1)
start_date = datetime.date.today()
end_date = start_date + 7*day_delta
for i in range((end_date - start_date).days):
print(start_date + i*day_delta)
#程序輸出:
2016-07-21
2016-07-22
2016-07-23
2016-07-24
2016-07-25
2016-07-26
2016-07-27
今天的分享就到這里,禁止轉(zhuǎn)載,違者必究!
總結(jié)
以上是生活随笔為你收集整理的python datetime.date 和数据库date_Python成为专业人士笔记-date 对象、time 对象及datetime用法深度剖析...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DNF中接到了寻找NPC【博肯】的任务,
- 下一篇: python string转int_我用