84

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
Ninjakannon
  • 3,751
  • 7
  • 53
  • 76
cs_newbie
  • 1,959
  • 1
  • 15
  • 16

10 Answers10

96

Solution was:

import pandas as pd 
ts = pd.to_datetime(str(date)) 
d = ts.strftime('%Y.%m.%d')
Ninjakannon
  • 3,751
  • 7
  • 53
  • 76
cs_newbie
  • 1,959
  • 1
  • 15
  • 16
  • 5
    This doesn't work for some reason. numpy.datetime64' object has no attribute 'strftime' – chemeng Oct 17 '18 at 14:53
  • 3
    @chemeng you need to run `pd.to_datetime` on the `numpy.datetime64` object before doing `.strftime` – RK1 Oct 30 '18 at 12:55
56

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
citynorman
  • 4,918
  • 3
  • 38
  • 39
  • 3
    That is madness! What a creative solution! – four43 May 31 '18 at 13:18
  • 1
    This works on a [pandas.Timestamp](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Timestamp.html) object as well, which is good for keeping nanosecond, or smaller, precision, as `strftime` does not support this level of precision. – Adrian Torrie Sep 05 '18 at 06:29
49

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'
jgrant
  • 1,273
  • 1
  • 14
  • 22
11

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

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

brunoff
  • 4,161
  • 9
  • 10
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.

Wirawan Purwanto
  • 3,613
  • 3
  • 28
  • 28
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"
four43
  • 1,675
  • 2
  • 20
  • 33
3

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.

tommy.carstensen
  • 8,962
  • 15
  • 65
  • 108
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'
Grant Shannon
  • 4,709
  • 1
  • 46
  • 36
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
Corralien
  • 109,409
  • 8
  • 28
  • 52
Amit Tiwari
  • 163
  • 2
  • 10
0
  • datetime objects can be converted to strings using the str() method
t.__str__()
kwa
  • 49
  • 4