zoukankan      html  css  js  c++  java
  • 日期文本互转,时间戳,时间差 以及 时区变换

    2019-05-25 重新编辑了一下

    以下基本我在日常写代码中,最常用的一些日期相关部分。

    1、当前时间转文本strftime()

    无论是timedatetime,哪个模块都可以,具体怎么输出,自行调整格式参数'%Y-%m-%d %H:%M:%S'

    %字符表意数值范围
    %y 年(2位) 00, 01, …, 99
    %Y 年(4位) 0001, 0002, …, 2013, 2014, …, 9998, 9999
    %m 01, 02, …, 12
    %d 01, 02, …, 31
    %H 时(24小时制) 00, 01, …, 23
    %M 00, 01, …, 59
    %S 00, 01, …, 59
    %f 毫秒 000000, 000001, …, 999999
    %z 时区 (empty), +0000, -0400, +1030, +063415, -030712.345216
    %a 工作日作为语言环境的缩写名称。
    太阳,周一,......,周六(en_US);
    所以,Mo,...,Sa(de_DE)
     
    %A 平日作为语言环境的全名。
    星期日,星期一,......,星期六(en_US);
    Sonntag,Montag,......,Samstag(de_DE)
     
    %w 工作日为十进制数,其中0表示星期日,6表示星期六。 0,1,...,6  
    %d 作为零填充十进制数的月中的某一天。 01,02,...,31  
    %b 月份为区域设置的缩写名称。
    Jan,Feb,...,Dec(en_US);
    Jan,Feb,...,Dez(de_DE)
     
    %B 月份为区域设置的全名。
    1月,2月,...,12月(en_US);
    Januar,Februar,...,Dezember(de_DE)
     
    %m 月份为零填充十进制数。 01,02,...,12  
    %y 没有世纪的年份为零填充十进制数。 00,01,...,99  
    %Y 年份以世纪为十进制数。 1970年,1988年,2001年,2013年  
    %H 小时(24小时制)作为零填充十进制数。 00,01,...,23  
    %I 小时(12小时制)作为零填充十进制数。 01,02,...,12  
    %p Locale相当于AM或PM。
    AM,PM(en_US);
    上午,下午(de_DE)
     
    %M 分钟为零填充十进制数。 00,01,...,59  
    %S 其次是零填充十进制数。 00,01,...,59  
    %f Microsecond为十进制数,左侧为零填充。 000000,000001,...,999999  
    %z UTC偏移量,格式为+ HHMM或-HHMM(如果对象是天真的,则为空字符串)。 (空),+ 0000,-0400,+ 1030  
    %Z 时区名称(如果对象是天真的,则为空字符串)。 (空),UTC,EST,CST  
    %j 一年中的一天作为零填充十进制数。 001,002,...,366  
    %U 作为零填充十进制数的一年中的周数(星期日作为一周的第一天)。在第一个星期日之前的新年中的所有日子都被认为是在第0周。 00,01,...,53  
    %W 一年中的周数(星期一作为一周的第一天)作为十进制数。在第一个星期一之前的新年中的所有日子被认为是在第0周。 00,01,...,53  
    %c Locale的适当日期和时间表示。
    1988年8月16日星期二21:30:00(en_US);
    Di 16 Aug 21:30:00 1988(de_DE)
     
    %x Locale的适当日期表示。
    08/16/88(无);
    1988年8月16日(en_US);
    19.08.1988(de_DE)
     
    %X Locale的适当时间表示。
    21:30:00(zh_);
    21:30:00(de_DE)
     
    %% 文字'%'字符。  

    这里只列一下我用到的,更多可以看官方文档:
    https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior

    【注意】:
    time、datetime两种时间模块虽然都有strftime,但是(格式,时间)参数位置正好相反。

    time模块(格式在前,时间在后)

    import time
    t = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
    print(type(t),t)
    
    # 输出结果
    <class 'str'> 2019-05-25 08:56:45
     

    datetime模块(格式在后,时间在前)

    import datetime
    dt = datetime.datetime.strftime(datetime.datetime.now(),'%Y-%m-%d %H:%M:%S')
    print(type(dt),dt)
    
    # 输出结果
    <class 'str'> 2019-05-25 08:56:45

    2、文本转日期

    (1)常规方法strptime("日期时间文本","文本格式")

    制定时间格式,进行解析

    import datetime
    dt = datetime.datetime.strptime('2019-05-25T07:46:45.743+0000','%Y-%m-%dT%H:%M:%S.%f%z')
    print(type(dt),dt)
    
    # 输出结果
    <class 'datetime.datetime'> 2019-05-25 07:46:45.743000+00:00
     

    (2)万能方法parse("日期时间文本")

    自动解析

    easy_install python-dateutil

    pip install python-dateutil

    from dateutil.parser import parse
    dt = parse('2019-05-25 07:46:45')
    print(type(dt),dt)
    
    # 输出结果
    <class 'datetime.datetime'> 2019-05-25 07:46:45
     

    该方法适用于很多类型时间格式,建议使用前自行测试

    dt = ["2001.07.04 AD at 12:08:56 PDT",
    "Wed, 4 Jul 2001 12:08:56 -0700",
    "190525","2018-08-06T10:00:00.000Z",
    "Wed, Jul 4",
    "12:08 PM",
    "02001.July.04 AD 12:08 PM",
    "20190525083855-0700",
    "2001-07-04T12:08:56.235-0700",
    "Thu Oct 16 07:13:48 GMT 2014"]
    
    for i in dt:
    	print(parse(i))
    
    # 输出结果
    2001-07-04 12:08:56
    2001-07-04 12:08:56-07:00
    2025-05-19 00:00:00
    2018-08-06 10:00:00+00:00
    2019-07-04 00:00:00
    2019-05-25 12:08:00
    2001-07-04 12:08:00
    2019-05-25 08:38:55-07:00
    2001-07-04 12:08:56.235000-07:00
    2014-10-16 07:13:48+00:00
     

    但是注意,国外日期时间的常用格式和国内不一样。单写19-05-25会被解析成2025年5月19日

    print(parse("19-05-25"))
    
    # 输出结果
    2025-05-19 00:00:00
     

     

    如果是2019-05-25就不会错了

    print(parse("2019-05-25"))
    
    # 输出结果
    2019-05-25 00:00:00
     

    3、时间戳相关

    生成10或13位时间戳(做一些网页爬虫或构造提交时候可能用到)

    import time
    t = time.time()
    print(type(t),t)
    print('10位时间戳:',str(int(t)))
    print('13位时间戳:',str(int(t*1000)))
    
    # 输出结果
    <class 'float'> 1558750679.0872486
    10位时间戳: 1558750679
    13位时间戳: 1558750679087
     

     

    时间戳转日期时间

    import datetime
    ts = '1517302458364'
    dt1 = datetime.datetime.fromtimestamp(float(ts)/10**(len(ts)-10))
    print(type(dt1),dt1)
    
    # 输出结果
    <class 'datetime.datetime'> 2018-01-30 16:54:18.364000

     

    4、时间差计算

    定义两个日期时间dt1dt2,计算一下差值

    import datetime
    dt1 = datetime.datetime.fromtimestamp(1517302458)
    dt2 = datetime.datetime.now()
    td = '相差%d天零%.1f个小时'%((dt2-dt1).days,(dt2-dt1).seconds/60/60)
    print('%s
    %s
    %s'%(dt1,dt2,td))
    
    # 输出结果
    2018-01-30 16:54:18
    2019-05-25 09:31:11.750390
    相差479天零16.6个小时

    5、时区转换

    时区并非东八区的时间,比如2018-12-10T07:46:45.743+0000

    from datetime import datetime,timezone,timedelta
    dt1 = datetime.utcnow().replace(tzinfo=timezone.utc)
    dt2 = dt1.astimezone(timezone(timedelta(hours=8))) # 转换时区到东八区
    print('UTC协调世界时 	%s
    UTC+8北京时间	%s'%(dt1,dt2))
    
    # 输出结果
    UTC协调世界时 	2019-05-25 02:48:54.281741+00:00
    UTC+8北京时间	2019-05-25 10:48:54.281741+08:00
     

    Python 时间戳的坑

    在使用 datetimetimestamp() 方法获取时间戳时遇到一点问题

    1
    2
    3
    4
    5
    6
    7
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-


    from datetime import datetime
    print(datetime.now().timestamp() # ==> 1512393482.510263
    print(datetime.utcnow().timestamp()) # ==> 1512364682.510288

    理论上两个输出应该都返回当前时间戳,但是 utcnow() 方法的时间戳并不正确,网上查找资料没一个能说明白的,后来查看官方文档发现这么一句话

    There is no method to obtain the POSIX timestamp directly from a naive datetime instance representing UTC time. If your application uses this convention and your system timezone is not set to UTC, you can obtain the POSIX timestamp by supplying tzinfo=timezone.utc:

    我们不能通过 UTC 得到的 datetime 实例直接获取时间戳,如果系统的时区不是 UTC 则需要 timezone.utc 来帮忙转换。我晕,我们不提供,但是给你指条路。好吧,先试试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-


    from datetime import datetime
    from datetime import timezone

    dt = datetime.utcnow()
    print(dt.replace(tzinfo=timezone.utc).timestamp()) # ==> 1512454062.906826
    print(datetime.now().timestamp()) # ==> 1512454062.906826

    OK,这次可以了,但是呢,难道每次获取一次时间戳都这样麻烦或者修改系统时区吗?当然不是,我们还可以通过 time 模块来轻松搞定

    1
    2
    3
    4
    5
    6
    7
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-


    import time

    print(time.time()) # ==> 1512454270.614852

    时间戳转为地区时间

    如果想要将时间戳转为某个地区的时间,比如北京时间,需要引入 pytz 模块,首先下载 pip install pytz

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-


    import time
    from datetime import datetime
    import pytz

    tz = pytz.timezone('Asia/Shanghai') #东八区
    t = datetime.fromtimestamp(int(time.time()),
    pytz.timezone('Asia/Shanghai')).strftime('%Y-%m-%d %H:%M:%S %Z%z')
    print(t) # ==> 2017-12-05 18:39:45 CST+0800

    讨论

    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倍多。 如果你要处理大量的涉及到日期的数据的话,那么最好考虑下这个方案!

  • 相关阅读:
    常见的压缩命令
    Linux忘记root密码的解决
    QQFM 中转站(囧转站)OOXX V1.1 by wy811007 (附SkinH_Net的使用) 程序失效 更新1.3版 未发布
    直接插入排序和希尔排序
    SIGABRT错误的调试办法
    UIGestureRecognizer有用文档摘抄
    HTC G14 Sensation Z710e 刷机总结
    iOS 之生命周期(转)
    算法时间复杂度分析基础(转)
    NSURLConnection的同步与异步
  • 原文地址:https://www.cnblogs.com/presleyren/p/11821855.html
Copyright © 2011-2022 走看看