2013-06-09 11 views
6

Sto usando dateutil per analizzare i nomi dei file delle immagini e ordinarli in base alla data. Dato che non tutte le mie foto hanno metadati, dateutil sta cercando di indovinare dove metterle.Python datautil parser, ignora la parte non datata della stringa

La maggior parte delle mie foto sono in questo formato: 2007-09-10_0001.jpg 2007-09-10_0002.jpg ecc ...

fileName = os.path.splitext(file)[0] 
print("Guesssing date from ", fileName) 
try: 
    dateString = dateParser.parse(file, fuzzy=True) 
    print("Guessed date", dateString) 
    year=dateString.year 
    month = dateString.month 
    day=dateString.day 
except ValueError: 
    print("Unable to determine date of ", file) 

Il ritorno sto ottenendo è questo:

('Guesssing date from ', '2007-09-10_00005') 
('Unable to determine date of ', '2007-09-10_00005.jpg') 

Ora dovrei riuscire a rimuovere tutto da dopo il trattino basso, ma se possibile ho desiderato una soluzione più robusta, nel caso avessi delle immagini in un altro formato. Anche se sfocato proverei a trovare qualsiasi data nella stringa e corrispondere a quello, ma apparentemente non funziona ...

C'è un modo semplice per ottenere il parser per trovare qualcosa che assomiglia ad una data e fermarsi dopo? In caso contrario, qual è il modo più semplice per forzare il parser a ignorare tutto dopo il trattino basso? O un modo per definire più formati di data con sezioni ignorate.

Grazie!

+0

è la tua data almeno qualche modo formattato? Come "yyyy-mm-dd da qualche parte nel nome del file"? – mishik

+0

Ciò che intendo è che a volte non è possibile distinguere mese e data se il formato della data è aaaa-gg-mm o aaaa-mm-gg. – mishik

+0

@mishik Sì, di solito è qualcosa come "2007-09-10" in un nome file completo di "2007-09-10_001". Se rimuovo il "_001" dalla stringa, riconosce correttamente la data. – deranjer

risposta

4

si può provare a "ridurre" la stringa finché non si può decodificarlo:

from dateutil import parser 

def reduce_string(string): 
    i = len(string) - 1 
    while string[i] >= '0' and string[i] < '9': 
     i -= 1 
    while string[i] < '0' or string[i] > '9': 
     i -= 1 
    return string[:i + 1] 

def find_date(string): 
    while string: 
     try: 
      dateString = parser.parse(string, fuzzy=True) 
      year = dateString.year 
      month = dateString.month 
      day = dateString.day 
      return (year, month, day) 
     except ValueError: 
      pass 

     string = reduce_string(string) 

    return None 

date = find_date('2007-09-10_00005') 
if date: 
    print date 
else: 
    print "can't decode" 

L'idea è quella di rimuovere la fine della stringa (tutti i numeri poi eventuali non numeri) fino il parser può decodificarlo in una data valida.

+0

Grazie! Sembra che questa sia la soluzione migliore per me, anche grazie per aver scritto il codice .. molto nuovo per Python (e per la programmazione) e che mi avrebbe richiesto un po 'per capire: D – deranjer

2

Commentando dal futuro qui, come ulteriori informazioni su questo problema.

Mentre la ricerca fuzzy di dateutil è abbastanza buona per raccogliere le date nel normale linguaggio naturale, non riesce a stringhe come quella sopra con tonnellate di rumore numerico/relativo al simbolo. Con le versioni più recenti di dateutil, tuttavia, quando in esecuzione:

>>> from dateutil.parser import parse 
>>> parse('2007-09-10_00005.jpg', fuzzy=True) 

parse fallisce con TypeError: 'NoneType' object is not iterable, che non è molto idiomatica.

Un'altra alternativa è semplicemente la ricerca del formato data noto mediante regex. Naturalmente, questo varia a seconda del caso d'uso, ma OP ha detto che la sua data è stata sempre nel formato YYYY-MM-DD, che lo rende ideale per una ricerca regex:

from dateutil.parser import parse 
import re 

date_pattern = re.compile('\d{4}-\d{2}-\d{2}') 

def extract_date(filename): 
    matches = re.match(date_pattern, filename) 
    if matches: 
     return parse(matches.group(0)) 
    else: 
     return None 

extract_date('2007-09-10_00005.jpg') # datetime.datetime(2007, 9, 10, 0, 0) 
Problemi correlati