【问题标题】:Date conversion: From LINQ to JSON to Javascript日期转换:从 LINQ 到 JSON 到 Javascript
【发布时间】:2012-07-17 16:36:57
【问题描述】:

简而言之,在我的 API 控制器和使用结果的 Javascript 之间,一个 Date 被转换成一个可爱的NaN

我的问题是,有人建议我在哪里以及如何修复这条长链。

第 1 步:使用 LINQ 从数据库中检索对象

return _dbContext.Points.Where(
    point => point.AccountId == account.AccountId)
    .OrderBy(point => point.EarnedOn).ToList();

在这里进行任何更改似乎都不合理。模型指定了一个 DateTime 字段,所以我们这里真的没有与字符串进行任何交互。

第 2 步:API 控制器发送响应

var points = _pointRepository.GetByUserName(userName);
return Request.CreateResponse(HttpStatusCode.OK, points);

我可以在这里指定如何解析日期吗?即使在服务器端处理也有意义吗?我想我可以遍历所有对象并手动设置它们,如下所示:

 for (var i = 0; i < points.Count(); i++ )
 {
     points.ElementAt(i).EarnedOn =  points.ElementAt(i).EarnedOn.ToUniversalTime();
 }

但是谈论多个枚举!

第 3 步:客户端将 JSON 数据解析为 JS 对象,然后将字符串中的 Date 解析为 int 大大缩短了可读性

var points = JSON.parse(response);
for(i = 0; i < points.length; i++){
    var date = Date.parse(points[i].EarnedOn);

在这一点上,我能做的只有这么多。我已经在第 2 步结束时将日期转换为字符串,而我的目标浏览器根本不知道如何使用 C# 的默认 DateTime.toString 格式(我假设这是正在发送的内容)。在某些浏览器中它可以工作,在其他浏览器中我得到NaN

抱歉,解释太长了,但如果有人能指出他们将在何处以及如何应用修复程序,我将不胜感激。

====更新====

有问题的浏览器是 Android 的普通浏览器。我已经在我的手机和 BlueStacks 模拟器上对此进行了测试。两者都是最新的,并且两者都不起作用。它在 Chrome 中确实有效。

当时的JSON输出(切掉所有其他数据)如下:

"EarnedOn":"2012-05-10T00:00:00" 

【问题讨论】:

  • 这看起来很奇怪。您的目标是什么浏览器,JSON 的实际外观是什么样的?你能把那个贴出来吗?至少是日期表示。
  • @aquinas 更新了我的问题来回答你的问题
  • This chart 表明有问题的格式只能被较新的浏览器识别,这可能是这里的问题。他忽略了在列表中显示移动浏览器
  • 可能要检查hanselman.com/blog/… - 请注意日期“literal”末尾的尾随“Z”。看来您可能也必须这样做。

标签: c# javascript json datetime formatting


【解决方案1】:

如何将 .Net 中的 DateTime 转换为时间戳/秒。 JavaScript 到日期对象的转换。不过我还没有在移动浏览器上测试过,所以不能 100% 有效。

DateTime myDateTime = new DateTime(2012, 01, 17, 9, 30, 0);

long ticks = (myDateTime - DateTime.Parse("01/01/1970 00:00:00")).Ticks;
ticks /= 10000000; //Convert ticks to seconds
var timestamp = ticks.ToString();

然后在 JavaScript 中,类似

secsToTime = function(theSecs)
{
    var date = new Date(theSecs*1000);
    // hours part from the timestamp

    var hours = date.getHours();
    // minutes part from the timestamp
    var minutes = date.getMinutes();
    // seconds part from the timestamp
    var seconds = date.getSeconds();

    // will display time in 10:30:23 format
    var formattedTime = hours + ':' + minutes + ':' + seconds;
    alert(formattedTime);
}

secsToTime(1326792600);

【讨论】:

  • 从技术上讲,我喜欢这个解决方案,因为它没有任何误解的余地,但我会在在哪里这样做?在我从 LINQ 获得列表之后?我觉得必须再次迭代该列表很愚蠢,但如果在 LINQ 本身中没有办法做到这一点,我想我别无选择
  • 系统的架构是什么?是实体框架吗?在将模型返回给客户端之前,您是否将其转换为 ViewModel?
  • 我正在使用实体框架,但我不倾向于将 ViewModel 用于 API JSON 请求。这是一个不好的做法吗?您可以在我的原始帖子的第 2 步中看到我发送请求的大部分内容
  • 这实际上取决于要求,例如您可能有无法传输给客户端的敏感数据。通常我使用 AutoMapper 投影到 ViewModel 中,以减少发送到客户端的数据量。或者,如果您想保留它,在您的模型中有一个额外的属性(而不是映射到 EF),它是以秒为单位的时间字符串,并使用循环更新它并将其用于客户端。
【解决方案2】:

我最初说我会使用 Date.js,但谷歌搜索显示它自 2007 年以来就没有提交过,并且充满了错误。此外,它只是不太正常。

截至目前,我已经厌倦了寻找合适的解决方案,并在第 3 步中使用以下 Javascript 代码。

function parseDate(date){
    var year = parseInt(date.substring(0,4));
    var month = parseInt(date.substring(5,7));
    var day = parseInt(date.substring(8,10));
    var hour = parseInt(date.substring(11,13));
    var minute = parseInt(date.substring(14,16));
    var second = parseInt(date.substring(17,19));
    return new Date(year, month, day, hour, minute, second);
}

for(i = 0; i < points.length; i++){
    var date = Date.parse(points[i].EarnedOn);
    ...

这真的很丑,但它是一个答案,所以我把它放在这里。我真的希望有人能找到比这更优雅的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-07
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多