Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript DateTime在数据库中以UTC表示,不从控制器执行时区转换,仅在客户端浏览器中处理转换_Javascript_C#_Asp.net Mvc_Json.net_Momentjs - Fatal编程技术网

Javascript DateTime在数据库中以UTC表示,不从控制器执行时区转换,仅在客户端浏览器中处理转换

Javascript DateTime在数据库中以UTC表示,不从控制器执行时区转换,仅在客户端浏览器中处理转换,javascript,c#,asp.net-mvc,json.net,momentjs,Javascript,C#,Asp.net Mvc,Json.net,Momentjs,我面临着一个有很多讨论的问题。事实上,我读了两天的问答,试图找到一个处理问题的好方法。这个问题是一个相当基本的概念。日期和时间应发送到mvc控制器方法,并作为UTC保存在数据库中。关于这个主题,我能找到的所有答案都是关于在控制器方法本身中处理UTC转换的。我特别想处理客户机代码中的所有日期转换。我还需要使用SQLCommand来查询包含日期的表,而不是使用Linq/EF。我发现的一些解决方案是关于在Newtonsoft序列化中使用DateTime.SpecifyKind和使用JsonSerial

我面临着一个有很多讨论的问题。事实上,我读了两天的问答,试图找到一个处理问题的好方法。这个问题是一个相当基本的概念。日期和时间应发送到mvc控制器方法,并作为UTC保存在数据库中。关于这个主题,我能找到的所有答案都是关于在控制器方法本身中处理UTC转换的。我特别想处理客户机代码中的所有日期转换。我还需要使用SQLCommand来查询包含日期的表,而不是使用Linq/EF。我发现的一些解决方案是关于在Newtonsoft序列化中使用DateTime.SpecifyKind和使用JsonSerializerSettings作为DateTimeZoneHandling.Utc

例如。。。我将日期作为DateTime可为空的数据类型存储在Sql Server数据库中。我使用军事时间并以以下格式存储它

2020-05-04 16:52:00.000

以下代码是所有用html/jquery/js编写的客户端代码:

在我正在使用的系统中,我使用FlatPicker在输入上设置日期选择器

<div class="flatpickrcontainer">
     <input type="text" id="time" class="form-control" placeholder="Select Date..." data-input>
</div>
flatpickr_for_add现在是一个可以用方法调用的实例。接下来我要做的是将FlatPicker数据转换成如下字符串:

var strInputDate=flatpickr\u用于添加所选日期[0]

我的问题是,如何将这个日期和时间从flatpickr字符串转换为UTC,然后使用AJAX/JSON/JS/JQUERY/C#MVC SqlServer的任意/全部将其存储在数据库中


我问题的第二部分是,如何从数据库中检索日期时间并将其返回到浏览器,同时将日期时间从UTC转换为用户的本地浏览器时区?

以下是我最终处理此问题的方法。我希望它能帮助其他人,我也希望我把这篇文章放在一起不会有任何可疑的技巧

在我的c#mvc服务器代码中,我的类与此类似

public class GridRecord
{
     public int id { get; set; }
     public DateTime? opened_dt { get; set; }
     public DateTime? closed_dt { get; set; }
}
注意我使用了DateTime?对于类型,不是DateTimeOffset

假设您已格式化SQLCommand并准备就绪,并且您的类(在我的示例中,GridRecord是类的名称)与sql列数据的结果匹配,请在c#mvc控制器方法中执行此操作:

//...here we would set up the connection string and define a variable typed to the class (GridRecord) 
//that will hold the returned data from the sqlcommand... for this variable I will use var sqlGridData 
//... and we can handle any passed in values from the controller method parameters, 
//like specialdata here in this area before we call the sqlcommand...
using (SqlConnection sqlconn = new SqlConnection(constring))
{
     SqlCommand command = new SqlCommand(sql, sqlconn);
     sqlconn.Open();
     SqlDataReader reader = command.ExecuteReader();
     try
     {
          var dataTable = new DataTable();
          dataTable.Load(reader);
          if (dataTable.Rows.Count > 0)
          {
               var serializedMyObjects = JsonConvert.SerializeObject(dataTable);
               sqlGridData = (List<GridModel.GridRecord>)JsonConvert.DeserializeObject(serializedMyObjects,typeof(List<GridModel.GridRecord>));
          }
     }
     //add catch{} here to handle exception if desired (good practice)
     finally
     {
          reader.Close();
     }
}
请注意,我们必须使用JsonSerializerSettings将DateTimeZoneHandling定义为未指定。这就是使用ActionResult而不是使用JsonResult的原因

对于客户端代码,我们在传递给控制器方法的格式上有更多的灵活性。我建议在数据库中存储数据时使用军事时间。我不打算在这里详细介绍ajax调用,将日期发送到服务器并保存在数据库中,因为如果要执行get或POST来调用该方法,这取决于您自己,也取决于您如何设置ajax数据对象

下面是我为controller方法的那一部分所做的示例(请注意,在这里使用JsonResult是可以的,因为我们只是发布数据,除了可能的错误代码之外,没有实际的返回预期)。您可以这样做:

注意,在上面的代码中,我将参数作为字符串接收到控制器方法,然后使用Convert.ToDateTime()处理数据库中DateTime数据类型的日期字符串转换

要在将最终用户浏览器上的日期发送到控制器方法之前将其格式化为UTC,在javascript/jquery代码中,我使用moment.js:

moment.utc(moment(dateStringVariableFromInput).utc().format('YYYY-MM-DD HH:mm:ssZ')).format('MM/DD/YYYY HH:mm');
或者,您可以使用以下方式从用户浏览器发送当前日期和时间:

moment.utc(new Date()).format("MM/DD/YYYY HH:mm")
如果您希望使用MM/DD/YYYY HH:MM以外的格式,则此解决方案的格式非常灵活,只要您使用的格式是moment.js友好的。就像我说的,你可能想坚持军事时间,这样你就不必应付上午/下午。有关可接受格式的详细信息,请查看

一旦您从控制器方法接收到数据,并且准备将UTC的日期/时间转换回用户的浏览器日期时间,那么您可以使用如下的矩.js语句

moment.utc(moment(dateStringFromController).format('YYYY-MM-DD HH:mm:SS')).local().format('MM/DD/YYYY h:mm A');
更新 在使用上面提到的代码将utc时间转换为本地时区一段时间后,我注意到转换为本地时间的这行代码并不总是起作用。我现在使用一个与矩时区相结合的函数,用于将从控制器方法检索到的UTC时间转换为用户的本地时区

  • 新增时刻时区最新稳定npm i时刻时区
  • 将矩-timezone-with-data-2012-2022.min.js添加到我的包中
  • 在我的js代码中添加了一个函数
  • 将我的js代码中的行替换为将utc转换为当地时间
  • 被替换

    moment.utc(moment(dateStringFromController).format('YYYY-MM-DD HH:mm:SS')).local().format('MM/DD/YYYY h:mm A');
    

    utcToLocal(dateStringFromController, moment.tz.guess())
    

    不错!我们也经历过类似的过程,但在服务器端保持日期转换。不过,这看起来是一个不错的实现
    moment.utc(moment(dateStringFromController).format('YYYY-MM-DD HH:mm:SS')).local().format('MM/DD/YYYY h:mm A');
    
    function utcToLocal(utcdateTime, tz) {
        var zone = moment.tz(tz).format("Z") // Actual zone value e:g +5:30
        var zoneValue = zone.replace(/[^0-9: ]/g, "") // Zone value without + - chars
        var operator = zone && zone.split("") && zone.split("")[0] === "-" ? "-" : "+" // operator for addition subtraction
        var localDateTime
        var hours = zoneValue.split(":")[0]
        var minutes = zoneValue.split(":")[1]
        if (operator === "-") {
            localDateTime = moment(utcdateTime).subtract(hours, "hours").subtract(minutes, "minutes").format("YYYY-MM-DD HH:mm:ss")
        } else if (operator) {
            localDateTime = moment(utcdateTime).add(hours, "hours").add(minutes, "minutes").format("YYYY-MM-DD HH:mm:ss")
        } else {
            localDateTime = "Invalid Timezone Operator"
        }
        return localDateTime
    }
    
    
    moment.utc(moment(dateStringFromController).format('YYYY-MM-DD HH:mm:SS')).local().format('MM/DD/YYYY h:mm A');
    
    utcToLocal(dateStringFromController, moment.tz.guess())