كيف يمكنني الحصول على وقت UTC من "منتصف الليل" لتوقيت معين؟

StackOverflow https://stackoverflow.com/questions/373370

سؤال

وأفضل ما يمكن أن نخرج الآن هو هذا المسخ:

>>> datetime.utcnow() \
...   .replace(tzinfo=pytz.UTC) \
...   .astimezone(pytz.timezone("Australia/Melbourne")) \
...   .replace(hour=0,minute=0,second=0,microsecond=0) \
...   .astimezone(pytz.UTC) \
...   .replace(tzinfo=None)
datetime.datetime(2008, 12, 16, 13, 0)

وأي بمعنى، باللغة الإنجليزية، احصل على الوقت الحالي (في UTC)، وتحويله إلى بعض توقيت آخر، ضبط الوقت وحتى منتصف الليل، ثم تحويل إلى UTC.

وأنا لا فقط باستخدام الآن () أو LOCALTIME () كما أن من شأنه أن استخدام التوقيت خادم، وليس التوقيت المستخدم.

لا يسعني الشعور أنا في عداد المفقودين شيء، أي أفكار؟

هل كانت مفيدة؟

المحلول

وأعتقد أنك يمكن أن يحلق يدعو طريقة قليل إذا كنت تفعل ذلك مثل هذا:

>>> from datetime import datetime
>>> datetime.now(pytz.timezone("Australia/Melbourne")) \
            .replace(hour=0, minute=0, second=0, microsecond=0) \
            .astimezone(pytz.utc)

ولكن ... هناك مشكلة أكبر من الجماليات في التعليمات البرمجية: أنه سوف يعطي نتيجة خاطئة في يوم من التحول إلى أو من التوقيت الصيفي

والسبب في ذلك هو أنه لا المنشئات التاريخ والوقت ولا replace() تأخذ التغييرات DST في الاعتبار.

وعلى سبيل المثال:

>>> now = datetime(2012, 4, 1, 5, 0, 0, 0, tzinfo=pytz.timezone("Australia/Melbourne"))
>>> print now
2012-04-01 05:00:00+10:00
>>> print now.replace(hour=0)
2012-04-01 00:00:00+10:00 # wrong! midnight was at 2012-04-01 00:00:00+11:00
>>> print datetime(2012, 3, 1, 0, 0, 0, 0, tzinfo=tz)
2012-03-01 00:00:00+10:00 # wrong again!

ولكن، وثائق الدول tz.localize():

<اقتباس فقرة>   

وينبغي أن تستخدم هذه الطريقة لبناء localtimes، بدلا   من تمرير حجة tzinfo إلى منشئ التاريخ والوقت.

وهكذا، يتم حل مشكلتك مثل ذلك:

>>> import pytz
>>> from datetime import datetime, date, time

>>> tz = pytz.timezone("Australia/Melbourne")
>>> the_date = date(2012, 4, 1) # use date.today() here

>>> midnight_without_tzinfo = datetime.combine(the_date, time())
>>> print midnight_without_tzinfo
2012-04-01 00:00:00

>>> midnight_with_tzinfo = tz.localize(midnight_without_tzinfo)
>>> print midnight_with_tzinfo
2012-04-01 00:00:00+11:00

>>> print midnight_with_tzinfo.astimezone(pytz.utc)
2012-03-31 13:00:00+00:00

ولا ضمانات للتواريخ قبل 1582، بالرغم من ذلك.

نصائح أخرى

@ هوب الجواب هو الخطأ في يوم من الانتقال من التوقيت الصيفي (DST) على سبيل المثال، 1 أبريل 2012 . لإصلاحه tz.localize() يمكن استخدامها:

tz = pytz.timezone("Australia/Melbourne")
today = datetime.now(tz).date()
midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)
utc_dt = midnight.astimezone(pytz.utc)        

والشيء نفسه مع تعليقات:

#!/usr/bin/env python
from datetime import datetime, time
import pytz # pip instal pytz

tz = pytz.timezone("Australia/Melbourne") # choose timezone

# 1. get correct date for the midnight using given timezone.
today = datetime.now(tz).date()

# 2. get midnight in the correct timezone (taking into account DST)
#NOTE: tzinfo=None and tz.localize()
# assert that there is no dst transition at midnight (`is_dst=None`)
midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)

# 3. convert to UTC (no need to call `utc.normalize()` due to UTC has no 
#    DST transitions)
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
print midnight.astimezone(pytz.utc).strftime(fmt)

وتحديد متغير البيئة TZ يعدل ما تعمل التاريخ والوقت وظائف التوقيت بايثون مع.

>>> time.gmtime()
(2008, 12, 17, 1, 16, 46, 2, 352, 0)
>>> time.localtime()
(2008, 12, 16, 20, 16, 47, 1, 351, 0)
>>> os.environ['TZ']='Australia/Melbourne'
>>> time.localtime()
(2008, 12, 17, 12, 16, 53, 2, 352, 1)

وكل منطقة زمنية لديها عدد، على سبيل المثال الولايات المتحدة / الوسطى = -6. ويعرف هذا كما الإزاحة في ساعات من UTC. منذ 0000 هو منتصف الليل، يمكنك ببساطة استخدام هذا تعويض لإيجاد الوقت اللازم في أي منطقة زمنية عندما يكون منتصف الليل UTC. للوصول إلى ذلك، وأعتقد أنك يمكن استخدام

 time.timezone

ووفقا ل وبايثون مستندات ، time.timezone في الواقع يعطي قيمة سالبة لل هذا الرقم:

<اقتباس فقرة>   <اقتباس فقرة>     

وtime.timezone

         <اقتباس فقرة>       

وإزاحة المحلي (DST غير) التوقيت بالثواني غرب UTC (سلبية في معظم دول أوروبا الغربية، وإيجابية في الولايات المتحدة، صفر في المملكة المتحدة).

       

وهكذا كنت ببساطة استخدام هذا الرقم للمرة بالساعات اذا كان إيجابيا (أي لو كان منتصف الليل في شيكاغو (التي لديها قيمة +6 التوقيت)، ثم انها 6000 = 06:00 UTC).

إذا كان الرقم سالبا، طرح من 24. على سبيل المثال، برلين سيعطي -1، لذلك 24 - 1 => 2300 = 11:00

وهذا هو أكثر وضوحا مع dateutil.tz من pytz:

>>>import datetime
>>>import dateutil.tz
>>>midnight=(datetime.datetime
             .now(dateutil.tz.gettz('Australia/Melbourne'))
             .replace(hour=0, minute=0, second=0, microsecond=0)
             .astimezone(dateutil.tz.tzutc()))
>>>print(midnight)
2019-04-26 14:00:00+00:00

tzinfo الوثائق توصي dateutil.tz منذ بيثون 3.6. الكائنات tzinfo من dateutil.tz ليس لديها مشاكل مع الحالات الشاذة مثل DST دون الحاجة إلى وظيفة المعربة من pytz. باستخدام المثال من user3850:

>>> now = (datetime.datetime(2012, 4, 1, 5,  
...         tzinfo = dateutil.tz.gettz('Australia/Melbourne'))) 
>>> print(now.replace(hour = 0).astimezone(dateutil.tz.tzutc()))
2012-03-31 13:00:00+00:00
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top