Datetime field in da.SearchCursor to csv file

1857
9
Jump to solution
03-25-2021 11:51 AM
JoeBorgione
MVP Emeritus

I need to write the output of a search cursor to a csv file.  I stole an idea from this Stackexchange post that uses list comprehension and it works great.  The problem is one of my fields is a date field, and it's goofing up the works. 

import arcpy
fc = r'\Path\to\my\featureclass'
fields = ['UNIQUE_ID','asset_id','Condition','Year_Installed','Carto_ID',
          'Pave_Area','Pave_Width','Length','AM_Asset_ID','Lanes','OCI_Date']
lines = [row for row in arcpy.da.SearchCursor(fc,fields)]

Here is what one of the tuples in the lines list looks like:

 ('10100922','PWOPS_pave00024318',84,1989,7366264,8800.60992698,35.0,
  251.44599791,None,None,  datetime.datetime(2019, 2, 1, 0, 0))

Notice how the field OCI_date comes from the search cursor. I get what it's doing with the datetime.datetime() method, but how can I avoid that?  I guess I could just append every row to the list as individual tuple elements and for the date, format in a fashion that works, but maybe there is a better way?

That should just about do it....
0 Kudos
1 Solution

Accepted Solutions
BlakeTerhune
MVP Regular Contributor
import arcpy
from datetime import datetime

fc = r'\Path\to\my\featureclass'
fields = ['UNIQUE_ID','asset_id','Condition','Year_Installed','Carto_ID',
          'Pave_Area','Pave_Width','Length','AM_Asset_ID','Lanes','OCI_Date']
lines = [dtFormat(row) for row in arcpy.da.SearchCursor(fc,fields)]

def dtFormat(row):
    try:
        OCI_Date_index = row[row.index('OCI_Date')]
        row[OCI_Date_index] = row[OCI_Date_index].strftime('%m/%d/%Y')
        return row
    except AttributeError:
        return row

View solution in original post

9 Replies
BlakeTerhune
MVP Regular Contributor

Try using datetime strftime to format the date as a string in whatever style you want. You should probably do this in a traditional for loop rather than list comprehension.

JoeBorgione
MVP Emeritus

That's what I meant by I guess I could just append every row to the list as individual tuple elements.  I was hoping to keep in the list comprehension format, but I suspect opening an empty list and appending a formatted tuple to it is the only option...

That should just about do it....
0 Kudos
BlakeTerhune
MVP Regular Contributor

You could keep the list comprehension to create lines and then go back over lines with a for loop to format the datetime objects. Or write a helper function to check the value for a date and return the formatted date string during the list comprehension.

BlakeTerhune
MVP Regular Contributor
import arcpy
from datetime import datetime

fc = r'\Path\to\my\featureclass'
fields = ['UNIQUE_ID','asset_id','Condition','Year_Installed','Carto_ID',
          'Pave_Area','Pave_Width','Length','AM_Asset_ID','Lanes','OCI_Date']
lines = [dtFormat(row) for row in arcpy.da.SearchCursor(fc,fields)]

def dtFormat(row):
    try:
        OCI_Date_index = row[row.index('OCI_Date')]
        row[OCI_Date_index] = row[OCI_Date_index].strftime('%m/%d/%Y')
        return row
    except AttributeError:
        return row
JoeBorgione
MVP Emeritus

Sweet.  Thanks!

 

That should just about do it....
0 Kudos
BlakeTerhune
MVP Regular Contributor

Completely untested, but I think you get the idea. 🙂

0 Kudos
RandyBurton
MVP Alum

A wild guess, if you would consider tab delimited:

 

lines = ["\t".join(str(i) for i in row) for row in arcpy.da.SearchCursor("MyFeature",["*"])]

 

You could join with a comma instead of the tab.  Just a quick test in desktop, so it is 2.7 python.

JoshuaBixby
MVP Esteemed Contributor

You could go with a nested list comprehension:

lines = [
    [col.strftime('%m/%d/%Y') if isinstance(col, datetime.datetime) else col for col in row]
    for row
    in arcpy.da.SearchCursor(fc, fields)
]
Luke_Pinner
MVP Regular Contributor

Another way:

 

 

fc = r'path/to/featureclass'
dateformat = '%Y-%m-%d'
datefields = [d.name for d in arcpy.ListFields(fc, field_type='Date')]
recs = []
with arcpy.da.SearchCursor(fc, ['OID@', 'TheDate']) as rows:
    for row in rows:
        recs += [r if f not in datefields else r.strftime(dateformat) for r, f in zip(row, rows.fields)]
print(recs)

 

 

Or as a iterator:

 

def datecursor(fc, dateformat, *args, **kwargs):
    datefields = [d.name for d in arcpy.ListFields(fc, field_type='Date')]
    with arcpy.da.SearchCursor(fc, *args, **kwargs) as rows:
        for row in rows:
            yield [r if f not in datefields else r.strftime(dateformat) for r, f in zip(row, rows.fields)]

fc = r'path/to/featureclass'
dateformat = '%Y-%m-%d'
recs = [row for row in datecursor(fc, dateformat, ['OID@', 'TheDate'])]

 

0 Kudos