मैं JSON का उपयोग करके पायथन से क्रमबद्ध रूप में डेटाटाइम लाइफटाइम ऑब्जेक्ट भेजना चाहता हूं और JSON का उपयोग करके जावास्क्रिप्ट में डी-सीरियलाइज करना चाहता हूं । इसे करने का बेहतरीन तरीका क्या है?
मैं JSON का उपयोग करके पायथन से क्रमबद्ध रूप में डेटाटाइम लाइफटाइम ऑब्जेक्ट भेजना चाहता हूं और JSON का उपयोग करके जावास्क्रिप्ट में डी-सीरियलाइज करना चाहता हूं । इसे करने का बेहतरीन तरीका क्या है?
जवाबों:
आप इसे संभालने के लिए json.dumps में 'डिफ़ॉल्ट' पैरामीटर जोड़ सकते हैं:
date_handler = lambda obj: (
obj.isoformat()
if isinstance(obj, (datetime.datetime, datetime.date))
else None
)
json.dumps(datetime.datetime.now(), default=date_handler)
'"2010-04-20T20:08:21.634121"'
जो कि आईएसओ 8601 प्रारूप है।
एक अधिक व्यापक डिफ़ॉल्ट हैंडलर फ़ंक्शन:
def handler(obj):
if hasattr(obj, 'isoformat'):
return obj.isoformat()
elif isinstance(obj, ...):
return ...
else:
raise TypeError, 'Object of type %s with value of %s is not JSON serializable' % (type(obj), repr(obj))
अद्यतन: मूल्य के साथ ही प्रकार का जोड़ा गया उत्पादन।
अद्यतन: इसके अलावा तारीख संभालें
dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime) else json.JSONEncoder().default(obj)
क्रॉस-लैंग्वेज प्रोजेक्ट्स के लिए, मुझे पता चला कि RfC 3339 तारीख वाले तार जाने का सबसे अच्छा तरीका है। एक RfC 3339 तारीख इस तरह दिखता है:
1985-04-12T23:20:50.52Z
मुझे लगता है कि ज्यादातर प्रारूप स्पष्ट है। केवल कुछ असामान्य बात अंत में "जेड" हो सकती है। यह GMT / UTC के लिए है। आप CEST (गर्मियों में जर्मनी) के लिए +02: 00 जैसी टाइमज़ोन ऑफ़सेट भी जोड़ सकते हैं। मैं व्यक्तिगत रूप से UTC में सब कुछ रखना पसंद करता हूं जब तक कि यह प्रदर्शित न हो।
प्रदर्शन, तुलना और भंडारण के लिए आप इसे सभी भाषाओं में स्ट्रिंग प्रारूप में छोड़ सकते हैं। यदि आपको अधिकांश भाषा में मूल दिनांक ऑब्जेक्ट पर वापस कनवर्ट करने के लिए गणना के लिए आसान दिनांक की आवश्यकता है।
तो इस तरह JSON उत्पन्न करें:
json.dump(datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ'))
दुर्भाग्य से, जावास्क्रिप्ट का दिनांक निर्माता RfC 3339 तार को स्वीकार नहीं करता है, लेकिन इंटरनेट पर कई पार्सर उपलब्ध हैं।
huTools.hujson सबसे आम एन्कोडिंग मुद्दों को संभालने की कोशिश करता है जो आप समय-समय पर सही ढंग से हैंडल करते हुए दिनांक / डेटाटाइम ऑब्जेक्ट सहित पाइथन कोड में आ सकते हैं।
datetime
: datetime.isoformat () और simplejson
, जो डिफ़ॉल्ट datetime
रूप से ऑब्जेक्ट को isoformat
स्ट्रिंग के रूप में डंप करेगा । मैन्युअल strftime
हैकिंग की कोई आवश्यकता नहीं है ।
datetime
ऑब्जेक्ट से isoformat
स्ट्रिंग में स्वचालित रूपांतरण नहीं मिल रहा है । मेरे लिए, simplejson.dumps(datetime.now())
पैदावारTypeError: datetime.datetime(...) is not JSON serializable
json.dumps(datetime.datetime.now().isoformat())
जहां जादू होता है।
मैंने इसे काम किया है।
मान लीजिए कि आपके पास एक पायथन डेटाइम ऑब्जेक्ट है, d , जिसे डेटटाइम.वन () के साथ बनाया गया है। इसका मूल्य है:
datetime.datetime(2011, 5, 25, 13, 34, 5, 787000)
आप इसे आईएसओ 8601 डेटाइम स्ट्रिंग के रूप में JSON पर अनुक्रमित कर सकते हैं:
import json
json.dumps(d.isoformat())
उदाहरण के लिए आजीवन वस्तु को क्रमबद्ध किया जाएगा:
'"2011-05-25T13:34:05.787000"'
यह मान, एक बार जावास्क्रिप्ट लेयर में प्राप्त होने पर, दिनांक ऑब्जेक्ट का निर्माण कर सकता है:
var d = new Date("2011-05-25T13:34:05.787000");
जावास्क्रिप्ट के रूप में 1.8.5, दिनांक ऑब्जेक्ट में एक toJSON विधि है, जो एक मानक प्रारूप में एक स्ट्रिंग लौटाता है। उपरोक्त जावास्क्रिप्ट वस्तु को JSON में वापस लाने के लिए, इसलिए, कमांड होगी:
d.toJSON()
जो आपको देगा:
'2011-05-25T20:34:05.787Z'
पायथन में एक बार प्राप्त होने वाली यह स्ट्रिंग वापस एक डेडटाइम ऑब्जेक्ट के लिए deserialized हो सकती है:
datetime.strptime('2011-05-25T20:34:05.787Z', '%Y-%m-%dT%H:%M:%S.%fZ')
इसका परिणाम निम्न डेटाटाइम ऑब्जेक्ट में होता है, जो वही है जिसे आपने शुरू किया था और इसलिए सही है:
datetime.datetime(2011, 5, 25, 20, 34, 5, 787000)
का उपयोग करते हुए json
, आप JSONEncoder को उप-वर्ग कर सकते हैं और अपने स्वयं के कस्टम धारावाहिक प्रदान करने के लिए डिफ़ॉल्ट () विधि को ओवरराइड कर सकते हैं:
import json
import datetime
class DateTimeJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return obj.isoformat()
else:
return super(DateTimeJSONEncoder, self).default(obj)
फिर, आप इसे इस तरह से कॉल कर सकते हैं:
>>> DateTimeJSONEncoder().encode([datetime.datetime.now()])
'["2010-06-15T14:42:28"]'
obj.isoformat()
। आप अधिक सामान्य dumps()
कॉल का भी उपयोग कर सकते हैं , जो अन्य उपयोगी indent
आर्ग्स ( जैसे ) लेता है : simplejson.dumps (myobj, cls = JSONEncoder, ...)
यहाँ मानक लाइब्रेरी json
मॉड्यूल का उपयोग करके पुनरावर्ती एन्कोडिंग और डेटाइमटाइम .टाइमटाइम और डेटटाइम.डेट ऑब्जेक्ट्स को डिकोड करने के लिए एक पूर्ण पूर्ण समाधान है । इसके बाद से पायथन> = 2.6 की जरूरत है क्योंकि %f
प्रारूप कोड datetime.datetime.strptime () प्रारूप स्ट्रिंग में तब से ही समर्थित है। पायथन 2.5 समर्थन के लिए, %f
इसे बदलने की कोशिश करने से पहले आईएसओ तिथि स्ट्रिंग से माइक्रोसेकंड को छोड़ें और पट्टी करें, लेकिन आप निश्चित रूप से माइक्रोसेकंड परिशुद्धता को ढीला कर देंगे। अन्य स्रोतों से आईएसओ तिथि के तार के साथ अंतर के लिए, जिसमें एक समय क्षेत्र का नाम या यूटीसी ऑफसेट शामिल हो सकता है, आपको रूपांतरण से पहले दिनांक स्ट्रिंग के कुछ हिस्सों को पट्टी करने की भी आवश्यकता हो सकती है। ISO दिनांक स्ट्रिंग्स (और कई अन्य दिनांक स्वरूपों) के लिए एक पूर्ण पार्सर के लिए तृतीय-पक्ष डेट्यूटिल मॉड्यूल देखें।
डिकोडिंग केवल तभी काम करती है जब ISO डेट स्ट्रिंग्स एक जावास्क्रिप्ट शाब्दिक ऑब्जेक्ट नोटेशन या किसी ऑब्जेक्ट के भीतर नेस्टेड संरचनाओं में मान हो। आईएसओ तिथि के तार, जो एक शीर्ष-स्तरीय सरणी के आइटम हैं, को डिकोड नहीं किया जाएगा।
यानी यह काम करता है:
date = datetime.datetime.now()
>>> json = dumps(dict(foo='bar', innerdict=dict(date=date)))
>>> json
'{"innerdict": {"date": "2010-07-15T13:16:38.365579"}, "foo": "bar"}'
>>> loads(json)
{u'innerdict': {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)},
u'foo': u'bar'}
और यह भी:
>>> json = dumps(['foo', 'bar', dict(date=date)])
>>> json
'["foo", "bar", {"date": "2010-07-15T13:16:38.365579"}]'
>>> loads(json)
[u'foo', u'bar', {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)}]
लेकिन यह उम्मीद के मुताबिक काम नहीं करता है:
>>> json = dumps(['foo', 'bar', date])
>>> json
'["foo", "bar", "2010-07-15T13:16:38.365579"]'
>>> loads(json)
[u'foo', u'bar', u'2010-07-15T13:16:38.365579']
यहाँ कोड है:
__all__ = ['dumps', 'loads']
import datetime
try:
import json
except ImportError:
import simplejson as json
class JSONDateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (datetime.date, datetime.datetime)):
return obj.isoformat()
else:
return json.JSONEncoder.default(self, obj)
def datetime_decoder(d):
if isinstance(d, list):
pairs = enumerate(d)
elif isinstance(d, dict):
pairs = d.items()
result = []
for k,v in pairs:
if isinstance(v, basestring):
try:
# The %f format code is only supported in Python >= 2.6.
# For Python <= 2.5 strip off microseconds
# v = datetime.datetime.strptime(v.rsplit('.', 1)[0],
# '%Y-%m-%dT%H:%M:%S')
v = datetime.datetime.strptime(v, '%Y-%m-%dT%H:%M:%S.%f')
except ValueError:
try:
v = datetime.datetime.strptime(v, '%Y-%m-%d').date()
except ValueError:
pass
elif isinstance(v, (dict, list)):
v = datetime_decoder(v)
result.append((k, v))
if isinstance(d, list):
return [x[1] for x in result]
elif isinstance(d, dict):
return dict(result)
def dumps(obj):
return json.dumps(obj, cls=JSONDateTimeEncoder)
def loads(obj):
return json.loads(obj, object_hook=datetime_decoder)
if __name__ == '__main__':
mytimestamp = datetime.datetime.utcnow()
mydate = datetime.date.today()
data = dict(
foo = 42,
bar = [mytimestamp, mydate],
date = mydate,
timestamp = mytimestamp,
struct = dict(
date2 = mydate,
timestamp2 = mytimestamp
)
)
print repr(data)
jsonstring = dumps(data)
print jsonstring
print repr(loads(jsonstring))
datetime.datetime.utcnow().isoformat()[:-3]+"Z"
यह बिल्कुल वैसा ही होगा जैसे JSON.stringify () जावास्क्रिप्ट में पैदा होता है
यदि आप निश्चित हैं कि केवल जावास्क्रिप्ट JSON का उपभोग करेगा, तो मैं Date
सीधे जावास्क्रिप्ट वस्तुओं को पास करना पसंद करता हूं ।
ctime()
पर विधि datetime
वस्तुओं एक स्ट्रिंग है कि जावास्क्रिप्ट दिनांक वस्तु को समझ सकते हैं वापस आ जाएगी।
import datetime
date = datetime.datetime.today()
json = '{"mydate":new Date("%s")}' % date.ctime()
जावास्क्रिप्ट खुशी से एक वस्तु शाब्दिक के रूप में उपयोग करेगा, और आपको अपना दिनांक ऑब्जेक्ट सही में बनाया गया है।
.ctime()
एक बहुत बुरा तरीका है समय की जानकारी पारित करने के लिए, .isoformat()
बहुत बेहतर है। क्या .ctime()
करता है दूर फेंक समयजोन और दिन के उजाले की बचत की तरह वे मौजूद नहीं है। उस फंक्शन को मार देना चाहिए।
खेल में देर ... :)
एक बहुत ही सरल उपाय है कि जैसन मॉड्यूल को डिफ़ॉल्ट रूप से पैच किया जाए। उदाहरण के लिए:
import json
import datetime
json.JSONEncoder.default = lambda self,obj: (obj.isoformat() if isinstance(obj, datetime.datetime) else None)
अब, आप json.dumps () का उपयोग कर सकते हैं जैसे कि उसने हमेशा डेटाटाइम का समर्थन किया था ...
json.dumps({'created':datetime.datetime.now()})
यह समझ में आता है अगर आपको इस मॉड्यूल को हमेशा चालू करने के लिए जोंस मॉड्यूल के विस्तार की आवश्यकता होती है और आप या अन्य लोग जिस तरह से जसन क्रमांकन (मौजूदा कोड में या नहीं) का उपयोग करने के तरीके को नहीं बदलना चाहते हैं।
ध्यान दें कि कुछ इस तरह से खराब व्यवहार के रूप में पुस्तकालयों को पैच करने पर विचार कर सकते हैं। यदि आपको अपने आवेदन को एक से अधिक तरीकों से विस्तारित करने की इच्छा हो, तो विशेष देखभाल की आवश्यकता है - ऐसा एक मामला है, मैं रमेन या जेटी द्वारा समाधान का उपयोग करने का सुझाव देता हूं और प्रत्येक मामले में उचित जोंस एक्सटेंशन का चयन करता हूं।
None
। आप इसके बजाय एक अपवाद फेंकना चाह सकते हैं।
टाइमस्टैम्प को छोड़कर, सामुदायिक विकि उत्तर में जोड़ने के लिए बहुत कुछ नहीं !
जावास्क्रिप्ट निम्नलिखित प्रारूप का उपयोग करता है:
new Date().toJSON() // "2016-01-08T19:00:00.123Z"
अजगर पक्ष ( json.dumps
हैंडलर के लिए, अन्य उत्तर देखें):
>>> from datetime import datetime
>>> d = datetime.strptime('2016-01-08T19:00:00.123Z', '%Y-%m-%dT%H:%M:%S.%fZ')
>>> d
datetime.datetime(2016, 1, 8, 19, 0, 0, 123000)
>>> d.isoformat() + 'Z'
'2016-01-08T19:00:00.123000Z'
यदि आप उस जेड को छोड़ देते हैं, तो कोणीय जैसे फ्रंटएंड फ्रेमवर्क ब्राउज़र-स्थानीय टाइमज़ोन में दिनांक प्रदर्शित नहीं कर सकते हैं:
> $filter('date')('2016-01-08T19:00:00.123000Z', 'yyyy-MM-dd HH:mm:ss')
"2016-01-08 20:00:00"
> $filter('date')('2016-01-08T19:00:00.123000', 'yyyy-MM-dd HH:mm:ss')
"2016-01-08 19:00:00"
मेरी सलाह है कि एक पुस्तकालय का उपयोग करें। Pypi.org पर कई उपलब्ध हैं।
मैं इस का उपयोग करता हूं, यह अच्छा काम करता है: https://pypi.python.org/pypi/asjson
जाहिरा तौर पर "सही" JSON (अच्छी तरह से जावास्क्रिप्ट) दिनांक प्रारूप 2012-04-23T18: 25: 43.511Z - UTC और "Z" है। इसके बिना जावास्क्रिप्ट स्ट्रिंग से एक दिनांक () ऑब्जेक्ट बनाते समय वेब ब्राउज़र के स्थानीय समयक्षेत्र का उपयोग करेगा।
एक "भोले" समय के लिए (जिसे पायथन ने बिना समयक्षेत्र के एक समय कहा जाता है और यह माना जाता है कि स्थानीय है) नीचे स्थानीय समय-क्षेत्र को मजबूर कर देगा ताकि इसे तब सही ढंग से यूटीसी में परिवर्तित किया जा सके:
def default(obj):
if hasattr(obj, "json") and callable(getattr(obj, "json")):
return obj.json()
if hasattr(obj, "isoformat") and callable(getattr(obj, "isoformat")):
# date/time objects
if not obj.utcoffset():
# add local timezone to "naive" local time
# /programming/2720319/python-figure-out-local-timezone
tzinfo = datetime.now(timezone.utc).astimezone().tzinfo
obj = obj.replace(tzinfo=tzinfo)
# convert to UTC
obj = obj.astimezone(timezone.utc)
# strip the UTC offset
obj = obj.replace(tzinfo=None)
return obj.isoformat() + "Z"
elif hasattr(obj, "__str__") and callable(getattr(obj, "__str__")):
return str(obj)
else:
print("obj:", obj)
raise TypeError(obj)
def dump(j, io):
json.dump(j, io, indent=2, default=default)
यह इतना मुश्किल क्यों है।
पायथन से जावास्क्रिप्ट तिथि रूपांतरण के लिए, दिनांक ऑब्जेक्ट को विशिष्ट आईएसओ प्रारूप, यानी आईएसओ प्रारूप या यूनिक्स नंबर में होना चाहिए। यदि आईएसओ प्रारूप में कुछ जानकारी का अभाव है, तो आप पहले Date.parse के साथ यूनिक्स नंबर में बदल सकते हैं। इसके अलावा, Date.parse रिएक्ट के साथ काम करता है जबकि नई तिथि एक अपवाद को ट्रिगर कर सकती है।
यदि आपके पास मिलीसेकंड के बिना डेटटाइम ऑब्जेक्ट है, तो निम्नलिखित पर विचार किया जाना चाहिए। :
var unixDate = Date.parse('2016-01-08T19:00:00')
var desiredDate = new Date(unixDate).toLocaleDateString();
उदाहरण की तारीख समान रूप से एपीआई कॉल के बाद result.data ऑब्जेक्ट में एक चर हो सकती है।
वांछित प्रारूप में दिनांक प्रदर्शित करने के लिए विकल्पों के लिए (जैसे लंबे कार्यदिवस प्रदर्शित करने के लिए) एमडीएन डॉक्टर की जाँच करें ।