2014-10-02 18 views
9

vorrei convertire stringa di formato della data di timestamp con i microsecondi ho provare quanto segue, ma non dare risultato atteso:Python: La conversione di stringa per data con microsecondi

"""input string date -> 2014-08-01 04:41:52,117 
expected result -> 1410748201.117""" 

import time 
import datetime 

myDate = "2014-08-01 04:41:52,117" 
timestamp = time.mktime(datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timetuple()) 

print timestamp 
> 1410748201.0 

Dove sono finiti i millisecondi andare?

+0

la data di inserimento (2014-08-01) non corrisponde al timestamp (2014-09-15 02: 30: 01.117Z) – jfs

risposta

12

non ci sono slot per la componente microsecondi in una tupla tempo:

>>> import time 
>>> import datetime 
>>> myDate = "2014-08-01 04:41:52,117" 
>>> datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timetuple() 
time.struct_time(tm_year=2014, tm_mon=8, tm_mday=1, tm_hour=4, tm_min=41, tm_sec=52, tm_wday=4, tm_yday=213, tm_isdst=-1) 

dovrete aggiungere manualmente quelli:

>>> dt = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f") 
>>> time.mktime(dt.timetuple()) + (dt.microsecond/1000000.0) 
1406864512.117 

L'altro metodo si potrebbe seguire è quello di produrre un timedelta() object relativa all'epoca, quindi ottenere il timestamp con la timedelta.total_seconds() method:

epoch = datetime.datetime.fromtimestamp(0) 
(dt - epoch).total_seconds() 

L'utilizzo di un'ora locale è piuttosto deliberato poiché si dispone di un valore datetime ingenuo (non sensibile al fuso orario). Questo metodo può essere impostato su in base alla cronologia del fuso orario locale, tuttavia, vedere J.F. Sebastian's comment. Dovresti convertire il valore datetime ingenuo in un valore datetime timezone-aware prima di utilizzare il fuso orario locale prima di sottrarre un'epoca sensibile al fuso orario.

Come tale, è più semplice attenersi all'approccio timetuple() + microsecondi.

Demo:

>>> dt = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f") 
>>> epoch = datetime.datetime.fromtimestamp(0) 
>>> (dt - epoch).total_seconds() 
1406864512.117 
+0

** 1 ** '(dt - epoch)' non è corretto se ' dt' è un'ingenua ora locale. L'ora locale può essere ripristinata (transizione dell'ora legale nell'autunno dell'emisfero settentrionale). Il timestamp dovrebbe ** non ** essere ripristinato in questo caso. ** 2 ** Anche "epoca dell'ora locale" potrebbe essere fuorviante. L'epoca è un'istanza * single * time (1970 per Python) - è la stessa in tutto il mondo. Se la libreria C supporta un database storico del fuso orario o l'UTC per il fuso orario locale ha lo stesso valore al momento, quindi 'datetime.fromtimestamp (0)' restituisce l'ora locale corrispondente all'epoca. – jfs

+0

@ J.F.Sebastian: il valore 'epoch' utilizza' fromtimestamp() ', non' utcfromtimestamp() ', per gestire la differenza dell'ora legale, proprio perché il valore' dt' è ingenuo. –

+0

@ J.F.Sebastian: Avevo usato 'utcfromtimestamp()' invece, dovevo prima rendere noto 'dt' timezone e quindi permettere a Python di compensare i problemi dell'ora legale. –

2

Dove sono finiti i millisecondi andare?

È la parte facile. La chiamata .timetuple() li fa cadere. Puoi aggiungerli di nuovo usando l'attributo .microsecond. Il datetime.timestamp() method from the standard library funziona in questo modo per gli oggetti datetime ingenui:

def timestamp(self): 
    "Return POSIX timestamp as float" 
    if self._tzinfo is None: 
     return _time.mktime((self.year, self.month, self.day, 
          self.hour, self.minute, self.second, 
          -1, -1, -1)) + self.microsecond/1e6 
    else: 
     return (self - _EPOCH).total_seconds() 

E 'sufficiente, se possibile, ~ 1 ora errori potevano essere ignorati nel tuo caso. Suppongo che tu voglia dei microsecondi e quindi non puoi ignorare silenziosamente gli errori di un'ora circa.

Per convertire correttamente l'ora locale fornita come stringa in POSIX in modo corretto, è un'operazione complessa in generale. È possibile convertire l'ora locale in UTC e quindi get the timestamp from UTC time.

Ci sono due questioni principali:

Entrambi possono essere risolti utilizzando il database tz (pytz modulo in Python) :

from datetime import datetime 
import pytz # $ pip install pytz 
from tzlocal import get_localzone # $ pip install tzlocal 

tz = get_localzone() # get pytz timezone corresponding to the local timezone 

naive_d = datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f") 
# a) raise exception for non-existent or ambiguous times 
d = tz.localize(naive_d, is_dst=None) 
## b) assume standard time, adjust non-existent times 
#d = tz.normalize(tz.localize(naive_d, is_dst=False)) 
## c) assume DST is in effect, adjust non-existent times 
#d = tz.normalize(tz.localize(naive_d, is_dst=True)) 
timestamp = d - datetime(1970, 1, 1, tzinfo=pytz.utc) 

Il risultato è timestamp - un oggetto timedelta, è possibile convertirlo in secondi, millisecondi, ecc

anche diversi sys i valori possono comportarsi in modo diverso intorno/durante i secondi bisestili. La maggior parte delle applicazioni può ignorare che esistono.

In generale, potrebbe essere più semplice memorizzare i timestamp POSIX in aggiunta a all'ora locale invece di provare a indovinarlo dall'ora locale.

+0

Nota: 'datetime.timestamp' è disponibile solo in Python 3; l'OP sta usando Python 2 (a giudicare dalle istruzioni 'print'). –

+0

@MartijnPieters: non ho * suggerito * di usare il metodo '.timestamp()'. Lo uso solo come esempio di implementazione (imperfetta). – jfs

+0

Non volevo suggerire di averlo fatto. Sto solo facendo notare che il metodo non esiste in Python 2. –

1

In Python 3.4 e versioni successive è possibile utilizzare

timestamp = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timestamp() 

Ciò non richiede l'importazione del modulo time. Utilizza anche meno passaggi quindi dovrebbe essere più veloce. Per le versioni precedenti di python le altre risposte fornite sono probabilmente la scelta migliore.

Problemi correlati