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