• 超越datetime:Arrow,Python中的日期时间管理大师


    介绍

    Arrow是一个Python库,它提供了一种合理且对人类友好的方法来创建、操作、格式化和转换日期、时间和时间戳。它实现了对datetime类型的更新,填补了功能上的空白,提供了一个智能的模块API,支持许多常见的创建场景。简单来说,它可以帮助您使用更少的导入和更少的代码来处理日期和时间。

    Arrow以时间之箭命名,并且受到moment.jsrequests的极大启发。

    为什么要使用Arrow而不是内置模块?

    Python的标准库和其他一些低级模块拥有近乎完整的日期、时间和时区功能,但从可用性的角度来看,它们的工作效果并不理想:

    • 模块太多:datetimetimecalendardateutilpytz

    • 类型太多:datetimedatetimetzinfotimedeltarelativedelta

    • 时区和时间戳转换冗长且不愉快

    • 通常情况下都是时区不敏感的

    • 功能上存在gap:ISO 8601支持、时区间隔支持、不够人性化

    特性

    • 完全实现的,可替代datetime

    • 支持Python 3.6+

    • 默认支持时区感知和UTC

    • 为许多常见输入场景提供超简单的创建选项

    • shift方法支持相对偏移,包括周

    • 自动格式化和解析字符串

    • 广泛支持ISO 8601标准

    • 时区转换

    • 支持dateutilpytzZoneInfo tzinfo对象

    • 生成时间段、范围、下限和上限,适用于从微秒到年的时间框架

    • 使用不断增长的贡献语言环境人性化日期和时间

    • 可扩展为您自己的Arrow派生类型

    • 全面支持PEP 484风格的类型提示

    快速开始

    安装

    使用 pip or pipenv:

    pip install -U arrow

    简单使用

    >>> import arrow
    >>> arrow.get('2024-06-13T17:23:58.970460+08:00')
    
    
    >>> utc = arrow.utcnow()
    >>> utc
    
    
    >>> utc = utc.shift(hours=-1)
    >>> utc
    
    
    >>> local = utc.to('Asia/Shanghai')
    >>> local
    
    
    >>> local.timestamp()
    1718264259.95005
    
    >>> local.format()
    '2024-06-13 15:37:39+08:00'
    
    >>> local.format('YYYY-MM-DD HH:mm:ss ZZ')
    '2024-06-13 15:37:39 +08:00'
    
    >>> local.humanize()
    'an hour ago'
    
    >>> local.humanize(locale='zh-cn')
    '1小时前'

    用户指南

    Creation(创建对象)

    通过now方法创建:

    >>> arrow.utcnow()
    
    >>> arrow.now()
    
    >>> arrow.now('Asia/Shanghai')
    

    通过时间戳创建 (int or float):

    >>> arrow.get(1718264259) 
    
    >>> arrow.get(1718264259.95005)
    

    使用无时区时间、有时区时间,或者灵活指定时区:

    >>> arrow.get(datetime.utcnow())
    
    >>> arrow.get(datetime(2024, 6, 13), 'Asia/Shanghai') 
    
    >>> from dateutil import tz
    >>> arrow.get(datetime(2024, 6, 13), tz.gettz('Asia/Shanghai')) 
    
    >>> arrow.get(datetime.now(),tz.gettz('Asia/Shanghai')) 
    

    从字符串转换:

    >>> arrow.get('2024-06-13 15:30:45', 'YYYY-MM-DD HH:mm:ss') 
    

    从文本中查找日期:

    >>> arrow.get('June was born in May 1980', 'MMMM YYYY')
    

    自动识别ISO 8601格式的字符串,并解析出相应的日期时间对象,包括时区信息:

    >>> arrow.get('2024-06-13T15:34:00.000-08:00') 
    

    直接实例化Arrow对象(使用datetime类一样的参数):

    >>> arrow.get(2024, 6, 13)
    
    >>>
    >>> arrow.Arrow(2024, 6, 13)
    

    Properties(属性)

    获取日期时间或时间戳表示形式:

    >>> a = arrow.utcnow()
    >>> a.datetime  
    datetime.datetime(2024, 6, 13, 9, 25, 1, 195217, tzinfo=tzutc())

    获取一个原生的时间,包含tzinfo:

    >>> a.naive
    datetime.datetime(2024, 6, 13, 9, 25, 1, 195217)
    >>> a.tzinfo
    tzutc()

    获取任意日期时间值:

    >>> a.year
    2024
    >>> a.month
    6

    调用datetime类相关函数和属性:

    >>> a.date()
    datetime.date(2024, 6, 13)
    >>> a.time()
    datetime.time(9, 25, 1, 195217)

    Replace & Shift(替换和偏移)

    获取一个新的Arrow对象,更改其属性,就像处理datetime类型一样:

    >>> arw = arrow.utcnow()
    >>> arw
    
    >>> arw.replace(hour=4, minute=40)
    

    或者,将属性向前或向后移动的:

    >>> arw.shift(weeks=+3)
    
    >>> arw.shift(days=-3)  
    

    甚至,直接替换时区

    >>> arw.replace(tzinfo='US/Pacific')
    

    Format(格式化)

    arrow.utcnow().format('YYYY-MM-DD HH:mm:ss ZZ')
    '2024-06-13 09:34:54 +00:00'

    Convert(转换)

    按名称或tzinfo从UTC转换为其他时区:

    >>> utc = arrow.utcnow()
    >>> utc
    
    
    >>> utc.to('US/Pacific')
    
    
    >>> utc.to(tz.gettz('US/Pacific'))
    

    或者使用简写:

    >>> utc.to('local')
    
    
    >>> utc.to('local').to('utc')
    

    Humanize(人性化)

    相对于现在时间的人性化表现:

    >>> past = arrow.utcnow().shift(hours=-1)
    >>> past.humanize()
    'an hour ago'

    或者另一个Arrow对下或日期时间:

    >>> present = arrow.utcnow()
    >>> future = present.shift(hours=2)
    >>> future.humanize(present)
    'in 2 hours'

    将时间表示为相对时间或仅包括时间距离:

    >>> present = arrow.utcnow()
    >>> future = present.shift(hours=2)
    >>> future.humanize(present)
    'in 2 hours'
    >>> future.humanize(present, only_distance=True)
    '2 hours'

    指定特定的时间粒度(或多个):

    >>> present = arrow.utcnow()
    >>> future = present.shift(minutes=66)
    >>> future.humanize(present, granularity="minute")
    'in 66 minutes'
    >>> future.humanize(present, granularity=["hour", "minute"])
    'in an hour and 6 minutes'
    >>> present.humanize(future, granularity=["hour", "minute"])
    'an hour and 6 minutes ago'
    >>> future.humanize(present, only_distance=True, granularity=["hour", "minute"])
    'an hour and 6 minutes'

    支持不同时区的语言显示:

    >>> future = arrow.utcnow().shift(hours=1)
    
    >>> future.humanize(a, locale='ru')
    'через час'
    
    >>> future.humanize(a, locale='zh-cn') 
    '1小时后'

    Dehumanize(去人性化)

    使用人类可读的字符串描述,并使用它转换到过去的时间:

    >>> arw = arrow.utcnow()
    >>> arw
    
    
    >>> earlier = arw.dehumanize("2 days ago")
    >>> earlier
    

    或者用它来转换到未来的时间:

    >>> arw = arrow.utcnow()
    >>> arw
    
    
    
    >>> later = arw.dehumanize("in a month")
    >>> later
    

    支持不同时区的语言转换:

    >>> later = arw.dehumanize('1小时后', locale="zh-cn") 
    >>> later
    

    Ranges & Spans(范围&跨度)

    获取任意单位的时间跨度:

    >>> arrow.utcnow().span('hour')
    (2024-06-13T09:00:00+00:00]>, 2024-06-13T09:59:59.999999+00:00]>)
    >>> arrow.utcnow().span('day')  
    (2024-06-13T00:00:00+00:00]>, 2024-06-13T23:59:59.999999+00:00]>)

    或者只获取最大最小值:

    >>> arrow.utcnow().floor('hour')
    
    >>> arrow.utcnow().ceil('hour')
    

    您还可以获取一系列时间跨度:

    >>> start = datetime(2024, 6, 13, 12, 30) 
    >>> end = datetime(2024, 6, 13, 17, 15)
     
    >>> for r in arrow.Arrow.span_range('hour', start, end):
    ...     print(r)
    ...
    (<Arrow [2024-06-13T12:00:00+00:00]>, <Arrow [2024-06-13T12:59:59.999999+00:00]>)
    (<Arrow [2024-06-13T13:00:00+00:00]>, <Arrow [2024-06-13T13:59:59.999999+00:00]>)
    (<Arrow [2024-06-13T14:00:00+00:00]>, <Arrow [2024-06-13T14:59:59.999999+00:00]>)
    (<Arrow [2024-06-13T15:00:00+00:00]>, <Arrow [2024-06-13T15:59:59.999999+00:00]>)
    (<Arrow [2024-06-13T16:00:00+00:00]>, <Arrow [2024-06-13T16:59:59.999999+00:00]>)
    (<Arrow [2024-06-13T17:00:00+00:00]>, <Arrow [2024-06-13T17:59:59.999999+00:00]>)

    或者只是获取一系列时间点:

    >>> start = datetime(2024, 6, 13, 12, 30) 
    >>> end = datetime(2024, 6, 13, 17, 15)
    
    >>> for r in arrow.Arrow.range('hour', start, end):
    ...     print(repr(r))
    ...
    
    
    
    
    

    Factories(工厂方法)

    使用工厂模式实现自定义Arrow派生类型,来继承和扩展Arrow的模块API。首先,定义您的类型:

    class CustomArrow(arrow.Arrow):
    ...
    ...     def days_till_xmas(self):
    ...         xmas = arrow.Arrow(self.year, 12, 25)
    ...         if self > xmas:
    ...             xmas = xmas.shift(years=1)
    ...         return (xmas - self).days

    然后使用工厂:

    >>> factory = arrow.ArrowFactory(CustomArrow)
    >>> custom = factory.utcnow()
    >>> custom
    
    >>> custom.days_till_xmas()
    194

    Supported Tokens(支持的格式)

    使用以下标记进行分析和格式化。请注意,它们与strptime的标记不同:

      标记格式 示例
    Year YYYY 2000, 2001, 2002 … 2012, 2013
      YY 00, 01, 02 … 12, 13
    Month MMMM January, February, March …1
      MMM Jan, Feb, Mar …1
      MM 01, 02, 03 … 11, 12
      M 1, 2, 3 … 11, 12
    Day of Year DDDD 001, 002, 003 … 364, 365
      DDD 1, 2, 3 … 364, 365
    Day of Month DD 01, 02, 03 … 30, 31
      D 1, 2, 3 … 30, 31
      Do 1st, 2nd, 3rd … 30th, 31st
    Day of Week dddd Monday, Tuesday, Wednesday …2
      ddd Mon, Tue, Wed …2
      d 1, 2, 3 … 6, 7
    ISO week date W 2011-W05-4, 2019-W17
    Hour HH 00, 01, 02 … 23, 24
      H 0, 1, 2 … 23, 24
      hh 01, 02, 03 … 11, 12
      h 1, 2, 3 … 11, 12
    AM / PM A AM, PM, am, pm1
      a am, pm1
    Minute mm 00, 01, 02 … 58, 59
      m 0, 1, 2 … 58, 59
    Second ss 00, 01, 02 … 58, 59
      s 0, 1, 2 … 58, 59
    Sub-second S 0, 02, 003, 000006, 123123123123…3
    Timezone ZZZ Asia/Baku, Europe/Warsaw, GMT …4
      ZZ -07:00, -06:00 … +06:00, +07:00, +08, Z
      Z -0700, -0600 … +0600, +0700, +08, Z
    Seconds Timestamp X 1381685817, 1381685817.915482 …5
    ms or µs Timestamp x 1569980330813, 1569980330813221

    Built-in Formats(内置格式)

    >>> arw = arrow.utcnow()
    >>> arw.format(arrow.FORMAT_ATOM)
    '2024-06-13 10:05:40+00:00'
    >>> arw.format(arrow.FORMAT_COOKIE)
    'Thursday, 13-Jun-2024 10:05:40 UTC'
    >>> arw.format(arrow.FORMAT_RSS)
    'Thu, 13 Jun 2024 10:05:40 +0000'
    >>> arw.format(arrow.FORMAT_RFC822)
    'Thu, 13 Jun 24 10:05:40 +0000'
    >>> arw.format(arrow.FORMAT_RFC850)
    'Thursday, 13-Jun-24 10:05:40 UTC'
    >>> arw.format(arrow.FORMAT_RFC1036)
    'Thu, 13 Jun 24 10:05:40 +0000'
    >>> arw.format(arrow.FORMAT_RFC1123)
    'Thu, 13 Jun 2024 10:05:40 +0000'
    >>> arw.format(arrow.FORMAT_RFC2822)
    'Thu, 13 Jun 2024 10:05:40 +0000'
    >>> arw.format(arrow.FORMAT_RFC3339)  
    '2024-06-13 10:05:40+00:00'
    >>> arw.format(arrow.FORMAT_W3C)
    '2024-06-13 10:05:40+00:00'

    Escaping Formats(转义格式)

    解析和格式化时,可以通过将格式字符串中的标记、短语和正则表达式括在方括号中来转义它们。

    标记格式

    >>> fmt = "YYYY-MM-DD h [h] m"
    
    >>> arw = arrow.get("2024-06-13 8 h 40", fmt) 
    >>> arw.format(fmt)                           
    '2024-06-13 8 h 40'
    
    >>> fmt = "YYYY-MM-DD h [hello] m"
    >>> arw = arrow.get("2024-06-13 8 hello 40", fmt) 
    >>> arw
    
    >>> arw.format(fmt)
    '2024-06-13 8 hello 40'
    
    >>> fmt = "YYYY-MM-DD h [hello world] m"
    >>> arw = arrow.get("2024-05-16 8 hello world 40", fmt) 
    >>> arw.format(fmt)
    '2024-05-16 8 hello world 40'

    正则

    您还可以通过将正则表达式括在方括号内来转义它们。在下面的示例中,我们使用正则表达式s+来匹配分隔标记的任意数量的空白字符。如果您不提前知道令牌之间的空间数(例如,在日志文件中),这将非常有用。

    >>> fmt = r"ddd[\s+]MMM[\s+]DD[\s+]HH:mm:ss[\s+]YYYY"
    >>> arrow.get("Thu Jun 16 16:41:45 2024", fmt)
    
    
    >>> arrow.get("Thu \tJun 16     16:41:45        2024", fmt) 
    
    
    >>> arrow.get("Thu Jun 16    16:41:45  2024", fmt) 
    

    Punctuation(标点符号)

    日期和时间格式的两侧可以用以下列表中的一个标点符号隔开:、.;:!" \ ' [ ] { } ( ) < >`

    >>> arrow.get("Cool date: 2024-06-16T09:12:45.123456+04:30.", "YYYY-MM-DDTHH:mm:ss.SZZ")
    2024-06-16T09:12:45.123456+04:30]>
    
    >>> arrow.get("Tomorrow (2024-06-16) is Halloween!", "YYYY-MM-DD") 
    2024-06-16T00:00:00+00:00]>
    
    >>> arrow.get("Halloween is on 2024.06.16.", "YYYY.MM.DD") 
    2024-06-16T00:00:00+00:00]>
    
    >>> arrow.get("It's Halloween tomorrow (2024-06-16)!", "YYYY-MM-DD") 
    Traceback (most recent call last):
      File "", line 1, in 
      File "C:\Users\LocalCache\local-packages\Python312\site-packages\arrow\api.py", line 91, in get
        return _factory.get(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "C:\Users\LocalCache\local-packages\Python312\site-packages\arrow\factory.py", line 292, in get
        dt = parser.DateTimeParser(locale).parse(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "C:\Users\LocalCache\local-packages\Python312\site-packages\arrow\parser.py", line 323, in parse
        raise ParserMatchError(
    arrow.parser.ParserMatchError: Failed to match 'YYYY-MM-DD' when parsing "It's Halloween tomorrow (2024-06-16)!".

    Redundant Whitespace(冗余空白字符处理)

    多余的空白字符(空格、制表符和换行符)可以通过将normalize_whitespace标志传递到arrow.get来自动规范化:

    >>> arrow.get('\t \n  2024-06-13T12:30:45.123456 \t \n', normalize_whitespace=True) 
    
    
    >>> arrow.get('2024-06-13  T \n   12:30:45\t123456', 'YYYY-MM-DD T HH:mm:ss S', normalize_whitespace=True) 
    

     

  • 相关阅读:
    C++异常
    Flink学习16:算子介绍map
    Android Studio 配置Git SVN忽略文件
    【云原生】第十篇--Docker主机集群化方案 Docker Swarm
    赔偿百万:全国首例短视频短算法侵权生效
    10.力扣c++刷题-->两数之和
    未找到重要体积,且场景太大,自动合成的体积无法产生良好的效果。请添加一个紧密包裹的lightmass重要体积来优化场景质量及光照构建时间。
    低代码+BPM+KM于一体的软件开发平台
    卷积神经网络
    论文分享 | 智能放牧无人机&多旋翼无人机发展趋势
  • 原文地址:https://www.cnblogs.com/sesshoumaru/p/18261860