• 【Day41】Python之路——Time时间模块


    time与datetime模块

    在Python中,通常有这几种方式来表示时间:

    • 时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。
    • 格式化的时间字符串(Format String)
    • 结构化的时间(struct_time --元组):struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)

    #导入时间模块
    >>>import time
    
    #时间戳
    >>>time.time()
    1500875844.800804
    
    #时间字符串
    >>>time.strftime("%Y-%m-%d %X")
    '2017-07-24 13:54:37'
    >>>time.strftime("%Y-%m-%d %H-%M-%S")
    '2017-07-24 13-55-04'
    
    #时间元组:localtime将一个时间戳转换为当前时区的struct_time
    time.localtime()
    time.struct_time(tm_year=2017, tm_mon=7, tm_mday=24,
              tm_hour=13, tm_min=59, tm_sec=37, 
                     tm_wday=0, tm_yday=205, tm_isdst=0)
    
    #格式化的时间字符串:'2017-02-15 11:40:53'
    print(time.strftime("%Y-%m-%d %X")) 
    
    #本地时区的struct_time
    print(time.localtime()) 
    
     #UTC时区的struct_time
    print(time.gmtime())   

    小结:时间戳是计算机能够识别的时间;时间字符串是人能够看懂的时间;元组则是用来操作时间的

     几种格式之间的转换

     

    #时间戳-->结构化时间

    #时间戳-->结构化时间
    #time.gmtime(时间戳)    #UTC时间,与英国伦敦当地时间一致
    #time.localtime(时间戳) #当地时间。例如我们现在在北京执行这个方法:与UTC时间相差8小时,UTC时间+8小时 = 北京时间 
    >>>time.gmtime(1500000000)
    time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=2, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0)
    >>>time.localtime(1500000000)
    time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=10, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0)
    
    #结构化时间-->时间戳 
    #time.mktime(结构化时间)
    >>>time_tuple = time.localtime(1500000000)
    >>>time.mktime(time_tuple)
    1500000000.0
    结构化时间-->字符串时间
    #结构化时间-->字符串时间
    #time.strftime("格式定义","结构化时间")  结构化时间参数若不传,则现实当前时间
    >>>time.strftime("%Y-%m-%d %X")
    '2017-07-24 14:55:36'
    >>>time.strftime("%Y-%m-%d",time.localtime(1500000000))
    '2017-07-14'
    
    #字符串时间-->结构化时间
    #time.strptime(时间字符串,字符串对应格式)
    >>>time.strptime("2017-03-16","%Y-%m-%d")
    time.struct_time(tm_year=2017, tm_mon=3, tm_mday=16, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=75, tm_isdst=-1)
    >>>time.strptime("07/24/2017","%m/%d/%Y")
    time.struct_time(tm_year=2017, tm_mon=7, tm_mday=24, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=205, tm_isdst=-1)

    #结构化时间 --> %a %b %d %H:%M:%S %Y串
    #time.asctime(结构化时间) 如果不传参数,直接返回当前时间的格式化串
    >>>time.asctime(time.localtime(1500000000))
    'Fri Jul 14 10:40:00 2017'
    >>>time.asctime()
    'Mon Jul 24 15:18:33 2017'
    
    #时间戳 --> %a %d %d %H:%M:%S %Y串
    #time.ctime(时间戳)  如果不传参数,直接返回当前时间的格式化串
    >>>time.ctime()
    'Mon Jul 24 15:19:07 2017'
    >>>time.ctime(1500000000)
    'Fri Jul 14 10:40:00 2017' 
    #时间加减
    import datetime
    
    # print(datetime.datetime.now()) #返回 2016-08-19 12:47:03.941925
    #print(datetime.date.fromtimestamp(time.time()) )  # 时间戳直接转成日期格式 2016-08-19
    # print(datetime.datetime.now() )
    # print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间+3天
    # print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间-3天
    # print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间+3小时
    # print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间+30分
    
    
    #
    # c_time  = datetime.datetime.now()
    # print(c_time.replace(minute=3,hour=2)) #时间替换
    datetime模块

    问题

    你需要执行简单的时间转换,比如天到秒,小时到分钟等的转换。

    可以创建一个timedelta 实例

    >>> from datetime import timedelta
    >>> a = timedelta(days=2, hours=6)
    >>> b = timedelta(hours=4.5)
    >>> c = a + b
    >>> c.days
    2
    >>> c.seconds
    37800
    >>> c.seconds / 3600
    10.5
    >>> c.total_seconds() / 3600
    58.5
    >>>

    表示指定的日期和时间

    先创建一个datetime 实例然后使用标准的数学
    运算来操作它们。

    >>> from datetime import datetime
    >>> a = datetime.now()
    >>> a.year
    2018
    >>> a.day
    19
    >>> print(a + timedelta(days=10))
    2018-01-29 18:03:18.837018
    >>> b = datetime(2012,12,21)
    >>> d = a-b
    >>> d
    datetime.timedelta(1855, 64998, 837018)
    >>> d.days
    1855
    >>> now = datetime.today()
    >>> now
    datetime.datetime(2018, 1, 19, 18, 6, 7, 306654)
    >>> print(now)
    2018-01-19 18:06:07.306654

    注意 :当以datetime 进行获取时间时,获取天数使用 obj.day  ,但是当两个日期进行相减时,获取天数使用 obj.days

    >>> e = datetime.now()
    >>> f = datetime.now()
    >>> e
    datetime.datetime(2018, 1, 19, 18, 22, 30, 380882)
    >>> f
    datetime.datetime(2018, 1, 19, 18, 22, 33, 405055)
    >>> a = f+e
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unsupported operand type(s) for +: 'datetime.dat
    >>> a = f-e
    >>> a.seconds
    3
    >>> a.days
    0
    >>> now = datetime.today()
    >>> print(now)
    2012-12-21 14:54:43.094063
    >>> print(now + timedelta(minutes=10))
    2012-12-21 15:04:43.094063 注意: 两个时间只能相减,只能获取到时间的天与秒 天:obj.days 秒:obj.seconds

    在计算的时候,需要注意的是datetime 会自动处理闰年。比如:

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

    复杂的日期操作,比如处理时区,模糊时间范围,节假日计算等等,可以考虑使
    用dateutil 模块
    许多类似的时间计算可以使用dateutil.relativedelta() 函数代替。但是,有一
    点需要注意的就是,它会在处理月份(还有它们的天数差距) 的时候填充间隙。看例子
    最清楚:

    >>> a = datetime(2012, 9, 23)
    >>> a + timedelta(months=1)
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: 'months' is an invalid keyword argument for this function
    >>>
    >>> from dateutil.relativedelta import relativedelta
    >>> a + relativedelta(months=+1)
    datetime.datetime(2012, 10, 23, 0, 0)
    >>> a + relativedelta(months=+4)
    datetime.datetime(2013, 1, 23, 0, 0)
    >>>
    >>> # Time between two dates
    >>> b = datetime(2012, 12, 21)
    >>> d = b - a
    >>> d
    datetime.timedelta(89)
    >>> d = relativedelta(b, a)
    >>> d
    relativedelta(months=+2, days=+28)
    >>> d.months
    2
    >>> d.days
    28
    >>>

    问题
    你需要查找星期中某一天最后出现的日期,比如星期五。

    from datetime import datetime, timedelta
    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
    View Code

     讨论
        上面的算法原理是这样的:先将开始日期和目标日期映射到星期数组的位置上(星
      期一索引为0),然后通过模运算计算出目标日期要经过多少天才能到达开始日期。然
      后用开始日期减去那个时间差即得到结果日期。

    如果你要像这样执行大量的日期计算的话,你最好安装第三方包python-dateutil
    来代替。比如,下面是是使用dateutil 模块中的relativedelta() 函数执行同样的计
    算:

    >>> from datetime import datetime
    >>> from dateutil.relativedelta import relativedelta
    >>> from dateutil.rrule import *
    >>> d = datetime.now()
    >>> print(d)
    2012-12-23 16:31:52.718111
    >>> # Next Friday
    >>> print(d + relativedelta(weekday=FR))
    2012-12-28 16:31:52.718111
    >>>
    >>> # Last Friday
    >>> print(d + relativedelta(weekday=FR(-1)))
    2012-12-21 16:31:52.718111

    问题:你的代码需要在当前月份中循环每一天,想找到一个计算这个日期范围的高效方法。

    解决方案
    在这样的日期上循环并需要事先构造一个包含所有日期的列表。你可以先计算出
    开始日期和结束日期,然后在你步进的时候使用datetime.timedelta 对象递增这个日
    期变量即可。
    下面是一个接受任意datetime 对象并返回一个由当前月份开始日和下个月开始日
    组成的元组对象。

    from datetime import datetime, date, 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)

    有了这个就可以很容易的在返回的日期范围上面做循环操作了:

    >>> a_day = timedelta(days=1)
    >>> first_day, last_day = get_month_range()
    >>> while first_day < last_day:
    ... print(first_day)
    ... first_day += a_day
    ...
    2012-08-01
    2012-08-02
    2012-08-03
    2012-08-04

    讨论
    上面的代码先计算出一个对应月份第一天的日期。一个快速的方法就是使用date
    或datetime 对象的replace() 方法简单的将days 属性设置成1 即可。replace() 方
    法一个好处就是它会创建和你开始传入对象类型相同的对象。所以,如果输入参数是一
    个date 实例,那么结果也是一个date 实例。同样的,如果输入是一个datetime 实
    例,那么你得到的就是一个datetime 实例。
    然后,使用calendar.monthrange() 函数来找出该月的总天数。任何时候只要你
    想获得日历信息,那么calendar 模块就非常有用了。monthrange() 函数会返回包含
    星期和该月天数的元组。
    一旦该月的天数已知了,那么结束日期就可以通过在开始日期上面加上这个天数
    获得。有个需要注意的是结束日期并不包含在这个日期范围内(事实上它是下个月的开
    始日期)。这个和Python 的slice 与range 操作行为保持一致,同样也不包含结尾。
    为了在日期范围上循环,要使用到标准的数学和比较操作。比如,可以利用
    timedelta 实例来递增日期,小于号< 用来检查一个日期是否在结束日期之前。
    理想情况下,如果能为日期迭代创建一个同内置的range() 函数一样的函数就好
    了。幸运的是,可以使用一个生成器来很容易的实现这个目标:

    def date_range(start, stop, step):
    while start < stop:
    yield start
    start += step

    下面是使用这个生成器的例子:

    >>> 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

    字符串转换为日期

    问题
      你的应用程序接受字符串格式的输入,但是你想将它们转换为datetime 对象以便
    在上面执行非字符串操作。
    解决方案
      使用Python 的标准模块datetime 可以很容易的解决这个问题。比如:

    >>> from datetime import datetime
    >>> text = '2012-09-20'
    >>> y = datetime.strptime(text, '%Y-%m-%d')
    >>> z = datetime.now()
    >>> diff = z - y
    >>> diff
    datetime.timedelta(3, 77824, 177393)
    >>>

    讨论
      datetime.strptime() 方法支持很多的格式化代码,比如%Y 代表4 位数年份,%m
    代表两位数月份。还有一点值得注意的是这些格式化占位符也可以反过来使用,将日期
    输出为指定的格式字符串形式。
      比如,假设你的代码中生成了一个datetime 对象,你想将它格式化为漂亮易读形
    式后放在自动生成的信件或者报告的顶部:

    >>> z
    datetime.datetime(2012, 9, 23, 21, 37, 4, 177393)
    >>> nice_z = datetime.strftime(z, '%A %B %d, %Y')
    >>> nice_z
    'Sunday September 23, 2012'

      还有一点需要注意的是,strptime() 的性能要比你想象中的差很多,因为它是使
    用纯Python 实现,并且必须处理所有的系统本地设置。如果你要在代码中需要解析大
    量的日期并且已经知道了日期字符串的确切格式,可以自己实现一套解析方案来获取
    更好的性能。比如,如果你已经知道所以日期格式是YYYY-MM-DD ,你可以像下面这样
    实现一个解析函数:

    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))

      实际测试中,这个函数比datetime.strptime() 快7 倍多。如果你要处理大量的
    涉及到日期的数据的话,那么最好考虑下这个方案!

    结合时区的日期操作

    问题
      你有一个安排在2012 年12 月21 日早上9:30 的电话会议,地点在芝加哥。而你
    的朋友在印度的班加罗尔,那么他应该在当地时间几点参加这个会议呢?
    解决方案
      对几乎所有涉及到时区的问题,你都应该使用pytz 模块。这个包提供了Olson 时
    区数据库,它是时区信息的事实上的标准,在很多语言和操作系统里面都可以找到。
    pytz 模块一个主要用途是将datetime 库创建的简单日期对象本地化。比如,下
    面如何表示一个芝加哥时间的示例:

    >>> from datetime import datetime
    >>> from pytz import timezone
    >>> d = datetime(2012, 12, 21, 9, 30, 0)
    >>> print(d)
    2012-12-21 09:30:00
    >>> central = timezone('US/Central')
    >>> loc_d = central.localize(d)
    >>> print(loc_d)
    2012-12-21 09:30:00-06:00

      一旦日期被本地化了,它就可以转换为其他时区的时间了。为了得到班加罗尔对应
    的时间,你可以这样做:

    >>> # Convert to Bangalore time
    >>> bang_d = loc_d.astimezone(timezone('Asia/Kolkata'))
    >>> print(bang_d)
    2012-12-21 21:00:00+05:30

    处理本地化日期的通常的策略先将所有日
    期转换为UTC 时间,并用它来执行所有的中间存储和操作。比如:

    >>> print(loc_d)
    2013-03-10 01:45:00-06:00
    >>> utc_d = loc_d.astimezone(pytz.utc)
    >>> print(utc_d)
    2013-03-10 07:45:00+00:00

      一旦转换为UTC,你就不用去担心跟夏令时相关的问题了。因此,你可以跟之前
    一样放心的执行常见的日期计算。当你想将输出变为本地时间的时候,使用合适的时区
    去转换下就行了。比如:

    >>> later_utc = utc_d + timedelta(minutes=30)
    >>> print(later_utc.astimezone(central))
    2013-03-10 03:15:00-05:00

      当涉及到时区操作的时候,有个问题就是我们如何得到时区的名称。比如,在这个
    例子中,我们如何知道“Asia/Kolkata”就是印度对应的时区名呢?为了查找,可以使
    用ISO 3166 国家代码作为关键字去查阅字典pytz.country_timezones 。比如:

    >>> pytz.country_timezones['IN']
    ['Asia/Kolkata']

    注:当你阅读到这里的时候,有可能pytz 模块已经不再建议使用了,因为PEP431
    提出了更先进的时区支持。但是这里谈到的很多问题还是有参考价值的(比如使用UTC
    日期的建议等)。

     

     构建时间对象

  • 相关阅读:
    jquery的优势
    基于指纹识别技术的超市储物箱设计
    jquery核心
    jquery中的筛选
    红包算法设计
    jquery中trim() 去掉收尾空格
    jquery中效果的创建
    项目缓存
    StringUtils方法全集
    IE8下onclick事件不支持
  • 原文地址:https://www.cnblogs.com/huyangblog/p/8318594.html
Copyright © 2020-2023  润新知