debugging 如何使用JSON.parse reiver参数解析日期字符串

mmvthczy  于 2022-12-13  发布在  其他
关注(0)|答案(7)|浏览(161)

我的JSON字符串包含一个日期字段,该字段返回这样一个值:

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

我特别感兴趣的是只解析日期而不是时间。我试过使用一个reviver函数,但有趣的是reviver函数从来没有被调用过!(在Firefox上试过)
下面是我的代码:

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);
        ....
    });
}
};

loadArticle中的JSON.parse从不调用dateReviver
我投资了一整天,但运气不好!有人能帮帮我吗?

pbwdgjma

pbwdgjma1#

使用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)来做实际的解析...这样就支持所有时区的变体。
希望能有所帮助!

kb5ga3dv

kb5ga3dv2#

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后实际修改日期,以符合时区。
1.我可以看到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
ppcbkaq5

ppcbkaq53#

扩展 AJAX 转换器的默认设置对我来说很有效:

"text json": jQuery.parseJSON

"text json": function (xmlValue) {
            var value = JSON.parse(xmlValue, Site.dateReviver);
      return value;
      }
qvtsj1bj

qvtsj1bj4#

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)。

nvbavucw

nvbavucw5#

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;
}
ygya80vv

ygya80vv6#

嵌入式解决方案

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);
}
siotufzp

siotufzp7#

我今天遇到了这个问题,我有一个不同的方法,从那些由其他人贡献。
如果你知道包含日期的键提前的时间,你可以写这样的reviver:

export const jsonDateReviver = (keysToParse: Record<string, boolean>) => (key: string, value: any) => {
  if (keysToParse[key]) {
    if (Array.isArray(value)) {
      return value.map(v => new Date(v));
    }
    return new Date(value);
  }
  return value;
};

然后,您可以像这样使用它:

JSON.parse(data, jsonDateReviver({ lastModifiedAt: true }))

或者,您可以使用全局keysToParse对象,而不是每次都重新定义它

相关问题