Arrow is a flexible Python library designed to create, format, manipulate, and convert dates, time, and timestamps in a sensible and human-friendly manner. It provides an intelligent module API that allows dealing with dates and times with a few code lines and imports. The library is named after the “time’s arrow” concept suggesting the one-directional progress of time. It is inspired by Requests (an HTTP library) and Moment.js (a JavaScript date library).
Why Arrow?
Standard Python library and low-level conventional modules are available for the various date and time functionalities but have the following limitations from a user’s point of view:
- Too many modules available such as time, datetime, dateutil, calendar and pytz
- A large number of data types to choose from such as datetime, date, time, timedelta, tzinfo and so on
- Users may lack experience in handling different time zones
- Inefficient ways of timestamps and timezone conversions
- Gaps in functionalities such as humanization (e.g. converting a date into human-readable format) and ISO 8601 parsing
Highlighting Features of Arrow
- Supports Python 3.6+ versions
- A fully-implemented, efficient alternative to datetime standard library
- Aware of timezones (uses UTC (Coordinated Universal Time) by default) and enables easy timezone conversion.
- Automatic formatting and parsing of strings
- Widely supports ISO 8601 standard date and time format.
- Supports pytz, ZoneInfo and dateutil objects
- Can generate floors, ceilings, spans and ranges for time frames ranging from microseconds to years
- Can be extended to users’ own Arrow-derived datatypes
- Supports PEP 484-style type hints
Installing Arrow
Install Arrow using pip command as follows:
pip install -U arrow
(where -U option is used for installing the updated version)
Practical Implementation
Here’s a demonstration of performing various operations using Arrow. The experiments have been done in Google colab with Python version3.7.10. Explanation of each operation along with its output is as follows:
First, import the Arrow library
import arrow as arw
- Represent current time in the given timezone
arw.now()
With no timezone specified, an Arrow object representing current UTC time will be created. Same output results on executing
arw.utcnow()
Output: <Arrow [2021-03-16T10:39:26.746385+00:00]>
To get current time in say US/Pacific timezone:
arw.now(‘US/Pacific’)
Output: <Arrow [2021-03-16T03:48:10.893440-07:00]>
- Convert a specified integer or float number into a floating-point UTC timestamp
arw.get(1567900664)
Output: <Arrow [2019-09-07T23:57:44+00:00]>
#Try with a floating point input arw.get(17900664.5463877)
Output: <Arrow [1970-07-27T04:24:24.546388+00:00]>
Verify the converted output here.
- String parsing
arw.get('12-03-2020 22:30:25', 'MM-DD-YYYY HH:mm:ss')
Specified date and time will be represented as MM-DD-YYYY HH:mm:ss
format
Output: <Arrow [2020-12-03T22:30:25+00:00]>
- Extract date from a string
arw.get('I was born on March 12 1990','MMMM DD YYYY')
‘MMMM DD YYYY’ formatted date will be searched in the string
Output: <Arrow [1990-03-12T00:00:00+00:00]>
- Instantiate Arrow object by directly providing a datetime argument
arw.Arrow(2020,12,26)
Output: <Arrow [2020-12-26T00:00:00+00:00]>
- Get a datetime representation an Arrow object
x = arw.now()
Suppose, x is <Arrow [2021-03-16T11:49:17.908895+00:00]>
x.datetime
Output: datetime.datetime(2021, 3, 16, 11, 49, 17, 908895, tzinfo=tzlocal())
The components can then be separated as:
x.month
Output: 3
x.year
Output: 2021
x.day
Output: 16
x.hour
Output: 11
Datetime functions can be called to get properties of the Arrow object
x.time()
Output: datetime.time(11, 49, 17, 908895)
- Replace one or more components of the Arrow object
a = arw.now()
Suppose, ‘a’ is <Arrow [2021-03-16T12:00:13.500164+00:00]>
a.replace(year=2019, second=45, month=11)
will give the output: <Arrow [2019-11-16T12:00:45.500164+00:00]>
- One or more Arrow object attributes can be shifted forward or backward
present = arw.now()
Suppose, ‘present’ object is <Arrow [2021-03-16T12:08:34.530495+00:00]>
Go forward in time by 2 years
present.shift(years=+2)
Output: <Arrow [2023-03-16T12:08:34.530495+00:00]>
Go backward by 4 hours
present.shift(hours=-4)
Output: <Arrow [2021-03-16T08:08:34.530495+00:00]>
- Represent date and time in the required format
arw.now().format('HH:MM:SS MM:DD:YYYY')
Output: 12:03:00 03:16:2021
(i.e. 12 hrs 3 mins 00 sec, 16 March 2021)
- Convert default UTC to specified timezone
utc = arw.utcnow()
Suppose, utc is <Arrow [2021-03-16T12:20:43.301159+00:00]>
It can be converted to US/Pacific time zone as follows:
utc.to('US/Pacific')
Output: <Arrow [2021-03-16T05:20:43.301159-07:00]>
- Humanization examples
Humanize relative to current time:
future = arw.now().shift(minutes=+2) #advance by 2 mins future.humanize()
Output: ‘in 2 minutes’
Humanize relative to another datetime or Arrow object
present = arw.now() #current time future = present.shift(days=-3) #go back by 3 days #how far is present from future future.humanize(present)
Output: ‘3 days ago’
#how far is future from present present.humanize(future)
Output: ‘in 3 days’
To get only the distance:
future.humanize(present, only_distance=True)
Output: ‘3 days’
Indicate time difference in terms of one or more specific time granularities like hours,
minutes etc.
future.humanize(present, granularity="minute")
Output: ‘4320 minutes ago’
#3 days equals 4320 mins
Multiple granularities can be specified as:
future.humanize(present, granularity=["minute","second"])
Output: ‘in 4320 minutes and 0 seconds’
- Get the span of any time unit
arw.now().span(‘minute’)
Output:
(<Arrow [2021-03-16T12:58:00+00:00]>, <Arrow [2021-03-16T12:58:59.999999+00:00]>)
arw.now().span('day') #get the span of time for a whole day
Output:
(<Arrow [2021-03-16T00:00:00+00:00]>, <Arrow [2021-03-16T23:59:59.999999+00:00]>)
- Get floor and ceiling values of a specific time component
arw.now().floor('minute')
Output: <Arrow [2021-03-16T13:04:00+00:00]>
arw.now().ceil('minute')
Output: <Arrow [2021-03-16T13:04:59.999999+00:00]>
- Get the range of specified timespans
import datetime begin = datetime.datetime(2020, 6, 5, 2, 30) #start time end = datetime.datetime(2020, 6, 5, 4, 50) #end time for r in arw.Arrow.range('hour', begin, end): #iterate in terms of hour print(r)
We want time from 2:30 to 4:50 at the interval of an hour so output will contain 2:30, 3:30 and 4:30 times.
Output:
2020-06-05T02:30:00+00:00 2020-06-05T03:30:00+00:00 2020-06-05T04:30:00+00:00
- FACTORIES can be used for utilizing Arrow’s module API to create a custom Arrow-derive type.
Suppose, we need to find difference in terms of days between today and the Christmas day. We can define a custom class as:
class Custom(arw.Arrow): #pass an Arrow object def till_christmas(self): #define a function for computation #store christmas day of given year christmas = arw.Arrow(self.year, 12, 25) “”” If given date falls comes after Christmas of that year, compute its difference w.r.t. Christmas of the next year “”” if self > christmas: christmas = christmas.shift(years=1) return (christmas - self).days #return the difference
f = arw.ArrowFactory(Custom) #Create a factory x = f.now() #current date and time
Suppose, x is <Custom [2021-03-16T13:21:09.741500+00:00]>
Call the till_christmas() method to compute the difference
x.till_christmas()
Output: 283
i.e. Christmas of the year 2021 is 283 days away from 16 March 2021.
- Google colab notebook of the above-explained operations using Arrow is available here.
References
We have demonstrated some basic operations using Arrow. To know about more such available functionalities and dive deeper into the Arrow library for efficient handling of date, time and timestamps, refer to the following sources: