【2017-09-19】数字日期与时间(二)

日期与时间

  • 简单的日期转化与计算
    执行不同时间的转换与计算,通常用到datetime模块,不可忽略的是其中timedelta。顺便插播一段,时间的处理在日常工作中经常用到,记得最开始的时候,都是自定义一个方法通过时间戳来进行时间计算,直到最近给男朋友写爬虫时,结合之前了解到的datetime模块,才发现timedelta的好处。
>>> a=timedelta(days=2, hours=6)
>>> b = timedelta(hours=4.5)
>>> c=a+b
>>> c.days
2
>>> c.seconds
37800
>>> c.total_seconds()
210600.0
>>> 

   上述提到的爬虫,需求:有一个网站,需要输入起始时间和结束时间以及其他信息,点击下一页、下一页...,提取出每页的内容。
   上述需求暂仅考虑时间部分,为了实现最大自动化,用户可决定下载几天数据。‘几天’就需要用到时间的计算,给出一个当前日期,向前或者向后进行推送。

>>> start_time=datetime(2012, 3, 1)
>>> start_time
datetime.datetime(2012, 3, 1, 0, 0)
>>> next_time=start_time+timedelta(days=1)
>>> next_time
datetime.datetime(2012, 3, 2, 0, 0)
>>> 

   在进行计算时,datetime 会自动处理闰年

>>> a = datetime(2012, 3, 1)
>>> b = datetime(2012, 2, 28)
>>> a-b
datetime.timedelta(2)
>>> (a-b).days
2
>>> c = datetime(2013, 3, 1)
>>> d = datetime(2013, 2, 28)
>>> (c - d).days
1
>>> 

  使用timedelta可以很方便的在日期上做days,hours,seconds等时间计算,如果要计算月份则需要另外的办法。
  更加复杂的日期处理,可使用dateutil模块,许多类似的时间计算可以使用 dateutil.relativedelta()函数代替

  • 计算最后一个周五的日期
    你需要查找星期中某一天最后出现的日期,比如星期五
    示例:求出指定星期几最后出现的日期
      先将开始日期和目标日期映射到星期数组的位置上 (星期一索引为 0),然后通过模运算计算出目标日期要经过多少天才能到达开始日期。然后用开始日期减去那个时间差即得到结果日期。
>>> weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
'Friday', 'Saturday', 'Sunday']
>>> def get_previous_byday(dayname, start_date=None):
    if start_date is None:
        start_date = datetime.today()
        day_num = start_date.weekday()
        day_num_target = weekdays.index(dayname)
        days_ago = (7 + day_num - day_num_target) % 7
        if days_ago == 0:
            days_ago = 7
        target_date = start_date - timedelta(days=days_ago)
        return target_date

    
>>> get_previous_byday('Monday')
datetime.datetime(2017, 9, 18, 11, 6, 2, 863482)
>>> get_previous_byday('Tuesday')
datetime.datetime(2017, 9, 12, 11, 6, 24, 398482)
>>> 
  • 计算当前月份的日期范围
    问题:在当前月份中循环每一天,想找到一个计算这个日期范围的高效方法。
    解决方案:
      在这样的日期上循环并需要事先构造一个包含所有日期的列表。关键是先计算出开始日期和结束日期,然后在你步进的时候使用 datetime.timedelta 对象递增这个日期变量即可。
>>> import calendar
>>> def get_month_range(start_date=None):
    if start_date is None:
        start_date = date.today().replace(day=1)
        _, days_in_month = calendar.monthrange(start_date.year, start_date.month)
    end_date = start_date + timedelta(days=days_in_month)
    return (start_date, end_date)

>>> first_day, last_day = get_month_range()
>>> first_day
datetime.date(2017, 9, 1)
>>> last_day
datetime.date(2017, 10, 1)

  使用 calendar.monthrange() 函数来找出该月的总天数。任何时候只要你想获得日历信息,那么 calendar 模块就非常有用了。 monthrange() 函数会返回包含星期和该月天数的元组。

>>> calendar.monthrange(start_date.year, start_date.month)
(4, 30)
>>> 

  一旦该月的天数已知了,那么结束日期就可以通过在开始日期上面加上这个天数获得。值得注意的是结束日期并不包含在这个日期范围内 (事实上它是下个月的开始日期)。这个和 Python 的 slice 与 range 操作行为保持一致,同样也不包含结尾。可以创建类似内置range()的函数。

>>> for d in date_range(datetime(2012, 9, 1), datetime(2012,10,1),
timedelta(hours=6)):
    print(d)

    
2012-09-01 00:00:00
2012-09-01 06:00:00
2012-09-01 12:00:00
2012-09-01 18:00:00
2012-09-02 00:00:00
2012-09-02 06:00:00
...
  • 字符串转换为日期
    执行 datetime 对象转化成日期字符串或者日期字符串转化成datetime对象
    datetime模块提供了strptime()和strftime()方法供使用,但是考虑到性能,当涉及到处理大量日期的时候,strptime()不建议使用,因为它是使用纯 Python 实现,并且必须处理所有的系统本地设置,性能比想象中差很多。可自定义一个方法代替,比如:
from datetime import datetime
def parse_ymd(s):
year_s, mon_s, day_s = s.split('-')
return datetime(int(year_s), int(mon_s), int(day_s))
  • 结合时区的日期处理
    示例:
>>> d = datetime(2012, 12, 21, 9, 30, 0)
>>> central = timezone('US/Central')
>>> loc_d = central.localize(d)
>>> d
datetime.datetime(2012, 12, 21, 9, 30)
>>> loc_d
datetime.datetime(2012, 12, 21, 9, 30, tzinfo=<DstTzInfo 'US/Central' CST-1 day, 18:00:00 STD>)
>>> 

上述关键是类似US/Central怎么得到?
为了查找,可以使用 ISO 3166 国家代码作为关键字去查阅字典pytz.country timezones

>>> import pytz
>>> pytz.country_timezones['IN']
['Asia/Kolkata']
>>> pytz.country_timezones['AE']
['Asia/Dubai']
>>> 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容