C# 使用Javascript中创建的日期的时区信息将DateTime格式化为字符串

C# 使用Javascript中创建的日期的时区信息将DateTime格式化为字符串,c#,datetime,asp.net-web-api,C#,Datetime,Asp.net Web Api,在这个过于简化的示例中,我有一个接受DateTime的控制器方法 [Route("api/demo)] public IHttpActionResult Post(DateTime date) { // format dateTime here } 我们使用Javascript从客户端调用它 var data = { date: new Date() }; $.ajax({ url: "/api/demo", type: 'POST', contentT

在这个过于简化的示例中,我有一个接受DateTime的控制器方法

[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),
});
newdate()
部分是我认为最重要的部分,因为我们试图记录调用客户机看到的日期(他们的本地时间)

将DateTime对象格式化为字符串的最佳方式是什么,这样它可以记录时区信息,并且可以在需要时重新解析回
DateTime
对象

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

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

然后在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;
    }

这将帮助您解决问题。

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

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


通过使用DateTimeOffset,可以避免本地和UTC日期时间值之间的混淆。如果不知道时区偏移量,您就不知道“本地”指的是什么-客户机的时区还是服务器的时区

你真的不在乎数据存储在哪个时区,只在乎本地时间。如果您在纽约9:00AM输入日期,并且您在加利福尼亚州,您不想看到6:00AM而不是9:00AM吗?如果您想包含时区,请使用DateTimeOffset,而不是DateTimeUse
DateTimeOffset
作为操作参数,并确保日期以ISO8601格式发送,例如“2014-05-06T22:24:55Z”。在这种情况下,您不必转换任何内容。与其使用任意的本地时间(本地为谁?服务器?),不如使用DateTimeOffset类。我已升级代码以避免转换为LocalTime。ToLocalTime方法将UTC时间转换为用户请求数据的位置的本地时间。如果我们确保将DateTimeOffset与每个带有DateTime的请求一起传递给服务器,DateTimeOffset肯定会很有用。stringify将日期序列化为ISO8601格式,该格式包含offsetMy解决方案旨在确保日期和时间统一存储在数据库中,并在用户的当前时区中显示。如果DateTimeOffset可以做到这一点,我会认为它不那么复杂,而且是首选的解决方案。然后在数据库中也使用
DateTimeOffset
,谢谢-但是我们如何
ToString
日期参数呢?只需
.ToString()
?原因是,这是保存到第三方,期待一个string@Alex只需使用
ToString()
String.Format()
,方法与使用
DateTime
相同。如果其他服务理解ISO8601,则可以按原样使用该值。如果它只需要UTC,您可以先调用UTC来获取日期。@Alex第三方是数据库吗?有些数据库,例如SQL Server有一个
datetimeoffset
类型,允许存储偏移量。不,它是Keen.io-本质上是一个nosql数据库,但实际上只接受文本。因此,在存储offsetKeen.io的.tostring时,也接受ISO8601。只需确保使用正确的格式字符串,例如
o
[Route("api/demo)]
public IHttpActionResult Post(DateTimeOffset date)
{
    //use the date without conversions.
}