介紹
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
和ZoneInfo
tzinfo物件 -
生成時間段、範圍、下限和上限,適用於從微秒到年的時間框架
-
使用不斷增長的貢獻語言環境人性化日期和時間
-
可擴充套件為您自己的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:\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 [2024-06-13T12:30:45.123456+00:00]>
>>> arrow.get('2024-06-13 T \n 12:30:45\t123456', 'YYYY-MM-DD T HH:mm:ss S', normalize_whitespace=True)
<Arrow [2024-06-13T12:30:45.123456+00:00]>