8

我的 JSON 字符串包含一个返回此类值的日期字段:

"2009-04-04T22:55:16.0000000-04:00"

我对只解析日期而不是时间特别感兴趣。我尝试使用 reviver 函数,但有趣的是 reviver 函数从未被调用过!(在火狐上试过)

这是我的代码来实现这一点:

var Site = {
.....
dateReviver: function(key, value) {
    var a;
    if (typeof value === 'string') {
        a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
        if (a) {
            return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
                            +a[5], +a[6]));
        }
    }
    return value;
},
loadArticle: function(id) {
....
    proxy.getArticle(id, function(response) {
        var data = JSON.parse(response.result, Site.dateReviver);
        ....
    });
}
};

JSON.parse 在loadArticle从不调用dateReviver

我投资了一整天,但没有运气!有人可以帮我吗?

4

6 回答 6

9

使用 TypeScript,我的解决方案如下:

    export function parseWithDate(jsonString: string): any {
    var reDateDetect = /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/;  // startswith: 2015-04-29T22:06:55
    var resultObject = JSON.parse(jsonString,(key: any, value: any) => {
        if (typeof value == 'string' && (reDateDetect.exec(value))) {
            return new Date(value);
        }
        return value;
    });
    return resultObject;
}

最棒的 ;-) 它使用匿名的 datereviver,它被 JSON.parse 在每个属性上调用。reviver 逻辑是检查属性是否为字符串类型,如果是,它是否看起来像日期的开始......如果是日期,则让 new Date(value) 进行实际解析......所有以这种方式支持时区变化。

希望能帮助到你!

于 2015-04-30T15:14:20.713 回答
7
  1. 正则表达式需要一个“Zulu”时区(末尾有一个“Z”字符),而示例日期时间字符串显示一个数字时区(“-04:00”)。以下正则表达式将同时接受:

    /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)(Z|([+\-])(\d{2}):(\d{2}))$/
    

    如果时区数字不为零,您可能希望在解析和/或转换为 UTC 后实际修改日期,以尊重时区。

  2. 我可以看到 dateReviver() 被击中。在浏览器中尝试以下操作:

    <!-- saved from url=(0014)about:internet -->
    <html>
        <head>
            <script src="http://www.json.org/json2.js"></script>
            <script type="text/javascript" src="http://ajax.Microsoft.com/ajax/jQuery/jquery-1.3.2.js"></script>
            <script>
                $(function () {
                    // a mock proxy to return some json to play with
                    var proxy = {
                        getArticle: function(id, foo) { foo({
                            result: '["2009-04-04T22:55:16.0000000-04:00"]'
                        }); }
                    };
                    // the origial Site object, with the fixed regex
                    var Site = {
                        dateReviver: function(key, value) {
                            var a;
                            if (typeof value === 'string') {
                                a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)(Z|([+\-])(\d{2}):(\d{2}))$/.exec(value);
                                if (a) {
                                    return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
                                                    +a[5], +a[6]));
                                }
                            }
                            return value;
                        },
                        loadArticle: function(id) {
                            proxy.getArticle(id, function(response) {
                                var data = JSON.parse(response.result, Site.dateReviver);
                                // put the parsed JSON date on the page
                                $("#output").html(data[0].toString());
                            });
                        }
                    };
                    // try out our Site object
                    Site.loadArticle();
                });
            </script>
        </head>
        <body>
            <div id="output"></div>
        </body>
    </html>
    

    我在浏览器中得到以下信息,表明解析成功:

    Sat Apr 4 15:55:16 PDT 2009
    
于 2009-11-24T22:45:58.000 回答
3

从默认设置扩展 jQuery.ajax 转换器设置对我来说效果很好:

"text json": jQuery.parseJSON

"text json": function (xmlValue) {
            var value = JSON.parse(xmlValue, Site.dateReviver);
      return value;
      } 
于 2011-07-12T12:53:58.517 回答
2

指某东西的用途return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]));

不调整时区信息的日期,-4:00在示例中。

另一种方法是让 Date() 为您进行解析:

var dateReviver = function (key, value) {
    var a;
    if (typeof value === 'string') {
        a = Date.parse(value);
        if (a) {
            return new Date(a);
        }    
    }
    return value;
}

如果 JSON 已使用 JSON.stringify() 进行格式化,则它将采用 UTC (Z)。

于 2012-10-18T00:55:23.073 回答
0
function dateReviver (k,v) {

    var isnum = /^\d+$/.test(v);

    // Check if number since Date.parse(number) returns valid date
    if (isnum) {
        return v;
    }

    if (Date.parse(v)) {
        return new Date(Date.parse(v));
    }
    return v;
}
于 2016-09-16T10:00:09.647 回答
0

即插即用的解决方案

const jsonDateRegexp = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z$/;

function jsonRetriever(key: string, value: any) {
  // let's try to detect input we dont have to parse early, so this function is as fast as possible
  if (typeof value !== 'string') {
    return value;
  }

  const dateMatch = jsonDateRegexp.exec(value);

  if (!dateMatch) {
    return value;
  }

  return new Date(
    Date.UTC(
      +dateMatch[1],
      +dateMatch[2] - 1,
      +dateMatch[3],
      +dateMatch[4],
      +dateMatch[5],
      +dateMatch[6],
      +dateMatch[7],
    ),
  );
}

export function parseJsonWithDates(input: string) {
  return JSON.parse(input, jsonRetriever);
}
于 2020-03-01T20:08:03.277 回答