ใน Python คุณจะแปลงวัตถุ `datetime 'เป็นวินาทีได้อย่างไร


226

ขอโทษด้วยคำถามง่ายๆ ... ฉันยังใหม่กับ Python ... ฉันค้นหาไปแล้วและดูเหมือนว่าไม่มีอะไรทำงาน

ฉันมีวัตถุ datetime จำนวนมากและฉันต้องการคำนวณจำนวนวินาทีตั้งแต่เวลาที่กำหนดในอดีตสำหรับแต่ละรายการ (ตัวอย่างเช่นตั้งแต่วันที่ 1 มกราคม 1970)

import datetime
t = datetime.datetime(2009, 10, 21, 0, 0)

สิ่งนี้ดูเหมือนจะแตกต่างระหว่างวันที่ที่มีวันแตกต่างกัน:

t.toordinal()

ความช่วยเหลือใด ๆ ที่ชื่นชมมาก


ที่เกี่ยวข้อง: การแปลงdatetime.dateเวลาประทับ UTC ใน Python
jfs

2
ฉันอาจแปลงทั้งสองเป็น S ตั้งแต่int(t.timestamp())
กาล

สำหรับการดำเนินการที่ตรงกันข้ามไปที่นี่: แปลงวินาทีตั้งแต่ตั้งแต่ยุค - ต่อ - วันที่ - วัตถุ
เทรเวอร์บอยด์สมิ ธ

คำตอบ:


233

สำหรับวันพิเศษ 1 มกราคม 1970 มีหลายตัวเลือก

สำหรับวันที่เริ่มต้นอื่นคุณต้องได้รับความแตกต่างระหว่างวันที่สองในไม่กี่วินาที การลบสองวันให้timedeltaวัตถุซึ่งเป็น Python 2.7 มีtotal_seconds()ฟังก์ชั่น

>>> (t-datetime.datetime(1970,1,1)).total_seconds()
1256083200.0

วันที่เริ่มต้นมักจะถูกระบุใน UTC ดังนั้นสำหรับผลลัพธ์ที่ถูกต้องdatetimeฟีดที่คุณป้อนลงในสูตรนี้ควรเป็น UTC เช่นกัน หากคุณdatetimeไม่ได้อยู่ใน UTC คุณจะต้องแปลงก่อนที่จะใช้หรือแนบtzinfoคลาสที่มีออฟเซ็ตที่เหมาะสม

ดังที่ระบุไว้ในความคิดเห็นหากคุณมีไฟล์tzinfoแนบอยู่datetimeคุณจะต้องใช้วันที่เริ่มต้นเช่นกันการลบจะล้มเหลว สำหรับตัวอย่างข้างต้นฉันจะเพิ่มtzinfo=pytz.utcถ้าใช้ Python 2 หรือtzinfo=timezone.utcถ้าใช้ Python 3


1
Python เตือนฉันว่า: "TypeError: ไม่สามารถลบชุดข้อมูลตรงข้ามที่ไร้เดียงสาและออฟเซ็ตที่รับรู้ได้" วิธีแก้ไขปัญหาที่ดีที่สุดคืออะไร
Aaron Ash

2
@Charybdis datetime.datetime(1970,1,1,tzinfo=pytz.utc)ลอง
Mark Ransom

9
ลองใช้: datetime.datetime.utcfromtimestamp(0) ฉันเคยใช้สิ่งนี้เพื่อให้ 'ยุค' ง่ายขึ้น โปรดทราบว่ายุคนี้อาจไม่เหมือนกันในทุกระบบ
DA

3
ระวังด้วยเขตเวลาที่นี่ ฉันอยู่ที่ UTC + 2 ซึ่งหมายความว่าการส่งออกtime.time()และdatetime.now() - datetime(1970, 1, 1)แตกต่าง 7200 วินาที (t - datetime.datetime.fromtimestamp(0)).total_seconds()แต่การใช้งาน ไม่ได้ใช้utcfromtimestamp(0)ถ้าคุณต้องการแปลง datetime ในเขตเวลาท้องถิ่นของคุณ
Carl

2
@DA: งูหลามไม่สนับสนุน epochs ระบบทั้งหมดที่ python ใช้งานได้ในยุคเดียวกัน: 1970-01-01 00:00:00 UTC
jfs

130

ในการรับเวลา Unix (วินาทีตั้งแต่วันที่ 1 มกราคม 1970):

>>> import datetime, time
>>> t = datetime.datetime(2011, 10, 21, 0, 0)
>>> time.mktime(t.timetuple())
1319148000.0

22
ระวังเมื่อใช้ time.mktime เนื่องจากเป็นเวลาท้องถิ่นและขึ้นอยู่กับแพลตฟอร์ม
Shih-Wen Su

7
ระวังตัวด้วย มันทำให้ฉันกลายเป็นเรื่องใหญ่สำหรับฉัน
Arg

ถือว่าtเป็นเวลาท้องถิ่น UTC offset สำหรับเขตเวลาท้องถิ่นอาจมีความแตกต่างในอดีตและหากmktime()(ไลบรารี่ C) ไม่สามารถเข้าถึงข้อมูลเขตเวลาเชิงประวัติบนแพลตฟอร์มที่กำหนดได้อาจจะล้มเหลว ( pytzเป็นวิธีพกพาในการเข้าถึงฐานข้อมูล tz) นอกจากนี้เวลาท้องถิ่นอาจไม่ชัดเจนเช่นในระหว่างการเปลี่ยน DST - คุณต้องการข้อมูลเพิ่มเติมเพื่อทำให้เข้าใจผิดเช่นหากคุณรู้ว่าค่าวันที่ / เวลาติดต่อกันควรเพิ่มขึ้นในไฟล์บันทึก
jfs

1
ระวังเมื่อใช้สิ่งนี้กับเวลาที่มีเศษส่วนของวินาที time.mktime(datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timetuple())ส่งผล1564819506.0ให้ลดมิลลิวินาทีอย่างเงียบ ๆ แต่datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timestamp()(คำตอบของ Andrzej Pronobis) ทำให้ได้ผลลัพธ์1564819506.912ที่คาดหวัง
อเล็กซ์

128

เริ่มต้นจาก Python 3.3 วิธีนี้กลายเป็นเรื่องง่ายสุดdatetime.timestamp()ๆ หลักสูตรนี้จะมีประโยชน์ถ้าคุณต้องการจำนวนวินาทีจาก 1970-01-01 UTC

from datetime import datetime
dt = datetime.today()  # Get timezone naive now
seconds = dt.timestamp()

ค่าส่งคืนจะเป็นทศนิยมที่แสดงถึงเศษส่วนของวินาที หากวันที่และเวลาเป็นเขตเวลาไร้เดียงสา (ดังตัวอย่างข้างต้น) จะถือว่าสันนิษฐานว่าวัตถุวันที่และเวลาเป็นเวลาท้องถิ่นนั่นคือจำนวนวินาทีจากเวลาปัจจุบัน ณ สถานที่ของคุณถึง 1970-01-01 UTC


3
ใครก็ตามที่ลงคะแนนในเรื่องนี้คุณช่วยอธิบายได้ไหม
Andrzej Pronobis

5
ฉันคิดว่า downvote เกิดจากแท็ก python-2.7 ในคำถาม (เป็นเพียงการเดา)
jfs

3
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ / คำตอบที่ได้รับการยอมรับควรได้รับการอัปเดตตามนั้น
DreamFlasher

11
ถึงเวลาอัพเกรดแล้วฉันเดา;)
DreamFlasher

เป็นไปได้ในการคำนวณระยะทางจากวันที่เริ่มต้นอื่นหรือไม่ (ฉันหมายถึงเปลี่ยนวันที่ 1970-01-01)
pellerossa pelles

29

อาจเป็นเรื่องนอกหัวข้อ: เพื่อรับเวลา UNIX / POSIX จาก datetime และแปลงกลับมา:

>>> import datetime, time
>>> dt = datetime.datetime(2011, 10, 21, 0, 0)
>>> s = time.mktime(dt.timetuple())
>>> s
1319148000.0

# and back
>>> datetime.datetime.fromtimestamp(s)
datetime.datetime(2011, 10, 21, 0, 0)

โปรดทราบว่าเขตเวลาที่แตกต่างกันมีผลต่อผลลัพธ์เช่น TZ / DST ปัจจุบันของฉันส่งคืน:

>>>  time.mktime(datetime.datetime(1970, 1, 1, 0, 0).timetuple())
-3600 # -1h

ดังนั้นหนึ่งควรพิจารณา normalizing เป็น UTC โดยใช้ฟังก์ชัน UTC เวอร์ชัน

โปรดทราบว่าผลลัพธ์ก่อนหน้านี้สามารถใช้ในการคำนวณ UTC offset ของเขตเวลาปัจจุบันของคุณ ในตัวอย่างนี้นี่คือ + 1 ชม. เช่น UTC + 0100

อ้างอิง:


mktime()อาจล้มเหลว โดยทั่วไปคุณต้องpytzแปลงเวลาท้องถิ่นเป็น utc เพื่อรับ POSIX การประทับเวลา
jfs

calendar.timegm () น่าจะเป็นรุ่น utc ของ time.mktime ()
frankster

27

int (t.strftime("%s")) ยังใช้งานได้


1
ได้ผลสำหรับฉันใน Python 2.7 ด้วยimport datetime; t = datetime.datetime(2011, 10, 21, 0, 0)(ตามที่ระบุโดย OP) แต่จริงๆแล้วฉันสงสัยว่า% s เป็นรูปแบบเวลาที่เพิ่งเพิ่ม
dan3

1
@ dan3: ผิด %sไม่รองรับ (มันอาจทำงานบนบางแพลตฟอร์ม iff tเป็นวัตถุ datetime ไร้เดียงสาที่แสดงเวลาท้องถิ่นและถ้าไลบรารี C โลคัลสามารถเข้าถึงฐานข้อมูล tz มิฉะนั้นผลลัพธ์อาจไม่ถูกต้อง) อย่าใช้มัน
jfs

%sไม่มีการบันทึกไว้ที่ใดก็ได้ ฉันหว่านในรหัสจริงและสงสัยว่านี่คืออะไรและดูในเอกสารประกอบและไม่มีสิ่งเช่น%sนั้น มีเพียงตัวใหญ่ S เพียงไม่กี่วินาที
VStoykov

13

จาก python docs:

timedelta.total_seconds()

ส่งคืนจำนวนวินาทีทั้งหมดที่มีในช่วงเวลา เทียบเท่ากับ

(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6

คำนวณโดยเปิดใช้งานการแบ่งจริง

โปรดทราบว่าสำหรับช่วงเวลาที่มีขนาดใหญ่มาก (มากกว่า 270 ปีในแพลตฟอร์มส่วนใหญ่) วิธีนี้จะสูญเสียความแม่นยำในระดับไมโครวินาที

ฟังก์ชันนี้มีใหม่ในรุ่น 2.7


1
มีปัญหาขนาดเล็กที่มีการคำนวณมันจะต้องเป็น 10 6 แทน 10 * 6 ... td.microseconds + (+ td.seconds td.days * 24 * 3600) * 10 6) / 10 ** 6
SDU

@sdu great catch - เครื่องหมายดอกจันคู่อยู่ในคำตอบของฉัน แต่ stackoverflow ใช้งานไปพยายามแก้ไขเฉพาะข้อความที่เป็นตัวหนาเท่านั้น
ไมเคิล

2

ในการแปลงวัตถุ datetime ที่แสดงเวลาใน UTC เป็นเวลาประทับ POSIX :

from datetime import timezone

seconds_since_epoch = utc_time.replace(tzinfo=timezone.utc).timestamp()

ในการแปลงวัตถุ datetime ที่แสดงเวลาในเขตเวลาท้องถิ่นเป็นเวลาประทับ POSIX:

import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone()
seconds_since_epoch = local_timezone.localize(local_time, is_dst=None).timestamp()

ดูฉันจะแปลงเวลาท้องถิ่นเป็น UTC ใน Python ได้อย่างไร หากฐานข้อมูล tz พร้อมใช้งานบนแพลตฟอร์มที่กำหนด วิธีการแก้ปัญหา STDLIB อย่างเดียวอาจทำงาน

ติดตามลิงก์หากคุณต้องการวิธีแก้ไข <3.3เวอร์ชั่น Python


1

ฉันลองcalendar.timegmของห้องสมุดมาตรฐานและมันใช้งานได้ดี:

# convert a datetime to milliseconds since Epoch
def datetime_to_utc_milliseconds(aDateTime):
    return int(calendar.timegm(aDateTime.timetuple())*1000)

Ref: https://docs.python.org/2/library/calendar.html#calendar.timegm


มันแยกเศษเสี้ยวของวินาที มันถือว่าaDateTimeเป็นเวลา UTC
jfs
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.