349

How do I convert a numpy.datetime64 object to a datetime.datetime (or Timestamp)?

In the following code, I create a datetime, timestamp and datetime64 objects.

import datetime
import numpy as np
import pandas as pd
dt = datetime.datetime(2012, 5, 1)
# A strange way to extract a Timestamp object, there's surely a better way?
ts = pd.DatetimeIndex([dt])[0]
dt64 = np.datetime64(dt)

In [7]: dt
Out[7]: datetime.datetime(2012, 5, 1, 0, 0)

In [8]: ts
Out[8]: <Timestamp: 2012-05-01 00:00:00>

In [9]: dt64
Out[9]: numpy.datetime64('2012-05-01T01:00:00.000000+0100')

Note: it's easy to get the datetime from the Timestamp:

In [10]: ts.to_datetime()
Out[10]: datetime.datetime(2012, 5, 1, 0, 0)

But how do we extract the datetime or Timestamp from a numpy.datetime64 (dt64)?

.

Update: a somewhat nasty example in my dataset (perhaps the motivating example) seems to be:

dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100')

which should be datetime.datetime(2002, 6, 28, 1, 0), and not a long (!) (1025222400000000000L)...

piRSquared
  • 240,659
  • 38
  • 359
  • 510
Andy Hayden
  • 291,328
  • 80
  • 565
  • 500
  • 3
    you should probably accept [@Wes McKinney's answer](http://stackoverflow.com/a/13753918/4279) that is much shorter and should work on recent `numpy`, `pandas` versions. – jfs Apr 20 '15 at 23:26
  • @J.F.Sebastian Hmmm, does that mean the answer is "don't move from np.datetime to datetime"... just use pd.Timestamp (as it's a subclass of datetime anyway), or if you really must use `pd.Timestamp(dt64).to_datetime()`. I'm still a little unsatisfied about this, but certainly Wes' is less specific to my old problem (and so better for the world)! Thanks again for taking time to answer it. :) – Andy Hayden Apr 20 '15 at 23:50
  • Your question says *"or `Timestamp`"* and `Timestamp` is a `datetime` (a subclass of) anyway :) – jfs Apr 20 '15 at 23:58
  • 5
    For those coming to this question in 2017+, look at my answer below for a detailed tutorial of datetime, datetime64 and Timestamps: https://stackoverflow.com/a/46921593/3707607 – Ted Petrou Oct 25 '17 at 00:28
  • For Numpy -> datetime, as of 2020 str conversion is the most elegant option. – tejasvi88 Jul 08 '20 at 12:50

12 Answers12

234

You can just use the pd.Timestamp constructor. The following diagram may be useful for this and related questions.

Conversions between time representations

Quant
  • 3,099
  • 3
  • 13
  • 12
  • 157
    Just looking at this diagram tells me there's something fundamentally wrong with all this time stuff. – demented hedgehog Oct 12 '16 at 23:57
  • 5
    It's very confusing that pd.to_datetime would produce a TimeStamp if given the number of ms or ns, but would produce a datetime.datetime if given a datetime.datetime or a np.datetime64 if given a np.datetime64... Why would anyone think this is reasonable? – Mr.WorshipMe Feb 01 '17 at 11:14
  • For those skimming: `pd.Timestamp()` changes np.datetime to pd.Timestamp – zthomas.nc May 05 '17 at 22:16
  • 10
    @Mr.WorshipMe This diagram needs to be updated. `pd.to_datetime` converts everything to `pd.Timestamp`. A `pd.Timestamp` object has the method `to_pydatetime` to revert back to a `datetime.datetime` object and a `to_datetime64` method to convert to `np.datetime64`. – Ted Petrou Jul 01 '17 at 14:19
  • @TedPetrou This is much more reasonable - Do you know since what version this is the case? – Mr.WorshipMe Jul 01 '17 at 23:58
  • 5
    How can I get a higher resolution of this pic? – user3226167 Jan 03 '18 at 06:39
  • 1
    This chart needs the `string` -> mappings on it. Try these: `x = pd.to_datetime('2012-05-01T01:00:00.000000+0100'); print(type(x)); print(type(x.to_datetime());` -- the first is a `class 'pandas._libs.tslib.Timestamp'` and the second is a `class 'datetime.datetime'`. (And you get a warning that `to_datetime()` is deprecated for `to_pydatetime()` ) (In Pandas 0.22.0 and Python 3.5.2) – Dave X Mar 07 '18 at 21:33
  • @Quant it would be interesting to share the source file of this diagram, such that it could be updated as suggested by some other comments. With which program was it created? – cknoll Jul 26 '20 at 08:10
  • What is that function from `np.datetime64[ns]` to `datetime.datetime` (dotted arrow)? I find it weird. – rubebop Jul 31 '20 at 11:47
162

Welcome to hell.

You can just pass a datetime64 object to pandas.Timestamp:

In [16]: Timestamp(numpy.datetime64('2012-05-01T01:00:00.000000'))
Out[16]: <Timestamp: 2012-05-01 01:00:00>

I noticed that this doesn't work right though in NumPy 1.6.1:

numpy.datetime64('2012-05-01T01:00:00.000000+0100')

Also, pandas.to_datetime can be used (this is off of the dev version, haven't checked v0.9.1):

In [24]: pandas.to_datetime('2012-05-01T01:00:00.000000+0100')
Out[24]: datetime.datetime(2012, 5, 1, 1, 0, tzinfo=tzoffset(None, 3600))
Wes McKinney
  • 83,626
  • 27
  • 133
  • 107
  • 5
    You should mention that `issubclass(pd.Timestamp, datetime)` is `True`. And `Timestamp` class itself has `to_datetime()` method. – jfs Apr 20 '15 at 23:21
  • 9
    `pd.to_datetime('2012-05-01T01:00:00.000000+0100')` returns `Timestamp('2012-05-01 00:00:00')` at least in pandas `0.17.1`. – Anton Protopopov Jan 21 '16 at 10:15
160

To convert numpy.datetime64 to datetime object that represents time in UTC on numpy-1.8:

>>> from datetime import datetime
>>> import numpy as np
>>> dt = datetime.utcnow()
>>> dt
datetime.datetime(2012, 12, 4, 19, 51, 25, 362455)
>>> dt64 = np.datetime64(dt)
>>> ts = (dt64 - np.datetime64('1970-01-01T00:00:00Z')) / np.timedelta64(1, 's')
>>> ts
1354650685.3624549
>>> datetime.utcfromtimestamp(ts)
datetime.datetime(2012, 12, 4, 19, 51, 25, 362455)
>>> np.__version__
'1.8.0.dev-7b75899'

The above example assumes that a naive datetime object is interpreted by np.datetime64 as time in UTC.


To convert datetime to np.datetime64 and back (numpy-1.6):

>>> np.datetime64(datetime.utcnow()).astype(datetime)
datetime.datetime(2012, 12, 4, 13, 34, 52, 827542)

It works both on a single np.datetime64 object and a numpy array of np.datetime64.

Think of np.datetime64 the same way you would about np.int8, np.int16, etc and apply the same methods to convert beetween Python objects such as int, datetime and corresponding numpy objects.

Your "nasty example" works correctly:

>>> from datetime import datetime
>>> import numpy 
>>> numpy.datetime64('2002-06-28T01:00:00.000000000+0100').astype(datetime)
datetime.datetime(2002, 6, 28, 0, 0)
>>> numpy.__version__
'1.6.2' # current version available via pip install numpy

I can reproduce the long value on numpy-1.8.0 installed as:

pip install git+https://github.com/numpy/numpy.git#egg=numpy-dev

The same example:

>>> from datetime import datetime
>>> import numpy
>>> numpy.datetime64('2002-06-28T01:00:00.000000000+0100').astype(datetime)
1025222400000000000L
>>> numpy.__version__
'1.8.0.dev-7b75899'

It returns long because for numpy.datetime64 type .astype(datetime) is equivalent to .astype(object) that returns Python integer (long) on numpy-1.8.

To get datetime object you could:

>>> dt64.dtype
dtype('<M8[ns]')
>>> ns = 1e-9 # number of seconds in a nanosecond
>>> datetime.utcfromtimestamp(dt64.astype(int) * ns)
datetime.datetime(2002, 6, 28, 0, 0)

To get datetime64 that uses seconds directly:

>>> dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100', 's')
>>> dt64.dtype
dtype('<M8[s]')
>>> datetime.utcfromtimestamp(dt64.astype(int))
datetime.datetime(2002, 6, 28, 0, 0)

The numpy docs say that the datetime API is experimental and may change in future numpy versions.

jfs
  • 346,887
  • 152
  • 868
  • 1,518
  • 2
    I'm afraid this doesn't seem to always work: e.g. `dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100')`, which gives a long (`1025222400000000000L`) (!) – Andy Hayden Dec 04 '12 at 17:49
  • @hayden: try `type(dt64)`. `dt64.astype(datetime) == datetime.utcfromtimestamp(dt64.astype(int)*1e-6)` – jfs Dec 04 '12 at 17:59
  • @JFSebastian `type(dt64)` is `numpy.datetime64` and `dt64.astype(datetime)` is the same long int... :s – Andy Hayden Dec 04 '12 at 18:10
  • @hayden: What is your numpy version? Mine: `numpy.__version__` -> `'1.6.1'` – jfs Dec 04 '12 at 18:11
  • Version 1.8.0 (in python 2.7.3), if it works for you it does suggest it is a bug on my system! – Andy Hayden Dec 04 '12 at 18:12
  • None of these examples work for me. If I try `datetime.datetime.utcfromtimestamp`, I see two errors: (1) `TypeError: don't know how to convert scalar number to float` when I try passing in the unaltered `np.datetime64` and then (2) `ValueError: year is out of range` when I try first using `.astype(int)`. The test date is for 2012: `xx = numpy.datetime64(datetime.date(2012,1,31))` so the year is perfectly valid. I am using NumPy 1.6.1. – ely May 10 '13 at 18:54
  • @EMS: [run this](https://gist.github.com/5556838) (on success you should see nothing). If you see any errors; provide a link to the code that can be run. – jfs May 10 '13 at 19:43
115

I think there could be a more consolidated effort in an answer to better explain the relationship between Python's datetime module, numpy's datetime64/timedelta64 and pandas' Timestamp/Timedelta objects.

The datetime standard library of Python

The datetime standard library has four main objects

  • time - only time, measured in hours, minutes, seconds and microseconds
  • date - only year, month and day
  • datetime - All components of time and date
  • timedelta - An amount of time with maximum unit of days

Create these four objects

>>> import datetime
>>> datetime.time(hour=4, minute=3, second=10, microsecond=7199)
datetime.time(4, 3, 10, 7199)

>>> datetime.date(year=2017, month=10, day=24)
datetime.date(2017, 10, 24)

>>> datetime.datetime(year=2017, month=10, day=24, hour=4, minute=3, second=10, microsecond=7199)
datetime.datetime(2017, 10, 24, 4, 3, 10, 7199)

>>> datetime.timedelta(days=3, minutes = 55)
datetime.timedelta(3, 3300)

>>> # add timedelta to datetime
>>> datetime.timedelta(days=3, minutes = 55) + \
    datetime.datetime(year=2017, month=10, day=24, hour=4, minute=3, second=10, microsecond=7199)
datetime.datetime(2017, 10, 27, 4, 58, 10, 7199)

NumPy's datetime64 and timedelta64 objects

NumPy has no separate date and time objects, just a single datetime64 object to represent a single moment in time. The datetime module's datetime object has microsecond precision (one-millionth of a second). NumPy's datetime64 object allows you to set its precision from hours all the way to attoseconds (10 ^ -18). It's constructor is more flexible and can take a variety of inputs.

Construct NumPy's datetime64 and timedelta64 objects

Pass an integer with a string for the units. See all units here. It gets converted to that many units after the UNIX epoch: Jan 1, 1970

>>> np.datetime64(5, 'ns') 
numpy.datetime64('1970-01-01T00:00:00.000000005')

>>> np.datetime64(1508887504, 's')
numpy.datetime64('2017-10-24T23:25:04')

You can also use strings as long as they are in ISO 8601 format.

>>> np.datetime64('2017-10-24')
numpy.datetime64('2017-10-24')

Timedeltas have a single unit

>>> np.timedelta64(5, 'D') # 5 days
>>> np.timedelta64(10, 'h') 10 hours

Can also create them by subtracting two datetime64 objects

>>> np.datetime64('2017-10-24T05:30:45.67') - np.datetime64('2017-10-22T12:35:40.123')
numpy.timedelta64(147305547,'ms')

Pandas Timestamp and Timedelta build much more functionality on top of NumPy

A pandas Timestamp is a moment in time very similar to a datetime but with much more functionality. You can construct them with either pd.Timestamp or pd.to_datetime.

>>> pd.Timestamp(1239.1238934) #defautls to nanoseconds
Timestamp('1970-01-01 00:00:00.000001239')

>>> pd.Timestamp(1239.1238934, unit='D') # change units
Timestamp('1973-05-24 02:58:24.355200')

>>> pd.Timestamp('2017-10-24 05') # partial strings work
Timestamp('2017-10-24 05:00:00')

pd.to_datetime works very similarly (with a few more options) and can convert a list of strings into Timestamps.

>>> pd.to_datetime('2017-10-24 05')
Timestamp('2017-10-24 05:00:00')

>>> pd.to_datetime(['2017-1-1', '2017-1-2'])
DatetimeIndex(['2017-01-01', '2017-01-02'], dtype='datetime64[ns]', freq=None)

Converting Python datetime to datetime64 and Timestamp

>>> dt = datetime.datetime(year=2017, month=10, day=24, hour=4, 
                   minute=3, second=10, microsecond=7199)
>>> np.datetime64(dt)
numpy.datetime64('2017-10-24T04:03:10.007199')

>>> pd.Timestamp(dt) # or pd.to_datetime(dt)
Timestamp('2017-10-24 04:03:10.007199')

Converting numpy datetime64 to datetime and Timestamp

>>> dt64 = np.datetime64('2017-10-24 05:34:20.123456')
>>> unix_epoch = np.datetime64(0, 's')
>>> one_second = np.timedelta64(1, 's')
>>> seconds_since_epoch = (dt64 - unix_epoch) / one_second
>>> seconds_since_epoch
1508823260.123456

>>> datetime.datetime.utcfromtimestamp(seconds_since_epoch)
>>> datetime.datetime(2017, 10, 24, 5, 34, 20, 123456)

Convert to Timestamp

>>> pd.Timestamp(dt64)
Timestamp('2017-10-24 05:34:20.123456')

Convert from Timestamp to datetime and datetime64

This is quite easy as pandas timestamps are very powerful

>>> ts = pd.Timestamp('2017-10-24 04:24:33.654321')

>>> ts.to_pydatetime()   # Python's datetime
datetime.datetime(2017, 10, 24, 4, 24, 33, 654321)

>>> ts.to_datetime64()
numpy.datetime64('2017-10-24T04:24:33.654321000')
Ted Petrou
  • 45,121
  • 17
  • 113
  • 114
  • 5
    It's crazy how numpy to datetime is still hard/hacky... is there really no better way? This is a good answer, I am thinking about accepting to move it to the top-level I have to read the others more deeply once by a computer. – Andy Hayden Oct 25 '17 at 00:42
  • What's so quirky about it? Pandas Timestamps work well and are fairly simple. – Ted Petrou Oct 25 '17 at 00:45
  • 3
    Numpy to datetime. – Andy Hayden Oct 25 '17 at 01:13
  • 2
    I think this is the best answer I've ever seen. Coming from Excel, VBA, SAS, or SQL, Python seems weird because there's not just "one way" to work with dates/times. As with many things in Python or R, it seems one must choose a favourite method/module/class and stick with it. – Sean McCarthy Mar 15 '18 at 15:10
  • Yes, great answer. I finally understand this much better. Apparently there is also [`matplotlib.dates`](https://matplotlib.org/3.1.1/api/dates_api.html#date-format), why??? – Santiago May 06 '20 at 12:27
  • For an array of timestamps, `a`, you can do `a.astype('datetime64[s]')`. – Xaser Dec 01 '20 at 16:34
  • @TedPetrou thanks for the great answer, I think there is something that should be modified in your answer on datetime64 : from https://numpy.org/doc/stable/reference/arrays.datetime.html the unit can be much higher than hours, it can be up to years – Tom May 12 '21 at 10:10
34
>>> dt64.tolist()
datetime.datetime(2012, 5, 1, 0, 0)

For DatetimeIndex, the tolist returns a list of datetime objects. For a single datetime64 object it returns a single datetime object.

eumiro
  • 179,099
  • 29
  • 277
  • 252
  • 5
    @hayden if you know that its a scalar/0-d array I would rather use `.item()` which is far more explicit (and nobody can come around and start arguing that it should return a list). – seberg Dec 04 '12 at 14:03
  • 2
    I'm afraid this doesn't seem to always work: e.g. `dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100')`, which gives a long (`1025222400000000000L`) (!) – Andy Hayden Dec 04 '12 at 17:46
  • 5
    @hayden: the type that is returned by `.item()` (suggested by @seberg), `.tolist()` depends on what units datetime64 uses e.g., `D` produces `datetime.date()`, `us` (microseconds) produce `datetime.datetime()`, `ns` (nanoseconds) produce `long`. And the units change depending on input values e.g., `numpy.datetime64('2012-05-01')` uses `'D'`, `numpy.datetime64('2012-05-01T00:00:00.000')` uses `ms`, `numpy.datetime64('2012-05-01T00:00:00.000000000')` uses `ns`. You could [open an issue](https://github.com/numpy/numpy/issues) if you find it confusing. – jfs Dec 04 '12 at 20:51
  • @AndyHayden You could also just add an extra argument, 'us' or 'ms' to ensure the same format is applied resulting in the same datetime element being produced in tolist() – N M Mar 09 '18 at 09:06
15

If you want to convert an entire pandas series of datetimes to regular python datetimes, you can also use .to_pydatetime().

pd.date_range('20110101','20110102',freq='H').to_pydatetime()

> [datetime.datetime(2011, 1, 1, 0, 0) datetime.datetime(2011, 1, 1, 1, 0)
   datetime.datetime(2011, 1, 1, 2, 0) datetime.datetime(2011, 1, 1, 3, 0)
   ....

It also supports timezones:

pd.date_range('20110101','20110102',freq='H').tz_localize('UTC').tz_convert('Australia/Sydney').to_pydatetime()

[ datetime.datetime(2011, 1, 1, 11, 0, tzinfo=<DstTzInfo 'Australia/Sydney' EST+11:00:00 DST>)
 datetime.datetime(2011, 1, 1, 12, 0, tzinfo=<DstTzInfo 'Australia/Sydney' EST+11:00:00 DST>)
....

NOTE: If you are operating on a Pandas Series you cannot call to_pydatetime() on the entire series. You will need to call .to_pydatetime() on each individual datetime64 using a list comprehension or something similar:

datetimes = [val.to_pydatetime() for val in df.problem_datetime_column]
Scott Skiles
  • 2,933
  • 2
  • 26
  • 50
fantabolous
  • 15,954
  • 5
  • 46
  • 45
10

One option is to use str, and then to_datetime (or similar):

In [11]: str(dt64)
Out[11]: '2012-05-01T01:00:00.000000+0100'

In [12]: pd.to_datetime(str(dt64))
Out[12]: datetime.datetime(2012, 5, 1, 1, 0, tzinfo=tzoffset(None, 3600))

Note: it is not equal to dt because it's become "offset-aware":

In [13]: pd.to_datetime(str(dt64)).replace(tzinfo=None)
Out[13]: datetime.datetime(2012, 5, 1, 1, 0)

This seems inelegant.

.

Update: this can deal with the "nasty example":

In [21]: dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100')

In [22]: pd.to_datetime(str(dt64)).replace(tzinfo=None)
Out[22]: datetime.datetime(2002, 6, 28, 1, 0)
Community
  • 1
  • 1
Andy Hayden
  • 291,328
  • 80
  • 565
  • 500
  • Thanks Andy for sharing this tip. For some reason I am unable to make it work, as I discuss here: http://stackoverflow.com/questions/22825349/converting-between-datetime-and-timestamp-objects – Amelio Vazquez-Reina Apr 03 '14 at 00:06
  • @user815423426 this was never a very robust solution, I guess you can pass a format to the datetime constructor to work more generally. Not very pandastic though! – Andy Hayden Apr 03 '14 at 01:06
9

This post has been up for 4 years and I still struggled with this conversion problem - so the issue is still active in 2017 in some sense. I was somewhat shocked that the numpy documentation does not readily offer a simple conversion algorithm but that's another story.

I have come across another way to do the conversion that only involves modules numpy and datetime, it does not require pandas to be imported which seems to me to be a lot of code to import for such a simple conversion. I noticed that datetime64.astype(datetime.datetime) will return a datetime.datetime object if the original datetime64 is in micro-second units while other units return an integer timestamp. I use module xarray for data I/O from Netcdf files which uses the datetime64 in nanosecond units making the conversion fail unless you first convert to micro-second units. Here is the example conversion code,

import numpy as np
import datetime

def convert_datetime64_to_datetime( usert: np.datetime64 )->datetime.datetime:
    t = np.datetime64( usert, 'us').astype(datetime.datetime)
return t

Its only tested on my machine, which is Python 3.6 with a recent 2017 Anaconda distribution. I have only looked at scalar conversion and have not checked array based conversions although I'm guessing it will be good. Nor have I looked at the numpy datetime64 source code to see if the operation makes sense or not.

jtlz2
  • 4,913
  • 6
  • 43
  • 84
ndl303
  • 101
  • 1
  • 4
1

I've come back to this answer more times than I can count, so I decided to throw together a quick little class, which converts a Numpy datetime64 value to Python datetime value. I hope it helps others out there.

from datetime import datetime
import pandas as pd

class NumpyConverter(object):
    @classmethod
    def to_datetime(cls, dt64, tzinfo=None):
        """
        Converts a Numpy datetime64 to a Python datetime.
        :param dt64: A Numpy datetime64 variable
        :type dt64: numpy.datetime64
        :param tzinfo: The timezone the date / time value is in
        :type tzinfo: pytz.timezone
        :return: A Python datetime variable
        :rtype: datetime
        """
        ts = pd.to_datetime(dt64)
        if tzinfo is not None:
            return datetime(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second, tzinfo=tzinfo)
        return datetime(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second)

I'm gonna keep this in my tool bag, something tells me I'll need it again.

MikeyE
  • 1,378
  • 1
  • 13
  • 30
0
import numpy as np
import pandas as pd 

def np64toDate(np64):
    return pd.to_datetime(str(np64)).replace(tzinfo=None).to_datetime()

use this function to get pythons native datetime object

Crystal
  • 237
  • 2
  • 12
0

Some solutions work well for me but numpy will deprecate some parameters. The solution that work better for me is to read the date as a pandas datetime and excract explicitly the year, month and day of a pandas object. The following code works for the most common situation.

def format_dates(dates):
    dt = pd.to_datetime(dates)
    try: return [datetime.date(x.year, x.month, x.day) for x in dt]    
    except TypeError: return datetime.date(dt.year, dt.month, dt.day)
-1

indeed, all of these datetime types can be difficult, and potentially problematic (must keep careful track of timezone information). here's what i have done, though i admit that i am concerned that at least part of it is "not by design". also, this can be made a bit more compact as needed. starting with a numpy.datetime64 dt_a:

dt_a

numpy.datetime64('2015-04-24T23:11:26.270000-0700')

dt_a1 = dt_a.tolist() # yields a datetime object in UTC, but without tzinfo

dt_a1

datetime.datetime(2015, 4, 25, 6, 11, 26, 270000)

# now, make your "aware" datetime:

dt_a2=datetime.datetime(*list(dt_a1.timetuple()[:6]) + [dt_a1.microsecond], tzinfo=pytz.timezone('UTC'))

... and of course, that can be compressed into one line as needed.

Community
  • 1
  • 1
yoder
  • 9
  • 1
  • https://docs.scipy.org/doc/numpy/reference/arrays.datetime.html#changes-with-numpy-1-11 for changes in timezone handling. – hpaulj May 30 '17 at 20:38
  • Please `edit` to conform with proper: code formatting, quote formatting, and text formatting. Also, please adhere to proper capitalization, grammar, and check for typos, as per SO guidelines - see: [How to Post](https://stackoverflow.com/help/how-to-ask), and [Code Samples](https://stackoverflow.com/help/minimal-reproducible-example) – SherylHohman Jan 01 '20 at 22:41