Python Buat cap waktu unix lima menit di masa depan

297

Saya harus membuat nilai "Kedaluwarsa" 5 menit di masa mendatang, tetapi saya harus menyediakannya dalam format Timestamp UNIX. Saya punya ini sejauh ini, tetapi sepertinya hack.

def expires():
    '''return a UNIX style timestamp representing 5 minutes from now'''
    epoch = datetime.datetime(1970, 1, 1)
    seconds_in_a_day = 60 * 60 * 24
    five_minutes = datetime.timedelta(seconds=5*60)
    five_minutes_from_now = datetime.datetime.now() + five_minutes
    since_epoch = five_minutes_from_now - epoch
    return since_epoch.days * seconds_in_a_day + since_epoch.seconds

Apakah ada modul atau fungsi yang melakukan konversi stempel waktu untuk saya?

Daniel Rhoden
sumber
7
Saya sarankan untuk mengubah topik pembicaraan. Pertanyaannya bagus, tetapi ini bukan tentang mengubah datetime menjadi cap waktu Unix. Ini tentang bagaimana mendapatkan cap waktu Unix 5 menit di masa depan.
DA
Saya tidak setuju, @DA Pertanyaannya pada dasarnya mengatakan, "Saya perlu melakukan X dan Y. Inilah yang saya miliki sekarang. Apa cara yang lebih baik untuk melakukan Y?" Mungkin ada cara yang lebih baik untuk melakukan X, tetapi judul dan tubuh jelas bertanya tentang Y.
Rob Kennedy
6
Saya setuju dengan Anda sepenuhnya pada pertanyaan, dan saya pikir itu adalah jawaban yang bagus. Masalahnya adalah "Python datetime ke Unix timestamp" tidak mencerminkan pertanyaan atau jawaban. Saya menemukan posting ini sedang mencari cara untuk melakukan konversi, dan saya kehilangan waktu karena baris subjek yang menyesatkan. Saya menyarankan: "Python, 5 menit di masa depan sebagai UNIX Timestamp"
DA
3
@JimmyKane - Jawaban yang cukup komprehensif tentang cara mendapatkan cap waktu dari tanggal dapat ditemukan di sini: stackoverflow.com/questions/8777753/…
Tim Tisdall
@TimTisdall ya karena judulnya diubah tidak masuk akal
Jimmy Kane

Jawaban:

349

Cara lain adalah dengan menggunakan calendar.timegm:

future = datetime.datetime.utcnow() + datetime.timedelta(minutes=5)
return calendar.timegm(future.timetuple())

Ini juga lebih portabel daripada %smenandai ke strftime(yang tidak berfungsi pada Windows).

Cat Plus Plus
sumber
Terima kasih D.Shawley. help (datetime.timedelta) tidak menyebutkan pintasan itu. Itu hanya memiliki hari, detik, dan mikrodetik.
Daniel Rhoden
12
Perhatikan bahwa, menggabungkan sebelumnya dua komentar, solusi yang tepat adalah: calendar.timegm(future.utctimetuple()). Ini memastikan bahwa waktu UTC dilewatkan calendar.timegm.
shadowmatter
1
Tidak dapat mengunggulkan komentar @ tumbleweed cukup. Jika Anda mencoba untuk mendapatkan cap waktu UNIX (dan karenanya satu dalam UTC), gunakan calendar.timegm.
Bialecki
@tumbleweed, benar. Jika Anda menggunakan mktime plus gmtime (0) akan menghasilkan delta pulang-pergi bukan nol untuk zona waktu apa pun selain UTC: mis. `Time.mktime (datetime.fromtimestamp (time.mktime (time.gmtime (0))). Timetuple ())` memberikan 21600.0detik (6 jam) bukannya 0,0 untuk TZ mesin unix saya
hobs
Jika Anda ingin mendapatkan UTC timestamp Anda harus menggunakan ini: calendar.timegm(datetime.datetime.utcnow().timetuple()). Metode menggunakan datetime.datetime.now().utctimetuple()tidak berfungsi untuk saya (Python 3.2).
Wookie88
155

Sekarang dengan Python> = 3.3 Anda bisa memanggil metode timestamp () untuk mendapatkan timestamp sebagai float.

import datetime
current_time = datetime.datetime.now(datetime.timezone.utc)
unix_timestamp = current_time.timestamp() # works if Python >= 3.3

unix_timestamp_plus_5_min = unix_timestamp + (5 * 60)  # 5 min * 60 seconds
Tim Tisdall
sumber
4
+1 untuk ini. Itu harus ditampilkan jauh lebih tinggi, karena itu cara bersih bagaimana melakukannya dengan Python 3
Viktor Stískala
2
@ scott654 Saya pikir memilikinya tepat di awal komentar membuatnya cukup jelas, tetapi saya menambahkan beberapa tebal juga.
Tim Tisdall
1
Saya akan membuat catatan sebagai komentar di blok kode karena kita semua hanya memindai kode dalam jawaban terlebih dahulu dan hanya membaca sisanya jika kodenya terlihat bagus. Jawaban yang bagus.
Matius Purdon
2
waktu setempat mungkin ambigu . Contoh ( datetime.now()) buruk karena mendorong penggunaan objek datetime naif yang mewakili waktu lokal dan mungkin gagal selama transisi DST (karena ambiguitas yang melekat). Anda bisa menggunakannya ts = datetime.now(timezone.utc).timestamp()sebagai gantinya.
jfs
@ JSFSebastian - poin bagus. Saya tidak ingin menambah impor, jadi saya mengubahnya ke utcnow(). Saya sudah terbiasa bekerja dengan mesin di mana zona waktu diatur ke UTC, tetapi itu tidak seharusnya diasumsikan dalam cuplikan kode ini.
Tim Tisdall
139

Baru saja menemukan ini, dan bahkan lebih pendek.

import time
def expires():
    '''return a UNIX style timestamp representing 5 minutes from now'''
    return int(time.time()+300)
Daniel Rhoden
sumber
12
Ini tidak menjawab pertanyaan.
Jesse Dhillon
22
@JesseDhillon menjawab pertanyaan (membuat cap waktu UNIX 5 menit di masa depan), hanya saja bukan judulnya.
dbr
3
time.time()dapat diatur kembali. Untuk membuat nilai "Kedaluwarsa" 5 menit di masa depan, Anda mungkin perlu time.monotonic()analog tergantung pada kasus penggunaan Anda.
jfs
@ jf-sebastian time.monotonic () tidak mengembalikan timestamp UNIX, ia mengembalikan timestamp dengan titik referensi yang tidak ditentukan.
rspeer
@rspeer: ya, seperti yang dikatakan dokumen , hanya perbedaan antara panggilan berurutan yang valid. Apakah monotonicdapat digunakan tergantung pada kasus penggunaan Anda misalnya, subprocessmodul menggunakannya untuk menerapkan timeoutopsi.
jfs
57

Inilah yang Anda butuhkan:

import time
import datetime
n = datetime.datetime.now()
unix_time = time.mktime(n.timetuple())
Ali
sumber
Bagaimana ini berbeda atau menambah yang disediakan 'Cat Plus Plus'?
David
3
EG ini adalah jawaban untuk pertanyaan "datetime Python ke timestamp Unix" sementara Cat Plus Plus menjawab pertanyaan "datetime Python yang akan berada dalam 5 menit ke timestamp Unix". Jadi yang ini bersih dan jelas.
running.t
@ running.t: itu mengingatkan saya: "setiap masalah memiliki solusi yang sederhana, jelas dan salah ". Lihat kemungkinan masalah denganmktime(dt.timetuple()) . datetime.now(timezone.utc).timestamp()disediakan oleh @Tim Tisdall adalah solusi dalam Python 3.3+. Kalau tidak (dt - epoch).total_seconds()bisa digunakan .
jfs
@ JFSebastian bagaimana jika saya benar-benar ingin semua perhitungan dilakukan dalam waktu lokal? Apakah ini terjadi ketika misalnya. untuk mengurai string naif yang diketahui adalah waktu lokal dan memutuskan apakah ada DST yang berlaku pada waktu tertentu?
n611x007
1
@naxa: ya, beberapa waktu lokal bersifat ambigu atau tidak ada. Juga offset zona waktu mungkin berbeda karena alasan selain DST (Anda memerlukan basis data tz seperti pytz, untuk mengetahui offset yang benar). Waktu setempat berarti apa pun yang dipikirkan politisi lokal adalah ide yang baik untuk mengukur waktu, mungkin sangat tidak teratur.
jfs
48

Anda dapat menggunakan datetime.strftimeuntuk mendapatkan waktu dalam bentuk Epoch, menggunakan %sstring format:

def expires():
    future = datetime.datetime.now() + datetime.timedelta(seconds=5*60)
    return int(future.strftime("%s"))

Catatan: Ini hanya berfungsi di linux, dan metode ini tidak bekerja dengan zona waktu.

mipadi
sumber
32
Ini adalah perilaku yang agak tidak berdokumen ( python.org/doc/current/library/datetime.html ). Tampaknya bekerja di bawah linux dan tidak bekerja di bawah win32 (menghasilkan ValueError: Invalid format string).
Antony Hatchkins
3
Metode ini tidak bekerja dengan zona waktu. Mengubah zona waktu akan memberikan datetime hasil yang sama (2013,12,7, tzinfo = timezone ("America / Chicago")). Strftime ("% s") 1386385200 datetime (2013,12,7, tzinfo = timezone ("Eropa / Riga ")). Strftime ("% s ") 1386385200
Martins Balodis
11

Berikut ini adalah datetimesolusi berbasis -kurang rusak untuk mengkonversi dari objek datetime ke posix timestamp:

future = datetime.datetime.utcnow() + datetime.timedelta(minutes=5)
return (future - datetime.datetime(1970, 1, 1)).total_seconds()

Lihat lebih detail di Konversi datetime.date ke stempel waktu UTC dengan Python .

jfs
sumber
6
def in_unix(input):
  start = datetime.datetime(year=1970,month=1,day=1)
  diff = input - start
  return diff.total_seconds()
Sravan
sumber
4

Kuncinya adalah memastikan semua tanggal yang Anda gunakan berada di zona waktu utc sebelum Anda mulai mengonversi. Lihat http://pytz.sourceforge.net/ untuk mempelajari cara melakukannya dengan benar. Dengan menormalkan ke utc, Anda menghilangkan ambiguitas transisi tabungan siang hari. Kemudian Anda dapat menggunakan timedelta dengan aman untuk menghitung jarak dari zaman unix, dan kemudian mengonversi ke detik atau milidetik.

Perhatikan bahwa cap waktu unix yang dihasilkan itu sendiri di zona waktu UTC. Jika Anda ingin melihat cap waktu di zona waktu yang dilokalkan, Anda perlu melakukan konversi lain.

Perhatikan juga bahwa ini hanya akan berfungsi untuk tanggal setelah 1970.

   import datetime
   import pytz

   UNIX_EPOCH = datetime.datetime(1970, 1, 1, 0, 0, tzinfo = pytz.utc)
   def EPOCH(utc_datetime):
      delta = utc_datetime - UNIX_EPOCH
      seconds = delta.total_seconds()
      ms = seconds * 1000
      return ms
fawce
sumber
3
catatan: Saya tidak mengerti "cap waktu [unix] di zona waktu lokal". Stempel waktu sama (berlalu sejak detik 1970-01-01 00:00:00+00:00). Untuk mendapatkan objek datetime naif di zona waktu lokal:datetime.fromtimestamp(ts)
jfs
4

Berikut ini didasarkan pada jawaban di atas (ditambah koreksi untuk milidetik) dan mengemulasi datetime.timestamp()untuk Python 3 sebelum 3,3 ketika zona waktu digunakan.

def datetime_timestamp(datetime):
    '''
    Equivalent to datetime.timestamp() for pre-3.3
    '''
    try:
        return datetime.timestamp()
    except AttributeError:
        utc_datetime = datetime.astimezone(utc)
        return timegm(utc_datetime.timetuple()) + utc_datetime.microsecond / 1e6

Untuk benar-benar menjawab pertanyaan saat ditanyakan, Anda ingin:

datetime_timestamp(my_datetime) + 5 * 60

datetime_timestampadalah bagian dari kencan sederhana . Tetapi jika Anda menggunakan paket itu, Anda mungkin akan mengetik:

SimpleDate(my_datetime).timestamp + 5 * 60

yang menangani lebih banyak format / tipe untuk my_datetime.

andrew cooke
sumber
tidakkah Anda menambahkan (5 * 60) untuk menambah 5 menit? Saya pikir hanya menambahkan 5 menambahkan hanya 5 detik ke timestamp.
Tim Tisdall
1
def expiration_time():
    import datetime,calendar
    timestamp = calendar.timegm(datetime.datetime.now().timetuple())
    returnValue = datetime.timedelta(minutes=5).total_seconds() + timestamp
    return returnValue
hd1
sumber
1

Perhatikan bahwa solusi dengan timedelta.total_seconds()bekerja pada python-2.7 +. Gunakan calendar.timegm(future.utctimetuple())untuk versi Python yang lebih rendah.

mighq
sumber