介绍
Arrow是一个Python库,它提供了一种合理且对人类友好的方法来创建、操作、格式化和转换日期、时间和时间戳。它实现了对datetime类型的更新,填补了功能上的空白,提供了一个智能的模块API,支持许多常见的创建场景。简单来说,它可以帮助您使用更少的导入和更少的代码来处理日期和时间。
Arrow以时间之箭命名,并且受到moment.js和requests的极大启发。
为什么要使用Arrow而不是内置模块?
Python的标准库和其他一些低级模块拥有近乎完整的日期、时间和时区功能,但从可用性的角度来看,它们的工作效果并不理想:
-
模块太多:
datetime,time,calendar,dateutil,pytz等 -
类型太多:
date,time,datetime,tzinfo,timedelta,relativedelta等 -
时区和时间戳转换冗长且不愉快
-
通常情况下都是时区不敏感的
-
功能上存在gap:ISO 8601支持、时区间隔支持、不够人性化
特性
-
完全实现的,可替代
datetime -
支持Python 3.6+
-
默认支持时区感知和UTC
-
为许多常见输入场景提供超简单的创建选项
-
shift方法支持相对偏移,包括周 -
自动格式化和解析字符串
-
广泛支持ISO 8601标准
-
时区转换
-
支持
dateutil,pytz和ZoneInfotzinfo对象 -
生成时间段、范围、下限和上限,适用于从微秒到年的时间框架
-
使用不断增长的贡献语言环境人性化日期和时间
-
可扩展为您自己的Arrow派生类型
-
全面支持PEP 484风格的类型提示
快速开始
安装
使用 pip or pipenv:
pip install -U arrow
简单使用
>>> import arrow >>> arrow.get('2024-06-13T17:23:58.970460+08:00') <Arrow [2024-06-13T17:23:58.970460+08:00]> >>> utc = arrow.utcnow() >>> utc <Arrow [2024-06-13T08:37:39.950050+00:00]> >>> utc = utc.shift(hours=-1) >>> utc <Arrow [2024-06-13T07:37:39.950050+00:00]> >>> local = utc.to('Asia/Shanghai') >>> local <Arrow [2024-06-13T15:37:39.950050+08:00]> >>> 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 [2024-06-13T09:03:42.591212+00:00]> >>> arrow.now() <Arrow [2024-06-13T17:04:00.926319+08:00]> >>> arrow.now('Asia/Shanghai') <Arrow [2024-06-13T17:04:25.058905+08:00]>
通过时间戳创建 (int or float):
>>> arrow.get(1718264259) <Arrow [2024-06-13T07:37:39+00:00]> >>> arrow.get(1718264259.95005) <Arrow [2024-06-13T07:37:39.950050+00:00]>
使用无时区时间、有时区时间,或者灵活指定时区:
>>> arrow.get(datetime.utcnow()) <Arrow [2024-06-13T09:14:15.099808+00:00]> >>> arrow.get(datetime(2024, 6, 13), 'Asia/Shanghai') <Arrow [2024-06-13T00:00:00+08:00]> >>> from dateutil import tz >>> arrow.get(datetime(2024, 6, 13), tz.gettz('Asia/Shanghai')) <Arrow [2024-06-13T00:00:00+08:00]> >>> arrow.get(datetime.now(),tz.gettz('Asia/Shanghai')) <Arrow [2024-06-13T17:16:02.309002+08:00]>
从字符串转换:
>>> arrow.get('2024-06-13 15:30:45', 'YYYY-MM-DD HH:mm:ss') <Arrow [2024-06-13T15:30:45+00:00]>
从文本中查找日期:
>>> arrow.get('June was born in May 1980', 'MMMM YYYY') <Arrow [1980-05-01T00:00:00+00:00]>
自动识别ISO 8601格式的字符串,并解析出相应的日期时间对象,包括时区信息:
>>> arrow.get('2024-06-13T15:34:00.000-08:00') <Arrow [2024-06-13T15:34:00-08:00]>
直接实例化Arrow对象(使用datetime类一样的参数):
>>> arrow.get(2024, 6, 13) <Arrow [2024-06-13T00:00:00+00:00]> >>> >>> arrow.Arrow(2024, 6, 13) <Arrow [2024-06-13T00:00:00+00:00]>
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 <Arrow [2024-06-13T09:33:30.538303+00:00]> >>> arw.replace(hour=4, minute=40) <Arrow [2024-06-13T04:40:30.538303+00:00]>
或者,将属性向前或向后移动的:
>>> arw.shift(weeks=+3) <Arrow [2024-07-04T09:33:30.538303+00:00]> >>> arw.shift(days=-3) <Arrow [2024-06-10T09:33:30.538303+00:00]>
甚至,直接替换时区
>>> arw.replace(tzinfo='US/Pacific') <Arrow [2024-06-13T09:33:30.538303-07:00]>
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 <Arrow [2024-06-13T09:36:22.204239+00:00]> >>> utc.to('US/Pacific') <Arrow [2024-06-13T02:36:22.204239-07:00]> >>> utc.to(tz.gettz('US/Pacific')) <Arrow [2024-06-13T02:36:22.204239-07:00]>
或者使用简写:
>>> utc.to('local') <Arrow [2024-06-13T17:36:22.204239+08:00]> >>> utc.to('local').to('utc') <Arrow [2024-06-13T09:36:22.204239+00:00]>
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 <Arrow [2024-06-13T09:47:35.616633+00:00]> >>> earlier = arw.dehumanize("2 days ago") >>> earlier <Arrow [2024-06-11T09:47:35.616633+00:00]>
或者用它来转换到未来的时间:
>>> arw = arrow.utcnow() >>> arw <Arrow [2024-06-13T09:47:35.616633+00:00]> >>> later = arw.dehumanize("in a month") >>> later <Arrow [2024-07-13T09:47:35.616633+00:00]>
支持不同时区的语言转换:
>>> later = arw.dehumanize('1小时后', locale="zh-cn") >>> later <Arrow [2024-06-13T10:47:35.616633+00:00]>
Ranges & Spans(范围&跨度)
获取任意单位的时间跨度:
>>> arrow.utcnow().span('hour') (<Arrow [2024-06-13T09:00:00+00:00]>, <Arrow [2024-06-13T09:59:59.999999+00:00]>) >>> arrow.utcnow().span('day') (<Arrow [2024-06-13T00:00:00+00:00]>, <Arrow [2024-06-13T23:59:59.999999+00:00]>)
或者只获取最大最小值:
>>> arrow.utcnow().floor('hour') <Arrow [2024-06-13T09:00:00+00:00]> >>> arrow.utcnow().ceil('hour') <Arrow [2024-06-13T09:59:59.999999+00:00]>
您还可以获取一系列时间跨度:
>>> 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)) ... <Arrow [2024-06-13T12:30:00+00:00]> <Arrow [2024-06-13T13:30:00+00:00]> <Arrow [2024-06-13T14:30:00+00:00]> <Arrow [2024-06-13T15:30:00+00:00]> <Arrow [2024-06-13T16:30:00+00:00]>
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 <CustomArrow [2024-06-13T10:02:04.898347+00:00]> >>> 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 <Arrow [2024-06-13T08:40:00+00:00]> >>> 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 [2024-06-16T16:41:45+00:00]> >>> arrow.get("Thu tJun 16 16:41:45 2024", fmt) <Arrow [2024-06-16T16:41:45+00:00]> >>> arrow.get("Thu Jun 16 16:41:45 2024", fmt) <Arrow [2024-06-16T16:41:45+00:00]>
Punctuation(标点符号)
日期和时间格式的两侧可以用以下列表中的一个标点符号隔开:、.;:!" ' [ ] { } ( ) < >`
>>> arrow.get("Cool date: 2024-06-16T09:12:45.123456+04:30.", "YYYY-MM-DDTHH:mm:ss.SZZ") <Arrow [2024-06-16T09:12:45.123456+04:30]> >>> arrow.get("Tomorrow (2024-06-16) is Halloween!", "YYYY-MM-DD") <Arrow [2024-06-16T00:00:00+00:00]> >>> arrow.get("Halloween is on 2024.06.16.", "YYYY.MM.DD") <Arrow [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 "<stdin>", line 1, in <module> File "C:UsersLocalCachelocal-packagesPython312site-packagesarrowapi.py", line 91, in get return _factory.get(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:UsersLocalCachelocal-packagesPython312site-packagesarrowfactory.py", line 292, in get dt = parser.DateTimeParser(locale).parse( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:UsersLocalCachelocal-packagesPython312site-packagesarrowparser.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 [2024-06-13T12:30:45.123456+00:00]> >>> arrow.get('2024-06-13 T n 12:30:45t123456', 'YYYY-MM-DD T HH:mm:ss S', normalize_whitespace=True) <Arrow [2024-06-13T12:30:45.123456+00:00]>