Bagaimana saya bisa mengkonversi objek datetime menjadi milidetik sejak zaman (waktu unix) dengan Python?


354

Saya memiliki datetimeobjek Python yang ingin saya konversi ke waktu unix, atau detik / milidetik sejak era 1970-an.

Bagaimana saya melakukan ini?



Jika Anda mendarat di sini hanya ingin detik saat ini dengan presisi milidetik, coba $ python -c 'import time; print(time.time())'yang memberi:1584487455.698623
MarkHu

Jawaban:


473

Tampak bagi saya bahwa cara paling sederhana untuk melakukan ini adalah

import datetime

epoch = datetime.datetime.utcfromtimestamp(0)

def unix_time_millis(dt):
    return (dt - epoch).total_seconds() * 1000.0

32
Sejauh ini ini adalah solusi terbaik (jika versi python> 2.7). Karena implementasi %stergantung pada OS! Jadi siapa pun yang ingin kode bekerja dengan andal terlepas dari OS yang mana, TIDAK PERNAH digunakan %s. Untuk 2,3 <py ver <2,7. Orang dapat dengan mudah membangun total_seconds()seperti ini:delta.days*86400+delta.seconds+delta.microseconds/1e6
Wang

14
catatan: dtharus dalam UTC (bukan lokal). Lihat jawaban serupa dengan dukungan Python 2.6 / 3
jfs

7
Layak disebutkan bahwa jika semua yang Anda inginkan adalah cap waktu unix yang benar seperti yang didefinisikan di sini en.wikipedia.org/wiki/Unix_time (dan hanya akan menggunakan fungsi unix_time dari jawaban ini) maka Anda harus membungkus delta.total_seconds () dengan int to hindari berakhir dengan float
corford

1
zaman dihitung menggunakan utcfromtimestamp(0)dapat menyebabkan offset 'tz' hanya jika 'tz' tidak 0. Ini karena dt di dt- epoch'tz' telah dihitung di dalamnya di mana sebagai zaman adalah waktu UTC. Cara terbaik untuk menghitung zaman adalah di epoch = datetime.datetime(1970, 1, 1)mana zona waktu dipertimbangkan.
ahj

35
Mengapa oh mengapa datetime.utcfromtimestamp(0)mengembalikan datetime tanpa tzinfo? Itu ada di sana dalam nama metode, utc fromtimestamp. Untuk membuatnya non-naif saya harus melakukan sesuatu seperti datetime.utcfromtimestamp(0).replace(tzinfo=pytz.UTC). Ini diperlukan jika dtzona waktu sadar atau Anda akan mendapatkanTypeError: can't subtract offset-naive and offset-aware datetimes
FGreg

170

Dalam Python 3.3, menambahkan metode baru timestamp:

import datetime
seconds_since_epoch = datetime.datetime.now().timestamp()

Pertanyaan Anda menyatakan bahwa Anda membutuhkan milidetik, yang bisa Anda dapatkan seperti ini:

milliseconds_since_epoch = datetime.datetime.now().timestamp() * 1000

Jika Anda menggunakan timestampobjek datetime yang naif, maka diasumsikan bahwa objek tersebut berada dalam zona waktu lokal. Gunakan objek datetime sadar-waktu jika ini bukan yang Anda inginkan.


28
Catatan: .timestamp()metode mengasumsikan bahwa datetime input naif berada di zona waktu lokal (dan waktu lokal mungkin ambigu). Jika di UTC maka gunakan dt.replace(tzinfo=timezone.utc).timestamp()saja .
jfs

11
datetime.timestamp () mengembalikan detik sebagai float. Untuk memperoleh milidetik: int (datetime.timestamp () * 1000)
Solar.gy

9
Jawaban ini bukan contoh salin-dan-tempel, dalam semangat dokumen yang tidak ramah terhadap manusia di docs.python.org/3/library/… --ini adalah: datetime.datetime.timestamp(datetime.datetime.now())
MarkHu

3
Dalam 3.6 (setidaknya), datetime.timestamp () mengasumsikan datzone naif (tzinfo = Tidak Ada) datetime dalam UTC. Jadi selalu lebih baik untuk menetapkan zona waktu Anda: datetime.datetime.now(pytz.timezone('Europe/Paris')).timestamp() == datetime.datetime.now(pytz.utc).timestamp() == datetime.datetime.utcnow().timestamp()tetapi tidak (selalu) sama dengan datetime.datetime.now().timestamp()(yang terakhir ini hanya sama dengan yang lain jika tz lokalnya adalah UTC ...)
Bluu

1
Untuk kepentingan Anda, kebalikannya adalah] fromtimestamp( docs.python.org/3/library/… )
Flimm

98
>>> import datetime
>>> # replace datetime.datetime.now() with your datetime object
>>> int(datetime.datetime.now().strftime("%s")) * 1000 
1312908481000

Atau bantuan modul waktu (dan tanpa format tanggal):

>>> import datetime, time
>>> # replace datetime.datetime.now() with your datetime object
>>> time.mktime(datetime.datetime.now().timetuple()) * 1000
1312908681000.0

Dijawab dengan bantuan dari: http://pleac.sourceforge.net/pleac_python/datesandtimes.html

Dokumentasi:


6
Btw, strftime ("% s") mengembalikan string kosong untuk saya. Cara kedua berfungsi dengan baik.
Pavel Vlasov

23
Hanya memiliki akurasi kedua
shuckc

6
'% s' tidak didukung oleh Python misalnya, mungkin tidak ada di Windows. .timetuple()mengembalikannya tm_isdst=-1memaksa mktime()untuk menebak. Mungkin salah menebak selama DST (kemungkinan kesalahan 50% +/- jam). Keduanya '% s' dan mktime()dapat menggunakan offset utc yang salah untuk tanggal dari masa lalu. Anda memerlukan db zona waktu historis seperti yang disediakan oleh pytzmodul untuk secara andal mengubah waktu setempat ke stempel waktu POSIX (kecuali OS sudah menyediakan db tersebut)
jfs

1
time.mktime(ts.timetuple())di mana ts adalah objek
datime

1
@suhail: baca komentar saya di atas tentang mktime/timetuple. Juga timetuple()strip pecahan detik dan titik pertanyaannya adalah untuk mendapatkan cap waktu dengan presisi milidetik.
jfs


13

Beginilah cara saya melakukannya:

from datetime import datetime
from time import mktime

dt = datetime.now()
sec_since_epoch = mktime(dt.timetuple()) + dt.microsecond/1000000.0

millis_since_epoch = sec_since_epoch * 1000


2
@ JSFSebastian Terima kasih atas pimpinannya! memang tidak ada yang dipertimbangkan. Jika server Anda dalam waktu lokal bukan UTC maka itu akan membuat perbedaan. Saya belum menemukan alasan kuat untuk mengatur server selain dari UTC. Moto saya adalah "tulis UTC, baca waktu setempat" sehingga Anda tahu selalu di mana Anda tinggal ...
estani

2
Anda selalu dapat menggunakan calendar.timegm alih-alih mktime untuk menghindari masalah mktime mencoba menebak zona waktu.
Decko

13

@ChristopherBull Hanya membagi jumlah milidetik dengan 1000 untuk mendapatkan detik
Jonas

5
Anda salah paham dan mendapatkannya dengan cara yang salah. Detik semua siap tersedia dalam fungsi di atas. Anda dapat mengonversinya menjadi milidetik, tetapi akan menjadi presisi satu detik.
Christopher Bull

1
Jawaban ini menggunakan timemodul, tetapi OP bertanya tentang datetimemodul. FWIW, zaman sekarang yang paling sederhana adalahint(time.time())
MarkHu

7
from datetime import datetime
from calendar import timegm

# Note: if you pass in a naive dttm object it's assumed to already be in UTC
def unix_time(dttm=None):
    if dttm is None:
       dttm = datetime.utcnow()

    return timegm(dttm.utctimetuple())

print "Unix time now: %d" % unix_time()
print "Unix timestamp from an existing dttm: %d" % unix_time(datetime(2014, 12, 30, 12, 0))

timegm()hanya bekerja dengan waktu utc. Tidak menggunakan tm_isdstkarena itu Anda bisa menggunakan utcnow.timetuple()bukan utcnow.utctimetuple(). Catatan: menggunakan naive_local_datetime.utctimetuple()salah di sini. Itu tidak menerjemahkan waktu lokal ke utc. timetuple()Panggil juga pecahan sepersekian detik dari hasil (apakah itu penting tergantung pada aplikasi). Juga pertanyaannya tentang * mili * detik, bukan detik
jfs

Saya lebih suka menggunakan utcnow () dan utctimetuple () untuk membuat kode benar-benar jelas bahwa Anda berurusan dengan UTC (dan dengan cara ini siapa pun yang membacanya tidak harus ingat bahwa timegm hanya UTC). utctimetuple () tidak menyiratkan terjemahan pada objek dttm yang naif (karenanya menginttttttttttttttttttttttttttttttttttttttttttt%% dp% d% d%%%%%%%%%% sdn%%%%%%%%%%%%%%%%%%%% %sil%,%,%,%,%,%,%,%,,,,,,,,,,,,,,,,, maksudnya, ini tidak menyiratkan terjemahan pada objek DLT yang naif (karena itu memulai DLT dengan utcnow ()). Juga, pertanyaan disebutkan detik atau milidetik.
Corford

Catatan: seharusnya mengatakan dalam komentar terakhir saya membaca pertanyaan menyiratkan dia ingin detik atau milidetik (mungkin kesalahan saya). Untuk millis, kalikan dengan 1000 (seperti yang disarankan oleh skor penilaian teratas).
Corford

utctimetuple()strip pecahan detik. Mengalikan dengan 1000tidak akan mendapatkannya kembali.
jfs

1
Karena cara OP mengajukan pertanyaan ini, tidak jelas apa yang dia inginkan (yaitu cap waktu unix yang sebenarnya atau cap waktu dengan akurasi milidetik). Apapun, kedua pertanyaan sudah ditanyakan dan dijawab di tempat lain. Karena itu, saya pikir jawabannya di sini adalah yang tercepat dan terbersih bagi orang untuk melakukan grok dan melakukan pekerjaan yang bagus dalam menggambarkan berbagai solusi untuk masalah tersebut.
Corford

3
>>> import datetime
>>> import time
>>> import calendar

>>> #your datetime object
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2013, 3, 19, 13, 0, 9, 351812)

>>> #use datetime module's timetuple method to get a `time.struct_time` object.[1]
>>> tt = datetime.datetime.timetuple(now)
>>> tt
time.struct_time(tm_year=2013, tm_mon=3, tm_mday=19, tm_hour=13, tm_min=0, tm_sec=9,     tm_wday=1, tm_yday=78, tm_isdst=-1)

>>> #If your datetime object is in utc you do this way. [2](see the first table on docs)
>>> sec_epoch_utc = calendar.timegm(tt) * 1000
>>> sec_epoch_utc
1363698009

>>> #If your datetime object is in local timeformat you do this way
>>> sec_epoch_loc = time.mktime(tt) * 1000
>>> sec_epoch_loc
1363678209.0

[1] http://docs.python.org/2/library/datetime.html#datetime.date.timetuple

[2] http://docs.python.org/2/library/time.html


3

Berikut ini bentuk lain dari solusi dengan normalisasi objek waktu Anda:

def to_unix_time(timestamp):
    epoch = datetime.datetime.utcfromtimestamp(0) # start of epoch time
    my_time = datetime.datetime.strptime(timestamp, "%Y/%m/%d %H:%M:%S.%f") # plugin your time object
    delta = my_time - epoch
    return delta.total_seconds() * 1000.0

2

Sedikit kode panda:

import pandas

def to_millis(dt):
    return int(pandas.to_datetime(dt).value / 1000000)

1
import time
seconds_since_epoch = time.mktime(your_datetime.timetuple()) * 1000

9
Ini salah! Jadwal waktu tidak termasuk milidetik, sehingga mktime tidak akan mengembalikan zaman dengan resolusi milidetik. Tidak ada gunanya dalam kasus ini.
Wang

@ Wang - Anda benar, ini tidak mengembalikan milis, hanya beberapa detik
MattoTodd


1
Jika Anda menghapus * 1000, Anda memang mendapatkannya seconds_since_epoch. Menanggapi jawaban ini karena saya tidak peduli dengan milidetik sekarang.
Michael Scheper

0

Berikut adalah fungsi yang saya buat berdasarkan jawaban di atas

def getDateToEpoch(myDateTime):
    res = (datetime.datetime(myDateTime.year,myDateTime.month,myDateTime.day,myDateTime.hour,myDateTime.minute,myDateTime.second) - datetime.datetime(1970,1,1)).total_seconds()
    return res

Anda dapat membungkus nilai yang dikembalikan seperti ini: str (int (res)) Untuk mengembalikannya tanpa nilai desimal untuk digunakan sebagai string atau hanya int (tanpa str)


-14

Ini solusi lain untuk datetime rahasia untuk unixtimestampmillis.

private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    public static long GetCurrentUnixTimestampMillis()
    {
        DateTime localDateTime, univDateTime;
        localDateTime = DateTime.Now;          
        univDateTime = localDateTime.ToUniversalTime();
        return (long)(univDateTime - UnixEpoch).TotalMilliseconds;
    } 

2
Pertanyaannya adalah tentang bahasa Python
Stéphane
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.