4 votos

la fecha en el shapefile creado por el módulo python geoespacial parece incorrecto, pero no es

Me di cuenta de algo extraño cuando se mete con el geoespacial de python shapefile módulo (no hay quejas aquí, este módulo es impresionante y la única python puro manera de escribir shapefiles).

Cuando la adición de campos de fecha, los valores parecen estar escrito en la tabla correctamente, pero cuando voy a verlos en cualquier aplicación ArcGIS, las fechas que aparecen mal. El uso de este simple código, voy a añadir una nueva fecha:

import shapefile
from datetime import datetime

test = r'C:\TEMP\Date_test3.shp'

w = shapefile.Writer(1)
w.point(-93.1, 44.1)
w.field('Date', 'D')

# todays date, but appears in table as 12/8/2014....Weird?
today = datetime(2015, 8, 7) #hard coded so the example is always the same
w.records = [[today]]
w.save(test)

Cuando voy en ArcGIS, se ve mal:

enter image description here

También he intentado de entrada como una cadena sin suerte. Sin embargo, el valor que se almacena es la correcta. Cuando leí el shapefile:

# however, when I read it, it is indeed the correct value in the database
r = shapefile.Reader(test)

print r.records()[0][0] 
>>> 
2015-08-07 00:00:00
>>> 

Es allí una manera diferente me debe estar pasando en las fechas para el shapefile módulo? Es esto un error específico para ArcGIS, o es algo diferente ocurre con la forma en que shapefile es la codificación de los datos. También se abrió la .dbf en Excel, y se parece correcto, no demasiado (supongo que esto podría indicar un error con ArcGIS). ¿Alguien sabe qué puede estar pasando?

Estoy utilizando ArcGIS 10.3.

3voto

steveax Puntos 316

Eché un vistazo al código fuente para el shapefile y encontré este (línea 507):

    elif typ == b('D'):
        if value.count(b('0')) == len(value):  # QGIS NULL is all '0' chars
            value = None
        else:
            try:
                y, m, d = int(value[:4]), int(value[4:6]), int(value[6:8])
                value = [y, m, d]
            except:
                value = value.strip()

El shapefile módulo es sólo hacer una simple rebanada en una cadena de fecha, así que soy capaz de conseguir una fecha correcta por entrar en este formato como una cadena: '20150810'.

Al parecer esta es la única manera de pasar de las fechas. Yo no creo que esto es muy útil, así que puede añadir un poco de código y hacer un pull request para permitir datetime objetos y un par de otras opciones de la cadena.

ACTUALIZACIÓN:

Acabo de hacer un fork de este repo en GitHub con la siguiente propuesta de cambios (se incluye aquí por si alguien quiere agregar el código hasta que se la tire de la solicitud es aprobada/o nunca aprobado):

#proposed lines 20-21
import datetime
import re

#proposed line 41
DATE_EXP = re.compile('\d{4}[-/]\d{2}[-/]\d{2}')

if PYTHON3:
    xrange = range
    izip = zip
    basestring = str #proposed line 46

# proposed lines 917-928
elif fieldType == 'D':
    if isinstance(value, datetime.datetime):
        ymd = [str(v).zfill(2) for v in [value.year, value.month, value.day]]
        value = '{0}{1}{2}'.format(*ymd)[:size].ljust(size)
    elif isinstance(value, basestring):
        if DATE_EXP.match(value):
            try:
                value = DATE_EXP.findall(value)[0].replace('/','').replace('-','')[:size].ljust(size)
            except IndexError:
                value = str(value)[:size].ljust(size)
    else:
        value = str(value)[:size].ljust(size)

Con estas fecha de entrada de las mejoras, las fechas de ahora puede ser añadido como datetime.datetime() objetos y las cadenas que coinciden con estos formatos: '2015/08/10', '2015-08-10'.

Así que ahora, puede ejecutar esta nueva prueba y todo es bueno:

import shapefile
from datetime import datetime

test = r'C:\TEMP\Date_test.shp'

w = shapefile.Writer(1)
w.point(-93.1, 44.1)
w.field('Date_obj', 'D') #datetime.datetime() object
w.field('Date_dsh', 'D') #date with a dash
w.field('Date_slsh', 'D') #date with a slash


# now I can input 3 differnt formats
today = datetime.today() 
w.records = [[today, str(today), '2015/08/07']]
w.save(test)

# now all is good!
r = shapefile.Reader(test)

print r.records()[0] 

Este impreso:

[[2015, 8, 10], [2015, 8, 10], [2015, 8, 7]]

Y por último, cuando yo abra la tabla en ArcGIS Desktop:

enter image description here

ÚLTIMA ACTUALIZACIÓN:

Sólo re-examinado mi código, este es mejor:

ymd = ''.join([str(v).zfill(2) for v in [value.year, value.month, value.day]])
value = ymd[:size].ljust(size)

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X