Làm cách nào tôi có thể chuyển đổi một đối tượng datetime thành mili giây kể từ epoch (thời gian unix) trong Python?


354

Tôi có một datetimeđối tượng Python mà tôi muốn chuyển đổi thành thời gian unix hoặc giây / mili giây kể từ kỷ nguyên 1970.

Làm thế nào để tôi làm điều này?



Nếu bạn hạ cánh ở đây chỉ muốn giây hiện tại với độ chính xác đến mili giây, hãy thử $ python -c 'import time; print(time.time())'đưa ra:1584487455.698623
MarkHu

Câu trả lời:


473

Theo tôi, cách đơn giản nhất để làm điều này là

import datetime

epoch = datetime.datetime.utcfromtimestamp(0)

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

32
Cho đến nay đây là giải pháp tốt nhất (nếu phiên bản python> 2.7). Bởi vì việc thực hiện %sphụ thuộc vào hệ điều hành! Do đó, bất cứ ai cũng muốn mã hoạt động một cách đáng tin cậy bất kể hệ điều hành nào, KHÔNG BAO GIỜ nên sử dụng %s. Cho 2,3 <py ver <2.7. Người ta có thể chỉ cần xây dựng một cái total_seconds()như thế này:delta.days*86400+delta.seconds+delta.microseconds/1e6
Wang

14
lưu ý: dtphải ở UTC (không phải cục bộ). Xem câu trả lời tương tự với hỗ trợ Python 2.6 / 3
jfs

7
Đáng nói là nếu tất cả những gì bạn muốn là dấu thời gian unix đúng như được định nghĩa ở đây en.wikipedia.org/wiki/Unix_time (và do đó sẽ chỉ sử dụng hàm unix_time từ câu trả lời này) thì bạn nên bọc delta.total_seconds () với int để tránh kết thúc với một cuộc nổi
corford

1
epoch được tính bằng cách sử dụng utcfromtimestamp(0)có thể gây ra độ lệch 'tz' chỉ khi 'tz' không bằng 0. Điều này là do dt in dt- epoch'tz' được tính trong đó khi epoch là thời gian UTC. Cách tốt nhất để tính kỷ nguyên là epoch = datetime.datetime(1970, 1, 1)nơi xem xét múi giờ.
ahj

35
Tại sao oh tại sao datetime.utcfromtimestamp(0)trả lại một datetime mà không có tzinfo? Nó có ngay trong tên phương thức, utc fromtimestamp. Để làm cho nó không ngây thơ, tôi phải làm một cái gì đó như thế datetime.utcfromtimestamp(0).replace(tzinfo=pytz.UTC). Điều này là cần thiết nếu dtnhận biết múi giờ nếu không bạn sẽ nhận đượcTypeError: can't subtract offset-naive and offset-aware datetimes
FGreg

170

Trong Python 3.3, đã thêm phương thức mới timestamp:

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

Câu hỏi của bạn nói rằng bạn cần một phần nghìn giây mà bạn có thể nhận được như thế này:

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

Nếu bạn sử dụng timestamptrên một đối tượng datetime ngây thơ, thì nó giả định rằng nó nằm trong múi giờ địa phương. Sử dụng các đối tượng datetime nhận biết múi giờ nếu đây không phải là điều bạn định xảy ra.


28
Lưu ý: .timestamp()phương thức giả định rằng một datetime đầu vào ngây thơ nằm trong múi giờ cục bộ (và giờ địa phương có thể không rõ ràng). Nếu nó ở trong UTC thì sử dụng dt.replace(tzinfo=timezone.utc).timestamp()thay thế .
jfs

11
datetime.timestamp () trả về epoch giây dưới dạng float. Để có được miliseconds: int (datetime.timestamp () * 1000)
Solar.gy

9
Câu trả lời này không phải là một ví dụ sao chép và pasteable, theo tinh thần của các tài liệu un-con người-thân thiện tại docs.python.org/3/library/... --this là: datetime.datetime.timestamp(datetime.datetime.now())
MarkHu

3
Trong 3.6 (ít nhất), datetime.timestamp () giả sử một datetime ngây thơ múi giờ (tzinfo = Không) là trong UTC. Vì vậy, luôn luôn tốt hơn để đặt múi giờ của bạn: datetime.datetime.now(pytz.timezone('Europe/Paris')).timestamp() == datetime.datetime.now(pytz.utc).timestamp() == datetime.datetime.utcnow().timestamp()nhưng không (luôn luôn) bằng datetime.datetime.now().timestamp()(cái cuối cùng này chỉ bằng phần còn lại nếu tz cục bộ là UTC ...)
Bluu

1
Đối với sở thích của bạn, điều ngược lại là] fromtimestamp( docs.python.org/3/l Library / Khăn )
Flimm

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

Hoặc sự trợ giúp của mô-đun thời gian (và không có định dạng ngày):

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

Đã trả lời với sự giúp đỡ từ: http://pleac.sourceforge.net/pleac_python/datesandtimes.html

Tài liệu:


6
Btw, strftime ("% s") trả về một chuỗi trống cho tôi. Cách thứ hai hoạt động tốt.
Pavel Vlasov

23
Chỉ có độ chính xác thứ hai
shuckc

6
'% s' không được Python hỗ trợ, ví dụ, nó có thể vắng mặt trên Windows. .timetuple()trả lại tm_isdst=-1nó buộc mktime()phải đoán. Nó có thể đoán sai trong DST (50% khả năng xảy ra lỗi +/- giờ). Cả '% s' và mktime()có thể sử dụng offset utc sai cho các ngày từ quá khứ. Bạn cần một db múi giờ lịch sử, chẳng hạn như được cung cấp bởi pytzmô-đun để chuyển đổi đáng kể thời gian địa phương sang dấu thời gian POSIX (trừ khi HĐH đã cung cấp db như vậy)
jfs

1
time.mktime(ts.timetuple())Trong đó ts là đối tượng thời gian của python
suhailvs

1
@suhail: đọc bình luận của tôi ở trên về mktime/timetuple. Ngoài ra timetuple()dải phân số của một giây và điểm của câu hỏi là lấy dấu thời gian với độ chính xác mili giây.
jfs


13

Đây là cách tôi làm điều đó:

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
@JFSebastian Cảm ơn những người đứng đầu! thực sự không có dst đang được xem xét. Nếu máy chủ của bạn ở trong giờ địa phương thay vì UTC thì nó sẽ tạo ra sự khác biệt. Tôi chưa tìm thấy (chưa) bất kỳ lý do thuyết phục nào để đặt máy chủ ở bất kỳ nơi nào khác ngoài UTC. Moto của tôi là "viết UTC, đọc giờ địa phương" để bạn luôn biết nơi bạn đang ở ...
estani

2
Bạn luôn có thể sử dụng calendar.timegm thay vì mktime để tránh vấn đề mktime cố gắng đoán múi giờ.
Decko

13

@ChristopherBull Chỉ cần chia số mili giây cho 1000 để có được giây
Jonas

5
Bạn đã hiểu lầm và hiểu sai về nó. Giây đã sẵn sàng trong các chức năng trên. Bạn có thể chuyển đổi nó thành mili giây, nhưng nó sẽ là độ chính xác của một giây.
Christopher Bull

1
Câu trả lời này sử dụng timemô-đun, nhưng OP đã hỏi về datetimemô-đun. FWIW, kỷ nguyên đơn giản nhất hiện tại làint(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()chỉ hoạt động với thời gian utc. Nó không sử dụng tm_isdstdo đó bạn có thể sử dụng utcnow.timetuple()thay vì utcnow.utctimetuple(). Lưu ý: sử dụng naive_local_datetime.utctimetuple()sẽ sai ở đây. Nó không dịch giờ địa phương sang utc. Cũng timetuple()gọi các phân số dải của một giây từ kết quả (cho dù nó quan trọng phụ thuộc vào ứng dụng). Ngoài ra câu hỏi hỏi về * milli * giây, không phải giây
jfs

Tôi thích sử dụng utcnow () và utctimetuple () để làm cho mã hoàn toàn rõ ràng rằng bạn đang giao dịch với UTC (và theo cách này, bất cứ ai đọc nó cũng không phải nhớ rằng timegm chỉ là UTC). utctimetuple () không ngụ ý dịch trên một đối tượng dttm ngây thơ (do đó kích hoạt dttm với utcnow ()). Ngoài ra, câu hỏi đề cập đến giây hoặc mili giây.
corford

Lưu ý: đáng lẽ phải nói trong bình luận cuối cùng tôi đã đọc câu hỏi như ngụ ý anh ta muốn giây hoặc mili giây (có lẽ là lỗi của tôi). Đối với millis chỉ cần nhân với 1000 (như câu trả lời hàng đầu cho thấy).
corford

utctimetuple()dải phân số của một giây. Nhân với 1000sẽ không nhận được chúng trở lại.
jfs

1
Do cách OP hỏi câu hỏi này, nên không rõ chính xác anh ấy / cô ấy muốn gì (tức là dấu thời gian unix thực sự hoặc dấu thời gian với độ chính xác đến mili giây). Bất kể, cả hai câu hỏi đã được hỏi và trả lời ở nơi khác. Phải nói rằng, tôi nghĩ rằng các câu trả lời ở đây là nhanh nhất và sạch nhất để mọi người mò mẫm và làm tốt công việc minh họa các giải pháp khác nhau cho vấn đề.
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/l Library / datetime.html # datetime.date.timetuple

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


3

Đây là một hình thức khác của giải pháp với việc chuẩn hóa đối tượng thời gian của bạn:

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

Một chút mã gấu trúc:

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
Cái này sai! Thời gian biểu không bao gồm mili giây, do đó mktime sẽ không trả về epoch với độ phân giải mili giây. Nó là vô dụng trong trường hợp này.
Vương

@Wang - bạn đúng đấy thưa ngài, điều này không trả về millis, chỉ vài giây
MattoTodd


1
Nếu bạn loại bỏ * 1000, mặc dù, bạn có được seconds_since_epoch. Nâng cao câu trả lời này vì tôi không quan tâm đến mili giây ngay bây giờ.
Michael Scheper

0

Đây là một chức năng tôi đã thực hiện dựa trên câu trả lời ở trên

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

Bạn có thể gói giá trị được trả về như thế này: str (int (res)) Để trả về nó mà không có giá trị thập phân được sử dụng dưới dạng chuỗi hoặc chỉ int (không có str)


-14

Giải pháp khác này cho covert datetime thành 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
Câu hỏi là về ngôn ngữ Python
Stéphane
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.