Date Conversion .net Json To Iso
Solution 1:
[Replacement answer]
Here is a Python 2.x version. Only the print statements in the testing section need to be changed for Python 3.x.
As far as I can ascertain by googling: The main component is milliseconds since 1970-01-01. It can be negative. A +
sign is NOT expected for positive numbers. This can be followed by an OPTIONAL offset from UTC, which consists of 5 characters: an mandatory sign (+
or -
), 2 digits for hours, and 2 digits for minutes. All of the above is preceded by "/Date(" and followed by ")/".
This answer provides a function to convert the JSON.NET string to a Python datetime.datetime
(timestamp) object, and 2 functions to return ISO format truncated to seconds and milliseconds respectively.
Script:
# /Date(1154970000000+0700)/# 0123456............7654321# without timezone:# /Date(1154970000000)/# 0123456............21# dodgy case# /Date(-1234)/# 3210987654321import datetime
defjson_date_as_datetime(jd):
sign = jd[-7]
if sign notin'-+'orlen(jd) == 13:
millisecs = int(jd[6:-2])
else:
millisecs = int(jd[6:-7])
hh = int(jd[-7:-4])
mm = int(jd[-4:-2])
if sign == '-': mm = -mm
millisecs += (hh * 60 + mm) * 60000return datetime.datetime(1970, 1, 1) \
+ datetime.timedelta(microseconds=millisecs * 1000)
defdatetime_as_iso(dt):
return dt.strftime("%Y-%m-%dT%H:%M:%SZ") # truncatesdefdatetime_as_iso_ms(dt): # with millisecs as fractionreturn dt.strftime("%Y-%m-%dT%H:%M:%S.%%03dZ") \
% (dt.microsecond // 1000) # truncate if __name__ == "__main__":
tests = """\
/Date(1154970000000+0700)/
/Date(-1234)/
/Date(1000+0200)/
/Date(0+0000)/
/Date(0)/
/Date(0-0700)/
/Date(0-0730)/
/Date(0-0030)/
/Date(-1577923200000+0000)/
/Date(1)/
/Date(499)/
/Date(500)/
/Date(501)/
/Date(999)/
/Date(1000)/
/Date(-1)/
""".splitlines()
for test in tests:
test = test.strip()
ifnot test: continue
d = json_date_as_datetime(test)
print datetime_as_iso_ms(d), test
Output:
2006-08-08T00:00:00.000Z /Date(1154970000000+0700)/
1969-12-31T23:59:58.766Z /Date(-1234)/
1970-01-01T02:00:01.000Z /Date(1000+0200)/
1970-01-01T00:00:00.000Z /Date(0+0000)/
1970-01-01T00:00:00.000Z /Date(0)/
1969-12-31T17:00:00.000Z /Date(0-0700)/
1969-12-31T16:30:00.000Z /Date(0-0730)/
1969-12-31T23:30:00.000Z /Date(0-0030)/
1920-01-01T00:00:00.000Z /Date(-1577923200000+0000)/
1970-01-01T00:00:00.001Z /Date(1)/
1970-01-01T00:00:00.499Z /Date(499)/
1970-01-01T00:00:00.500Z /Date(500)/
1970-01-01T00:00:00.501Z /Date(501)/
1970-01-01T00:00:00.999Z /Date(999)/
1970-01-01T00:00:01.000Z /Date(1000)/
1969-12-31T23:59:59.999Z /Date(-1)/
Solution 2:
jsonDate = "/Date(1154970000000+0700)/";
var strDate = parseInt(jsonDate.replace(/\/Date\(([-\d]+).*$/, "$1"));
var strHour = parseInt(jsonDate.replace(/.*\d([+-]\d\d).*$/, "$1"), 10);
var strMin = parseInt(jsonDate.replace(/.*\d([+-])\d\d(\d\d).*$/, "$1$2"), 10);
var date = newDate(strDate);
if (!isNaN(strHour)) date.setHours(date.getHours() + strHour);
if (!isNaN(strMin)) date.setMinutes(date.getMinutes() + strMin);
var out = date.toISOString();
And the function to convert to ISO:
var toISOString = Date.prototype.toISOString ?
function(d){return d}:
(function(){
functiont(i){return i<10?"0"+i:i};
functionh(i){return i.length<2?"00"+i:i.length<3?"0"+i:3<i.length?Math.round(i/Math.pow(10,i.length-3)):i};
functiontoISOString(){
return"".concat(
this.getUTCFullYear(), "-",
t(this.getUTCMonth() + 1), "-",
t(this.getUTCDate()), "T",
t(this.getUTCHours()), ":",
t(this.getUTCMinutes()), ":",
t(this.getUTCSeconds()), ".",
h("" + this.getUTCMilliseconds()), "Z"
);
};
returnfunction(d){
d.toISOString = toISOString;
return d;
}
})();
Solution 3:
Returns timezone aware datetimes and provides correct output for John Machin's test cases and "/Date(1428145200000+1200)/"
Python >3.3 compatible. For 2.7, use pytz.utc
instead of datetime.timezone.utc
.
from datetime import datetime, timedelta, timezone
import re
defjsondate(jsondate, tzinfo=timezone.utc):
"""Converts an ASP.NET json date: "/DATE(x)/" to tz-aware datetime object."""
regex = (
r"/Date\("r"(?P<milleseconds>[\-]?\d+)"r"(?P<offset>"r"(?P<offset_sign>[\+\-])"r"(?P<offset_hours>[01][0-9]|2[0-3])"r"(?P<offset_mins>[0-5][0-9])"r")?\)/"
)
try:
parts = re.match(regex, jsondate).groupdict()
except (AttributeError, TypeError):
raise ValueError("Unsupported ASP.NET JSON Date Format: %s" % jsondate)
since_epoch = timedelta(microseconds=1000 * int(parts['milleseconds']))
if parts.get('offset'):
since_epoch += timedelta(
hours=int("%s%s" % (parts['offset_sign'], parts['offset_hours'])),
minutes=int("%s%s" % (parts['offset_sign'], parts['offset_mins']))
)
return datetime(year=1970, month=1, day=1, tzinfo=tzinfo) + since_epoch
Solution 4:
Here's a little class I wrote years ago to clean up this sort of invalid JSON that some .NET library generates:
classDotNETDecoder(simplejson.JSONDecoder):
'''
This is a decoder to convert .NET encoded JSON into python objects
The motivation for this is the way .NET encodes dates.
See:
https://msdn.microsoft.com/en-us/library/bb299886.aspx#intro_to_json_topic2
.NET encodes datetimes like this: "\/Date(628318530718)\/"
'''def__init__(self, timezone, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.parse_string = self._date_parse_string(timezone)
self.scan_once = py_make_scanner(self)
@staticmethoddef_date_parse_string(timezone):
def_parse_string(string, idx, encoding, strict):
obj = scanstring(string, idx, encoding, strict)
ifisinstance(obj[0], str):
match = date_match.search(obj[0])
if match:
return [dt.datetime.fromtimestamp(
int(match.group(1)) / 1000, timezone),
obj[1]]
return obj
return _parse_string
And a test case / example:
deftest_can_decode_dotnet_json_dates():
jsonstr = '{"date": "Date(1330848000000)", "f": "b", "l": [], "i": 5}'
timezone = pytz.timezone('America/New_York')
obj = json.loads(jsonstr, cls=DotNETDecoder, timezone=timezone)
assert obj['date'] == timezone.localize(dt.datetime(2012, 3, 4, 3, 0))
assert obj['f'] == "b"assert obj['i'] == 5assert obj['l'] == []
Post a Comment for "Date Conversion .net Json To Iso"