87

I am having trouble converting a python datetime64 object into a string. For example:

t = numpy.datetime64('2012-06-30T20:00:00.000000000-0400')

Into:

'2012.07.01' as a  string. (note time difference)

I have already tried to convert the datetime64 object to a datetime long then to a string, but I seem to get this error:

dt = t.astype(datetime.datetime) #1341100800000000000L
time.ctime(dt)
ValueError: unconvertible time
3
  • 2
    Does stackoverflow.com/questions/13703720/… help your specific problem? Commented Oct 21, 2013 at 19:05
  • 3
    thanks, solution was: import pandas as pd ts = pd.to_datetime(str(date)) d = ts.strftime('%Y.%m.%d') Commented Oct 21, 2013 at 19:31
  • there is a simpler way, take a look at my answer below Commented Nov 2, 2021 at 1:47

11 Answers 11

98

Solution was:

import pandas as pd 
ts = pd.to_datetime(str(date)) 
d = ts.strftime('%Y.%m.%d')
Sign up to request clarification or add additional context in comments.

3 Comments

This doesn't work for some reason. numpy.datetime64' object has no attribute 'strftime'
@chemeng you need to run pd.to_datetime on the numpy.datetime64 object before doing .strftime
downvoted as it does not work with all values of datetime64 (for example, pd.to_datetime(np.datetime64('0000-01-01T00:00:00.000', 'ms')) returns Timestamp('1969-12-31 06:43:52.780800') , i.e. casts the type to datetime64[ns] silently). np.datetime_as_string (see jgrant's answer) works with all cases, and the name makes more sense to boot, I swear the pd.to_datetime is named for maximum confusion. Mind you, it will work in most common cases...
63

You can use Numpy's datetime_as_string function. The unit='D' argument specifies the precision, in this case days.

 >>> t = numpy.datetime64('2012-06-30T20:00:00.000000000-0400')
 >>> numpy.datetime_as_string(t, unit='D')
'2012-07-01'

4 Comments

numpy instead of numpyp. Or with import numpy as np just np.datetime....
This is a great way to do it!
The real answer. No pandas needed, full support for time units other than 'ns' (meaning it has no problem with times way before BC in 'ms' resolution, like pandas.Timestamp), and overall "clearly the intended way"
I agree this is the best answer. The only caveat I would say is it gave me a datatype of np.str_ instead of just a straight string. I simply did str(result) and that gave me the string.
58

If you don't want to do that conversion gobbledygook and are ok with just one date format, this was the best solution for me

str(t)[:10]
Out[11]: '2012-07-01'

As noted this works for pandas too

df['d'].astype(str).str[:10]
df['d'].dt.strftime('%Y-%m-%d') # equivalent

2 Comments

That is madness! What a creative solution!
This works on a pandas.Timestamp object as well, which is good for keeping nanosecond, or smaller, precision, as strftime does not support this level of precision.
9

t.item().strftime('%Y.%m.%d')

.item() will cast numpy.datetime64 to datetime.datetime, no need to import anything.

2 Comments

This is a bit confusing because datetime64[ns] item returns an integer in nanoseconds since 1970. One fix is t.astype('datetime64[s]').item().strftime()
No. datetime64.item() will convert into int seconds.
5

There is a route without using pandas; but see caveat below.

Well, the t variable has a resolution of nanoseconds, which can be shown by inspection in python:

>>> numpy.dtype(t)
dtype('<M8[ns]')

This means that the integral value of this value is 10^9 times the UNIX timestamp. The value printed in your question gives that hint. Your best bet is to divide the integral value of t by 1 billion then you can use time.strftime:

>>> import time
>>> time.strftime("%Y.%m.%d", time.gmtime(t.astype(int)/1000000000))
2012.07.01

In using this, be conscious of two assumptions:

1) the datetime64 resolution is nanosecond

2) the time stored in datetime64 is in UTC

Side note 1: Interestingly, the numpy developers decided [1] that datetime64 object that has a resolution greater than microsecond will be cast to a long type, which explains why t.astype(datetime.datetime) yields 1341100800000000000L. The reason is that datetime.datetime object can't accurately represent a nanosecond or finer timescale, because the resolution supported by datetime.datetime is only microsecond.

Side note 2: Beware the different conventions between numpy 1.10 and earlier vs 1.11 and later:

  • in numpy <= 1.10, datetime64 is stored internally as UTC, and printed as local time. Parsing is assuming local time if no TZ is specified, otherwise the timezone offset is accounted for.

  • in numpy >= 1.11, datetime64 is stored internally as timezone-agnostic value (seconds since 1970-01-01 00:00 in unspecified timezone), and printed as such. Time parsing does not assume the timezone, although +NNNN style timezone shift is still permitted and that the value is converted to UTC.

[1]: https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/datetime.c see routine convert_datetime_to_pyobject.

Comments

4

Building on this answer I would do the following:

import numpy
import datetime
t = numpy.datetime64('2012-06-30T20:00:00.000000000')
datetime.datetime.fromtimestamp(t.item() / 10**9).strftime('%Y.%m.%d')

The division by a billion is to convert from nanoseconds to seconds.

Comments

3

I wanted an ISO 8601 formatted string without needing any extra dependencies. My numpy_array has a single element as a datetime64. With help from @Wirawan-Purwanto, I added just a bit:

from datetime import datetime   

ts = numpy_array.values.astype(datetime)/1000000000
return datetime.utcfromtimestamp(ts).isoformat() # "2018-05-24T19:54:48"

Comments

2

The following will handle np.datetime64 objects of any units:

dt = np.datetime64('2002-06-08T00:00:00.000000000')
format_str = "%a, %d %b %Y"

formatted_str = dt.astype('datetime64[us]').item().strftime(format_str)

.astype('datetime64[us]') is required because if the resolution is datetime64[ns] (nanoseconds - the default for Pandas in many cases) or smaller, then .astype(datetime) returns an int. 'us' (microseconds) is the smallest unit that gets converted to a Python datetime.

.item() returns "a standard Python scalar", usually this means a float or int, but with dates it returns a Python datetime (depending on the unit), so you can get the right object without importing anything. .astype('O') also works.

Reference, this GitHub issue: https://github.com/numpy/numpy/issues/19782#issuecomment-908318335

Comments

1

Here is a one liner (note the padding with extra zero's):

datetime.strptime(str(t),'%Y-%m-%dT%H:%M:%S.%f000').strftime("%Y-%m-%d") 

code sample

import numpy
from datetime import datetime

t = numpy.datetime64('2012-06-30T20:00:00.000000000-0400')

method 1:

datetime.strptime(str(t),'%Y-%m-%dT%H:%M:%S.%f000').strftime("%Y-%m-%d") 

method 2:

datetime.strptime(str(t)[:10], "%Y-%m-%d").strftime("%Y-%m-%d")  

output

'2012-07-01'

Comments

0

Also, if someone want to apply same formula for any series of datetime dataframe then you can follow below steps

import pandas as pd

temp = []
for i in range(len(t["myDate"])):                                                       
       ts = pd.to_datetime(str(t["myDate"].iloc[i])) 
       temp.append(ts.strftime('%Y-%m-%d'))
    
t["myDate"] = temp

Comments

0
  • datetime objects can be converted to strings using the str() method
t.__str__()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.