I do not believe that there is any way to have a datetime column that is part real and part NaN. Note that date-time is essentially a format on top of an integer, and an integer cannot be half valid and invalid (a bit more on that below).
Anyway, I would just make a new column for a while, which includes NaN. Starting from the following, where "raw_dt" is your raw data, and "formatted_dt" is the correct time and date:
raw_dt formatted_dt 0 12/31/2006 11:20:00 PM 2006-12-31 23:20:00 1 12/31/2006 11:30:00 PM 2006-12-31 23:30:00 ... 7 12/31/2006 4:45:00 PM 2006-12-31 16:45:00 8 12/31/2006 11:50:00 PM 2006-12-31 23:50:00 9 01/01/2007 2007-01-01 00:00:00
I would create a mask, something like this:
df['valid_time'] = df.raw_dt.str.contains(':')
which should work well here, and you can use regex if you need something more complex. Then create a new time column.
df['time'] = df.ix[df['valid_time'],'formatted_dt'].dt.time raw_dt formatted_dt valid_time time 0 12/31/2006 11:20:00 PM 2006-12-31 23:20:00 True 23:20:00 1 12/31/2006 11:30:00 PM 2006-12-31 23:30:00 True 23:30:00 ... 7 12/31/2006 4:45:00 PM 2006-12-31 16:45:00 True 16:45:00 8 12/31/2006 11:50:00 PM 2006-12-31 23:50:00 True 23:50:00 9 01/01/2007 2007-01-01 00:00:00 False NaN
From there, you can format as you like, for example:
df.formatted_dt.dt.date.map(str) + df.time.map(str).str.rjust(9) 0 2006-12-31 23:20:00 1 2006-12-31 23:30:00 ... 7 2006-12-31 16:45:00 8 2006-12-31 23:50:00 9 2007-01-01 nan
To briefly talk about what date-time is, look here and notice that you can do this as a glimpse of what really is (nano-seconds since January 1, 1970):
df.formatted_dt.astype(np.int64) 0 1167607200000000000 1 1167607800000000000 ... 7 1167583500000000000 8 1167609000000000000 9 1167609600000000000