日期转换 .NET JSON 到 ISO
我想把一个来自JSON.Net的日期时间格式,比如:
/Date(1154970000000+0700)/
转换成ISO格式,比如:
2011-12-18T23:34:59Z
最好用Python或者JavaScript来实现。
我决定用JavaScript,因为在这个领域它是最常用的,容易理解,而且排序也很自然。我会根据每个用户的情况来存储时区偏移。
如果实现的过程有点复杂的话,能不能告诉我这两种格式的正确名称,这样我可能更容易理解如何进行转换。
4 个回答
1
这个功能可以返回带有时区信息的日期和时间,并且能正确处理John Machin的测试案例和"/Date(1428145200000+1200)/"
这种格式。
这个功能适用于Python 3.3及以上版本。如果你使用的是2.7版本,记得用pytz.utc
来代替datetime.timezone.utc
。
from datetime import datetime, timedelta, timezone
import re
def jsondate(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
3
[替代答案]
这里是一个Python 2.x的版本。测试部分的打印语句需要改成Python 3.x的格式。
根据我在网上查找的信息:主要的内容是从1970年1月1日开始的毫秒数。这个数值可以是负的。对于正数,不需要加+
符号。接下来可以有一个可选的时区偏移,这个偏移由5个字符组成:一个必需的符号(+
或-
),2个数字表示小时,和2个数字表示分钟。所有这些内容前面有"/Date(",后面有")/"。
这个答案提供了一个函数,用来把JSON.NET字符串转换成Python的datetime.datetime
(时间戳)对象,还有两个函数分别返回截断到秒和毫秒的ISO格式。
脚本:
# /Date(1154970000000+0700)/
# 0123456............7654321
# without timezone:
# /Date(1154970000000)/
# 0123456............21
# dodgy case
# /Date(-1234)/
# 3210987654321
import datetime
def json_date_as_datetime(jd):
sign = jd[-7]
if sign not in '-+' or len(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) * 60000
return datetime.datetime(1970, 1, 1) \
+ datetime.timedelta(microseconds=millisecs * 1000)
def datetime_as_iso(dt):
return dt.strftime("%Y-%m-%dT%H:%M:%SZ") # truncates
def datetime_as_iso_ms(dt): # with millisecs as fraction
return 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()
if not test: continue
d = json_date_as_datetime(test)
print datetime_as_iso_ms(d), test
输出:
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)/
1
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 = new Date(strDate);
if (!isNaN(strHour)) date.setHours(date.getHours() + strHour);
if (!isNaN(strMin)) date.setMinutes(date.getMinutes() + strMin);
var out = date.toISOString();
这是一个将数据转换为ISO格式的函数:
var toISOString = Date.prototype.toISOString ?
function(d){return d}:
(function(){
function t(i){return i<10?"0"+i:i};
function h(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};
function toISOString(){
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"
);
};
return function(d){
d.toISOString = toISOString;
return d;
}
})();