【问题标题】:Formatting DateTime to string with timezone information for Date created in Javascript将 DateTime 格式化为字符串,其中包含在 Javascript 中创建的 Date 的时区信息
【发布时间】:2017-01-10 13:57:54
【问题描述】:

在这个过于简单的例子中,我有一个控制器方法,它接受一个日期时间

[Route("api/demo)]
public IHttpActionResult Post(DateTime date)
{
   // format dateTime here
}

我们使用 Javascript 从客户端调用它。

var data = {
    date: new Date()
};

$.ajax({
    url: "/api/demo",
    type: 'POST',
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    data: JSON.stringify(data),
});

new Date() 部分是我认为最重要的部分,因为我们正在尝试记录调用客户看到的日期(他们的当地时间)

将 DateTime 对象格式化为字符串的最佳方法是什么,以便它记录时区信息,并在以后需要时再次解析回 DateTime 对象?

(我们将此格式化字符串存储在分析记录平台/数据仓库中)

【问题讨论】:

  • 你真的不关心数据存储在哪个时区,只关心本地时间。如果您在上午 9:00 在纽约输入日期并且您在加利福尼亚,您不想看到上午 6:00 而不是上午 9:00?
  • 如果你想包含一个时区,使用 DateTimeOffset,而不是 DateTime
  • 使用 DateTimeOffset 作为您的操作参数,并确保以 ISO8601 格式发送日期,例如“2014-05-06T22:24:55Z”。在这种情况下,您无需转换任何内容。

标签: c# datetime asp.net-web-api


【解决方案1】:

您不需要进行任何转换,只需将参数类型更改为DateTimeOffset

[Route("api/demo)]
public IHttpActionResult Post(DateTimeOffset date)
{
    //use the date without conversions.
}

JSON.stringify 使用 ISO8601 格式(例如 "2017-01-10T14:52:04.780Z")序列化日期,可以直接解析为 DateTimeOffset。 DateTimeOffset 允许您直接比较具有不同偏移量的值,无需转换为相同的时区

通过使用 DateTimeOffset,您可以避免本地和 UTC DateTime 值之间的混淆。在不知道时区偏移的情况下,您真的不知道“本地”指的是客户端还是服务器的时区?

【讨论】:

  • 谢谢 - 但我们如何 ToString date 参数?只是.ToString()?原因是,这是否被保存到期望字符串的第三方中
  • @Alex 只需像使用DateTime 一样使用ToString()String.Format()。如果其他服务了解 ISO8601,您可以按原样使用该值。如果它只需要UTC,您可以通过首先调用ToUniversalTime 来获取UTC 日期。
  • @Alex 是第三方数据库吗?一些数据库,例如 SQL Server 有一个datetimeoffset 类型,它也允许存储偏移量。
  • 不,它是 Keen.io - 本质上是一个 nosql 数据库,但实际上只接受文本。所以看看存储偏移量的 .tostring
  • Keen.io 也接受 ISO8601。只要确保您使用正确的格式字符串,例如o
【解决方案2】:

您可以在 javascript 中使用 new Date().getTimezoneOffset() 来了解客户端当前时区与 UTC 之间的差异。它的偏移量将在几分钟内。示例 - 新加坡时间和 UTC 之间的 TimezoneOffset 为 -480 分钟。

http://www.w3schools.com/jsref/jsref_gettimezoneoffset.asp

然后在 javascript 中创建一个 cookie 并将该偏移量存储在其中。

function setTimezoneCookie(){

    var timezone_cookie = "timezoneoffset";

    if (!$.cookie(timezone_cookie)) { 
        // create a new cookie 
        $.cookie(timezone_cookie, new Date().getTimezoneOffset());
    }
}

发送到服务器的每个请求都将携带该 cookie 并在服务器端 通过添加来自cookie的偏移量将客户端提交的日期时间转换为UTC并将其保存在数据库中。这将确保无论用户在哪个时区,数据始终具有统一的 UTC 日期和时间。

另外,当在 UI 中显示日期时间信息时,在发送到 UI 之前,通过减去从 cookie 检索到的偏移量将其转换为客户端时间。

这样可以确保用户根据其客户端计算机时区看到日期和时间。

在这种情况下,扩展方法会很方便。

public static DateTime ToClientTime(this DateTime dt)
    {
        // read the value from session
        var timeOffSet = HttpContext.Current.Request["timezoneoffset"];

        if (timeOffSet != null)
        {
            var offset = int.Parse(timeOffSet.ToString());
            dt = dt.AddMinutes(-1 * offset);

            return dt;
        }

        // if there is no offset in session return the datetime as it is
        return dt;
    }

public static DateTime ToUtcTime(this DateTime dt)
    {
        // read the value from session
        var timeOffSet = HttpContext.Current.Request["timezoneoffset"];

        if (timeOffSet != null)
        {
            var offset = int.Parse(timeOffSet.ToString());
            dt = dt.AddMinutes(offset);

            return dt;
        }

        // if there is no offset in session return the datetime as it is

        return dt;
    }

这应该可以帮助您解决问题。

【讨论】:

  • 最好使用 DateTimeOffset 类,而不是使用任意本地时间(本地时间对谁?服务器?)。
  • 我已更新我的代码以避免转换为 LocalTime。 ToLocalTime 方法会将 UTC 时间转换为用户请求数据的位置的本地时间。如果我们确保将 DateTimeOffset 与每个带有 DateTime 的请求一起传递给服务器,DateTimeOffset 肯定会很有用..
  • 确实如此。 JSON.stringify 将日期序列化为包含偏移量的 ISO8601 格式
  • 我的解决方案旨在确保日期和时间统一存储在数据库中,并在用户的当前时区显示。如果 DateTimeOffset 可以使这成为可能,我会认为它不那么复杂和首选的解决方案。
  • 然后在数据库中也使用datetimeoffset
猜你喜欢
  • 2012-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多