4

I have created a python function within field calculator to calculate the time difference between a timestamp (yyyy-MM-dd HH:mm:ss) in a row and the row after (the interval field in seconds). I have used a update cursor with field calculator to do this, however I am receiving null values for both the first and last row.

The first is correctly missed due to the function being reliant on having a value set by the previous row.

I am unsure as to why the last row is being skipped?

The first row of the attribute is formatted as:

First row

The last:

Last row

I have had this issue on several other update cursor functions including those on simple single row condition statements.

Am I missing a statement to close the update cursor loop?

My code is:

import arcpy, time, datetime
from time import strftime
from datetime import timedelta, datetime
from arcpy import da

def FindTime(table,date,interval):

  firstRow = True

  with arcpy.da.UpdateCursor(table, ["interval", "date"]) as cursor:

    for row in cursor:
        gap2 = row[1]

        if firstRow == True:
            gap1 = gap2
            firstRow = False
            continue
        timedelta = gap2 - gap1
        row[0] = timedelta.days * 24 * 3600 + timedelta.seconds
        gap1 = gap2         
        cursor.updateRow(row)

*Updated from below comment's solution:

import arcpy
def FindTime(fc, datefield, daydiff_field):

    all_dates = [i[0] for i in     arcpy.da.SearchCursor(fc,datefield)]

    diff = [(d1-d0).seconds for d0,d1 in zip(all_dates, all_dates[1:])]
    givediff = iter(diff)

    with arcpy.da.UpdateCursor(fc, daydiff_field) as cursor:
        next(cursor) #uncomment this line if you want to calculate row2 diff as row2-row1, =first row no diff
        for row in cursor:
            try:
                row[0] = next(givediff) #Fetch diffs until list is empty...
                cursor.updateRow(row)
            except StopIteration: #...then break the cursor
                break
  • 1
    There is no row[2] in your first try, you only have two fields. Are you trying to fetch the value from next row? That is not possible – BERA Apr 9 at 19:23
  • Edited pasting to SE typo! – Will Apr 10 at 9:42
4

If your field is type date, code below should work. Last line is not calculated since there is no row after. Or do you want to calculate for example second rows diff as second row-first row?

import arcpy

fc = 'somedates'
datefield = 'date123'
daydiff_field = 'seconddiff_long'

all_dates = [i[0] for i in arcpy.da.SearchCursor(fc,datefield)]

diff = [(d1-d0).seconds for d0,d1 in zip(all_dates, all_dates[1:])]
givediff = iter(diff)

with arcpy.da.UpdateCursor(fc, daydiff_field) as cursor:
#next(cursor) #uncomment this line if you want to calculate row2 diff as row2-row1, =first row no diff
    for row in cursor:
        try:
            row[0] = next(givediff) #Fetch diffs until list is empty...
            cursor.updateRow(row)
        except StopIteration: #...then break the cursor
            break

enter image description here

  • 3
    This is why I love using SE, I have never used the iter() function before, had to go away and look it up, like it! Is there a performance boost using that approach or was it for convenience? – Hornbydd Apr 9 at 10:29
  • 3
    Nice! Dont know if there is a performance boost. I use it because it is a simple way of fetching items in a list instead of trying to iterate over a cursor and list at the same time. – BERA Apr 9 at 10:31
  • 2
    If anything, it will actually be slower, because the table is traversed twice instead of once. But for small tables that may not be an issue. – Berend Apr 9 at 12:52
  • 1
    Slower than what approach? – BERA Apr 9 at 12:54
  • 1
    Slower than using just an update cursor, as OP does – Berend Apr 9 at 12:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.