UTC डेटाटाइम स्ट्रिंग को स्थानीय डेटाटाइम में कनवर्ट करें


206

मुझे UTC से कभी भी समय नहीं बदलना पड़ा। हाल ही में मेरा अनुरोध था कि मेरे ऐप को टाइमज़ोन के बारे में पता होना चाहिए, और मैं खुद को हलकों में चला रहा हूं। UTC को स्थानीय समय को परिवर्तित करने के बारे में बहुत सारी जानकारी, जो मुझे काफी प्राथमिक लगी (शायद मैं भी यही गलत कर रहा हूँ), लेकिन मैं यूटीसी समय को अंत-उपयोगकर्ताओं के समयक्षेत्र में आसानी से परिवर्तित करने के बारे में कोई जानकारी नहीं पा सकता हूँ।

संक्षेप में, और android ऐप मुझे (appengine ऐप) डेटा भेजता है और उस डेटा के भीतर एक टाइमस्टैम्प है। उस टाइमस्टैम्प को स्टोर करने के लिए जिसे मैं उपयोग कर रहा हूं:

datetime.utcfromtimestamp(timestamp)

वह काम करने लगता है। जब मेरा ऐप डेटा स्टोर करता है, तो इसे 5 घंटे आगे स्टोर किया जा रहा है (मैं EST -5)

डेटा को एपेंजिन के BigTable पर संग्रहीत किया जा रहा है, और जब इसे पुनः प्राप्त किया जाता है तो यह स्ट्रिंग की तरह बाहर आता है:

"2011-01-21 02:37:21"

मैं उपयोगकर्ताओं को सही समय क्षेत्र में दिनांक को इस स्ट्रिंग में कैसे परिवर्तित करूं?

इसके अलावा, उपयोगकर्ताओं को समय-सीमा की जानकारी के लिए अनुशंसित संग्रहण क्या है? (आप आम तौर पर tz जानकारी कैसे संग्रहीत करते हैं अर्थात: "-5: 00" या "ईएसटी" इत्यादि?) मुझे यकीन है कि मेरे पहले प्रश्न के उत्तर में एक पैरामीटर हो सकता है कि उत्तर दूसरा हो।



यह उत्तर दिखाता है कि इसे सरल तरीके से कैसे हल किया जाए।
जुआन

जवाबों:


402

यदि आप अपनी खुद की tzinfoवस्तुएं प्रदान नहीं करना चाहते हैं, तो अजगर-डेटुतिल लाइब्रेरी देखें। यह tzinfoएक जोनइनफो (ओल्सन) डेटाबेस के शीर्ष पर कार्यान्वयन प्रदान करता है जैसे कि आप कुछ हद तक विहित नाम से समय क्षेत्र के नियमों का उल्लेख कर सकते हैं।

from datetime import datetime
from dateutil import tz

# METHOD 1: Hardcode zones:
from_zone = tz.gettz('UTC')
to_zone = tz.gettz('America/New_York')

# METHOD 2: Auto-detect zones:
from_zone = tz.tzutc()
to_zone = tz.tzlocal()

# utc = datetime.utcnow()
utc = datetime.strptime('2011-01-21 02:37:21', '%Y-%m-%d %H:%M:%S')

# Tell the datetime object that it's in UTC time zone since 
# datetime objects are 'naive' by default
utc = utc.replace(tzinfo=from_zone)

# Convert time zone
central = utc.astimezone(to_zone)

strptimeउपयोग दिखाने के लिए विस्तारित उदाहरण संपादित करें

बेहतर प्रविष्टि बिंदु विधि दिखाने के लिए 2 फिक्स्ड एपीआई उपयोग को संपादित करें

टाइमज़ोन (यारिन) के लिए ऑटो-डिटेक्ट मेथड्स को शामिल करें


1
मेरी पिछली टिप्पणी पर, मैं आयात dateutil.tzऔर उपयोग करने में सक्षम था tz.tzutc()और tz.tzlocal()समय क्षेत्र की वस्तुओं के रूप में जिसकी मुझे तलाश थी। ऐसा लगता है कि मेरे सिस्टम पर टाइम ज़ोन डेटाबेस अच्छा है (मैंने चेक इन किया है /usr/share/zoneinfo)। यकीन नहीं था कि क्या था।
बेन क्रीगर

1
@ बैंजामिन आप सही रास्ते पर हैं। tzमॉड्यूल इस पुस्तकालय के लिए उपयोग किया जा करने के लिए सही प्रवेश बिंदु है। मैंने इसे दर्शाने के लिए अपना उत्तर अपडेट कर दिया है। जो dateutil.zoneinfoमॉड्यूल मैं पहले दिखा रहा था, वह आंतरिक tzरूप से मॉड्यूल द्वारा एक गिरावट बैक के रूप में उपयोग किया जाता है, अगर यह सिस्टम के ज़ॉंन्फो डीबी का पता नहीं लगा सकता है। यदि आप लाइब्रेरी के अंदर देखते हैं, तो आप देखेंगे कि पैकेज में एक जोनइनफो डीबी टारबॉल है जो इसका उपयोग करता है यदि यह आपके सिस्टम के डीबी को नहीं पा सकता है। मेरा पुराना उदाहरण उस डीबी को सीधे हिट करने की कोशिश कर रहा था और मैं अनुमान लगा रहा हूं कि आप उस निजी डीबी को लोड करने में समस्या कर रहे हैं (किसी तरह से पायनोन पथ पर नहीं है?)
जो होलो


1
इस में तय हो गई है @JFSebastian # 225
Rohmer

2
@briankip यह निर्भर करता है कि आपके एप्लिकेशन को कितना परिष्कृत होना चाहिए, लेकिन सामान्य अनुप्रयोगों में, हां, यह एक समस्या है। सबसे पहले यह वर्ष के किस समय पर निर्भर करता है, कुछ समय जोड़ने / घटाने के लिए घंटों की संख्या बदल सकती है क्योंकि कुछ समय के लिए डीएसटी का सम्मान होता है और अन्य नहीं। दूसरे, समय क्षेत्र के नियमों में समय के साथ मनमाने ढंग से बदलाव किया जाता है, इसलिए यदि आप पिछली तारीख / समय के साथ काम कर रहे हैं, तो आपको उस समय में मान्य नियमों को लागू करने की आवश्यकता है, वर्तमान समय में नहीं। यही कारण है कि एक एपीआई का उपयोग करना सबसे अच्छा है जो पर्दे के पीछे ओल्सन टीबी डेटाबेस का लाभ उठाता है।
जो होलोवे

44

यहाँ एक लचीला तरीका है जो किसी भी बाहरी पुस्तकालयों पर निर्भर नहीं करता है:

from datetime import datetime
import time

def datetime_from_utc_to_local(utc_datetime):
    now_timestamp = time.time()
    offset = datetime.fromtimestamp(now_timestamp) - datetime.utcfromtimestamp(now_timestamp)
    return utc_datetime + offset

यह DelboyJay के उदाहरण में समय के मुद्दों से बचा जाता है। और एरिक वैन ओस्टेन के संशोधन में कम समय के मुद्दे।

एक दिलचस्प फुटनोट के रूप में, ऊपर गणना की गई समय-सीमा ऑफसेट निम्नलिखित प्रतीत होने वाले समकक्ष अभिव्यक्ति से भिन्न हो सकती है, शायद दिन के उजाले की बचत नियम के कारण:

offset = datetime.fromtimestamp(0) - datetime.utcfromtimestamp(0) # NO!

अपडेट करें: इस स्निपेट में वर्तमान समय के यूटीसी ऑफसेट का उपयोग करने की कमजोरी है, जो इनपुट डेटाइम के यूटीसी ऑफसेट से भिन्न हो सकती है। एक अन्य समाधान के लिए इस उत्तर पर टिप्पणियाँ देखें।

अलग-अलग समय के लिए, समय बीतने के समय से समय को पकड़ो। यहाँ मैं क्या करूँ:

def utc2local (utc):
    epoch = time.mktime(utc.timetuple())
    offset = datetime.fromtimestamp (epoch) - datetime.utcfromtimestamp (epoch)
    return utc + offset

यह अच्छी तरह से काम करता है और समय और डेटाटाइम के अलावा कुछ भी नहीं चाहिए।
माइक_के

6
@ माइक_के: लेकिन यह गलत है। यह DST या टाइमज़ोन का समर्थन नहीं करता है जो अन्य कारणों से अतीत में अलग utc ऑफसेट था। pytzपीईबी -431 देखें, बिना डीबी के पूर्ण समर्थन असंभव है। यद्यपि आप stdlib- केवल समाधान लिख सकते हैं जो सिस्टम पर ऐसे मामलों में काम करता है जिनके पास पहले से ही ऐतिहासिक समय क्षेत्र db है, Linux, OS X, मेरा उत्तर देखें ।
JFS

@JFSebastian: आप कहते हैं कि यह कोड सामान्य रूप से काम नहीं करता है, लेकिन यह भी कहता है कि यह OS X और Linux पर काम करता है। क्या आपका मतलब है कि यह कोड विंडोज पर काम नहीं करता है?
डेविड फोस्टर

2
@DavidFoster: आपका कोड Linux और OS X पर भी विफल हो सकता है। तुम्हारा और मेरा stdlib- केवल समाधान के बीच का अंतर यह है कि तुम्हारा वर्तमान ऑफसेट का उपयोग करता है जो उस utc_datetimeसमय utc ऑफसेट से भिन्न हो सकता है ।
jfs

1
अच्छा निर्णय। यह बहुत सूक्ष्म अंतर है। यूटीसी ऑफसेट समय के साथ भी बदल सकता है। उच्छ्वास
डेविड फोस्टर

23

देखें datetime पर प्रलेखन tzinfo वस्तुओं। आपको उस टाइमज़ोन को लागू करना होगा जिसे आप अपना समर्थन देना चाहते हैं। प्रलेखन के तल पर उदाहरण हैं।

यहाँ एक सरल उदाहरण दिया गया है:

from datetime import datetime,tzinfo,timedelta

class Zone(tzinfo):
    def __init__(self,offset,isdst,name):
        self.offset = offset
        self.isdst = isdst
        self.name = name
    def utcoffset(self, dt):
        return timedelta(hours=self.offset) + self.dst(dt)
    def dst(self, dt):
            return timedelta(hours=1) if self.isdst else timedelta(0)
    def tzname(self,dt):
         return self.name

GMT = Zone(0,False,'GMT')
EST = Zone(-5,False,'EST')

print datetime.utcnow().strftime('%m/%d/%Y %H:%M:%S %Z')
print datetime.now(GMT).strftime('%m/%d/%Y %H:%M:%S %Z')
print datetime.now(EST).strftime('%m/%d/%Y %H:%M:%S %Z')

t = datetime.strptime('2011-01-21 02:37:21','%Y-%m-%d %H:%M:%S')
t = t.replace(tzinfo=GMT)
print t
print t.astimezone(EST)

उत्पादन

01/22/2011 21:52:09 
01/22/2011 21:52:09 GMT
01/22/2011 16:52:09 EST
2011-01-21 02:37:21+00:00
2011-01-20 21:37:21-05:00a

स्वीकार करने के लिए धन्यवाद! आपके विशिष्ट उदाहरण समय का अनुवाद करने के लिए मैंने इसे थोड़ा अद्यतन किया। समय को पार्स करने से डॉक्स को "भोला" समय कहते हैं। replaceसमयक्षेत्र को GMT पर सेट करने के लिए उपयोग करें और इसे समय-क्षेत्र "जागरूक" बनाने के लिए, फिर astimezoneकिसी अन्य समयक्षेत्र में बदलने के लिए उपयोग करें।
मार्क टोलेनन

जो के जवाब के लिए स्वैपिंग के लिए क्षमा करें। तकनीकी रूप से आपका उत्तर बताता है कि कच्चे अजगर के साथ यह कैसे करना है (जो जानना अच्छा है), लेकिन उसने जो पुस्तकालय सुझाया वह मुझे बहुत जल्दी मिल जाता है।
मट्टोडोड

4
ऐसा नहीं लगता कि यह स्वचालित रूप से दिन के उजाले की बचत का समय है।
ग़ैरमुल्की शिष्ट

@GringoSuave: इसका मतलब यह नहीं था। इसके लिए नियम जटिल हैं और अक्सर बदलते रहते हैं।
मार्क टोलेन

19

यदि आप उस समय के लिए भी सही परिणाम प्राप्त करना चाहते हैं जो एक अस्पष्ट स्थानीय समय (जैसे, डीएसटी संक्रमण के दौरान) से मेल खाता है और / या स्थानीय utc ऑफसेट आपके स्थानीय समय क्षेत्र में अलग-अलग समय पर अलग है तो टाइमज़ोन का उपयोग करें pytz:

#!/usr/bin/env python
from datetime import datetime
import pytz    # $ pip install pytz
import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone() # get pytz tzinfo
utc_time = datetime.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S")
local_time = utc_time.replace(tzinfo=pytz.utc).astimezone(local_timezone)

10

यदि आप इसके अलावा किसी अन्य मॉड्यूल का उपयोग नहीं करना चाहते हैं तो यह उत्तर उपयोगी होना चाहिए datetime

datetime.utcfromtimestamp(timestamp)एक भोली datetimeवस्तु लौटाता है (एक जागरूक नहीं)। जागरूक लोग टाइमजोन जागरूक हैं, और भोले नहीं हैं। यदि आप timezones (जैसे UTC और स्थानीय समय के बीच) में कनवर्ट करना चाहते हैं, तो आप एक जागरूक चाहते हैं।

यदि आप शुरू करने की तारीख को तत्काल नहीं कर रहे हैं, लेकिन आप अभी भी datetimeयूटीसी समय में एक भोली वस्तु बना सकते हैं, तो आप इसे परिवर्तित करने के लिए इस पायथन 3.x कोड को आज़माना चाह सकते हैं:

import datetime

d=datetime.datetime.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S") #Get your naive datetime object
d=d.replace(tzinfo=datetime.timezone.utc) #Convert it to an aware datetime object in UTC time.
d=d.astimezone() #Convert it to your local timezone (still aware)
print(d.strftime("%d %b %Y (%I:%M:%S:%f %p) %Z")) #Print it with a directive of choice

सावधान रहें कि गलती से यह न समझें कि यदि आपका टाइमज़ोन वर्तमान में एमडीटी है, तो दिन के उजाले की बचत उपरोक्त कोड के साथ काम नहीं करती है क्योंकि यह जीएसटी प्रिंट करता है। आप ध्यान दें कि यदि आप महीने को अगस्त में बदलते हैं, तो यह एमडीटी प्रिंट करेगा।

एक जागरूक datetimeवस्तु प्राप्त करने का एक और आसान तरीका (पायथन 3.x में भी) इसे शुरू करने के लिए निर्दिष्ट टाइमज़ोन के साथ बनाना है। यहाँ एक उदाहरण है, UTC का उपयोग करते हुए:

import datetime, sys

aware_utc_dt_obj=datetime.datetime.now(datetime.timezone.utc) #create an aware datetime object
dt_obj_local=aware_utc_dt_obj.astimezone() #convert it to local time

#The following section is just code for a directive I made that I liked.
if sys.platform=="win32":
    directive="%#d %b %Y (%#I:%M:%S:%f %p) %Z"
else:
    directive="%-d %b %Y (%-I:%M:%S:%f %p) %Z"

print(dt_obj_local.strftime(directive))

यदि आप Python 2.x का उपयोग करते हैं, तो संभवतः आपको उप-लिंक करना होगा datetime.tzinfoऔर इसका उपयोग करना होगा ताकि आप एक जागरूक datetimeवस्तु बना सकें , क्योंकि Python 2.x datetime.timezoneमें मौजूद नहीं है।


8

यदि Django का उपयोग कर रहे हैं, तो आप timezone.localtimeविधि का उपयोग कर सकते हैं :

from django.utils import timezone
date 
# datetime.datetime(2014, 8, 1, 20, 15, 0, 513000, tzinfo=<UTC>)

timezone.localtime(date)
# datetime.datetime(2014, 8, 1, 16, 15, 0, 513000, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)

2

आप तीर का उपयोग कर सकते हैं

from datetime import datetime
import arrow

now = datetime.utcnow()

print(arrow.get(now).to('local').format())
# '2018-04-04 15:59:24+02:00'

आप arrow.get()कुछ भी खिला सकते हैं । टाइमस्टैम्प, आईएसओ स्ट्रिंग आदि


1

मैं पारंपरिक रूप से इस दृश्य को स्थगित कर देता हूं - बैकएंड से टाइमस्टैम्प या यूटीसी में कुछ अन्य डेटाटाइम प्रारूप के रूप में बार-बार भेजता हूं, फिर क्लाइंट को टाइमजोन ऑफसेट करने दें और उचित समय में इस डेटा को प्रस्तुत करें।

एक वेबएप के लिए, जावास्क्रिप्ट में करना बहुत आसान है - आप ब्राउज़र के टाइमज़ोन ऑफसेट को आसानी से बिलिन विधियों का उपयोग करके समझ सकते हैं और फिर बैकएंड से डेटा को ठीक से प्रस्तुत कर सकते हैं।


3
यह बहुत सारे मामलों में अच्छी तरह से काम करता है, जहाँ आप केवल प्रदर्शन के लिए स्थानीयकरण कर रहे हैं। कभी-कभी, हालांकि, आपको उपयोगकर्ता के समय क्षेत्र के आधार पर कुछ व्यावसायिक तर्क करने की आवश्यकता होगी और आप एप्लिकेशन सर्वर टियर में रूपांतरण करने में सक्षम होना चाहते हैं।
जो होलोवे

1

आप calendar.timegmयूनिक्स की अवधि के बाद से सेकंड में अपना समय time.localtimeबदलने और वापस परिवर्तित करने के लिए उपयोग कर सकते हैं :

import calendar
import time

time_tuple = time.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S")
t = calendar.timegm(time_tuple)

print time.ctime(t)

देता है Fri Jan 21 05:37:21 2011(क्योंकि मैं UTC + 03: 00 समयक्षेत्र में हूं)।


1
import datetime

def utc_str_to_local_str(utc_str: str, utc_format: str, local_format: str):
    """
    :param utc_str: UTC time string
    :param utc_format: format of UTC time string
    :param local_format: format of local time string
    :return: local time string
    """
    temp1 = datetime.datetime.strptime(utc_str, utc_format)
    temp2 = temp1.replace(tzinfo=datetime.timezone.utc)
    local_time = temp2.astimezone()
    return local_time.strftime(local_format)

utc = '2018-10-17T00:00:00.111Z'
utc_fmt = '%Y-%m-%dT%H:%M:%S.%fZ'
local_fmt = '%Y-%m-%dT%H:%M:%S+08:00'
local_string = utc_str_to_local_str(utc, utc_fmt, local_fmt)
print(local_string)   # 2018-10-17T08:00:00+08:00

उदाहरण के लिए, मेरा टाइमज़ोन ' +08: 00 ' है। इनपुट utc = 2018-10-17T00 : 00: 00.111Z , तो मुझे आउटपुट मिलेगा = 2018-10-17T08: 00: 00 + 08: 00


1
आपको सादे पाठ में अपनी समस्या का बेहतर विवरण देना चाहिए, जहां आप बाकी उपयोगकर्ताओं को समझाते हैं कि आप क्या हासिल करने की कोशिश कर रहे हैं और आपकी समस्या क्या है
m33n

1

यहां उत्तर से , आप अपने कंप्यूटर में स्थानीय समय से utc में बदलने के लिए समय मॉड्यूल का उपयोग कर सकते हैं:

utc_time = time.strptime("2018-12-13T10:32:00.000", "%Y-%m-%dT%H:%M:%S.%f")
utc_seconds = calendar.timegm(utc_time)
local_time = time.localtime(utc_seconds)

0

यहां एक त्वरित और गंदा संस्करण है जो समय के अंतर को जानने के लिए स्थानीय सिस्टम सेटिंग्स का उपयोग करता है। नोट: यदि आप अपने वर्तमान सिस्टम में नहीं चल रहे हैं, तो आपको एक टाइमज़ोन में बदलने की आवश्यकता नहीं है, यह काम नहीं करेगा। मैंने इसे यूके सेटिंग्स के साथ बीएसटी टाइमज़ोन के तहत परीक्षण किया है।

from datetime import datetime
def ConvertP4DateTimeToLocal(timestampValue):
   assert isinstance(timestampValue, int)

   # get the UTC time from the timestamp integer value.
   d = datetime.utcfromtimestamp( timestampValue )

   # calculate time difference from utcnow and the local system time reported by OS
   offset = datetime.now() - datetime.utcnow()

   # Add offset to UTC time and return it
   return d + offset

यह होना चाहिए datetime.fromtimestamp(ts): पॉज़िक्स टाइमस्टैम्प (फ्लोट सेकंड) -> स्थानीय समय में डेटाटाइम ऑब्जेक्ट (यह अच्छी तरह से काम करता है अगर ओएस स्थानीय टाइमज़ोन के लिए पिछले यूसेट्स को याद करता है, यानी यूनिक्स पर लेकिन अतीत में तारीखों के लिए विंडोज पर नहीं))। अन्यथा pytz इस्तेमाल किया जा सकता है।
JFS

क्या मैं निम्नलिखित करने का सुझाव दे सकता offset = datetime.utcnow().replace(minute=0, second=0, microsecond=0) - datetime.now().replace(minute=0, second=0, microsecond=0) हूं : मुझे इसके बिना अजीब माइक्रोसेकंड अंतर मिला।
एरिक वैन ओस्टेन सेप

@ ErikvanOosten: क्या आपने datetime.fromtimestamp(ts)उत्तर के बजाय कोशिश की है?
JFS

0

एक सुविधाजनक विधि में फ़्रैंकैंड्स से उत्तर को समेकित करना ।

import calendar
import datetime

def to_local_datetime(utc_dt):
    """
    convert from utc datetime to a locally aware datetime according to the host timezone

    :param utc_dt: utc datetime
    :return: local timezone datetime
    """
    return datetime.datetime.fromtimestamp(calendar.timegm(utc_dt.timetuple()))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.