我正在使用json.net来反序列化a DateTimeOffset,但它忽略了指定的时区并将datetime转换为本地偏移量.例如,给定
var content = @"{""startDateTime"":""2012-07-19T14:30:00+09:30""}";
Run Code Online (Sandbox Code Playgroud)
使用以下方法进行反序列化时:
var jsonSerializerSettings = new JsonSerializerSettings() { DateFormatHandling = DateFormatHandling.IsoDateFormat, DateParseHandling = DateParseHandling.DateTimeOffset, DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind };
var obj = JsonConvert.DeserializeObject(content, jsonSerializerSettings);
Run Code Online (Sandbox Code Playgroud)
obj将包含一个包含a的属性,DateTimeOffset但该值将被2012-07-19T15:30:00+10:30转换为本地时区而不是保留原始时区.
有没有办法让值按预期进行解析,以便结果DateTimeOffset属性与提供的值匹配?
关于在DB中保存日期时间和时区信息有很多问题,但总体水平更多.在这里,我想谈谈一个具体的案例.
系统规格
DB中需要涵盖业务规则
ORDR-13432-Year-Month-Day).精确计算目前并不重要,重要的是它取决于租户的本地日期时间我们最初的想法
方法1
保存当地租户的日期时间对每个租户来说都不错,但是我们遇到的问题包括:
SELECT * FROM ORDERS WHERE OrderDateTime BETWEEN UTCDateTime1 AND UTCDateTime2
Run Code Online (Sandbox Code Playgroud)这是有问题的,因为OrderDateTime在这个查询中意味着基于租户的不同时刻.当然,此查询可能包括连接到Tenants表以获取本地日期时间偏移量,然后将在运行中进行计算OrderDateTime以进行调整.这是可能的,但不确定这是否是一个好方法呢?
方法2
让我们举一个极端的例子; 让我们说租户比UTC早6个小时,他的当地日期时间是2017-01-01 02:00.UTC会是2016-12-31 20:00.此时下达的订单应该获得OrderNumber 'ORDR-13432-2017-1-1'但是如果保存UTC则会得到ORDR-13432-2016-12-31.
在这种情况下,在DB中创建Order时,我们应该根据重新计算的租户本地时间获得UTC日期时间,租户偏移和编译OrderNumber,但仍然以UTC格式保存DateTime列.
问题
[UPDATE]
根据Gerard Ashton和Hugo的评论:
如果租户可以改变时区,那么最初的问题就细节而言并不明确,如果政治当局改变时区属性或某个时区的时区会发生什么.当然,这是非常重要的,但它不是这个问题的核心.我们可以在另一个问题中解决这个问题.
为了这个问题,让我们假设租户不会改变位置.该位置的时区属性或时区本身可能会发生变化,这些更改将在系统中与此问题分开处理.
我需要将UTC日期字符串转换为DateTimeOffsets.
这必须使用与计算机时区不同的时区. 例如,当前计算机时区是+02:00,但我想创建一个偏移-4:00的DateTimeOffset.
我已经在stackoverflow上阅读了很多问题,但没有一个能解决我的问题.
这就是我需要做的事情:
输入: "2012-11-20T00:00:00Z"
输出: DateTimeOffset:
当然,必须考虑夏令时.
编辑:为了使事情更清楚,请尝试完成以下代码段:
DateTimeOffset result;
const string dateString = "2012-11-20T00:00:00Z";
var timezone = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); //this timezone has an offset of +01:00:00 on this date
//do conversion here
Assert.AreEqual(result.Offset, new TimeSpan(1, 0, 0)); //the correct utc offset, in this case +01:00:00
Assert.AreEqual(result.UtcDateTime, new DateTime(2012, 11, 20, 0, 0, 0)); //equals the original date
Assert.AreEqual(result.LocalDateTime, …Run Code Online (Sandbox Code Playgroud) 我有一个旧表,其中有几行具有日期时间列.我想将其切换到datetimeoffset但我希望能够传输已存在的数据.所以我做的事情如下:
SET IDENTITY_INSERT Table_Temp ON
INSERT INTO Table_Temp
(Col0, ... ColN,)
SELECT
COl0,.... ColN, from
Table_Original;
SET IDENTITY_INSERT Table_Temp OFF
Run Code Online (Sandbox Code Playgroud)
这可以工作,但是当我执行dattime到datetimeoffset赋值时,偏移设置为0.幸运的是,我想要设置的偏移量是当前系统的偏移量.我不是tsql大师,但我似乎无法找到一个简单的方法来做到这一点.
我希望能够在转换中设置偏移量.我打算使用ac#utility(或PowerShell),但我宁愿保持简单.
好吧,过去几周我一直在努力工作,我遇到了一个小问题.我认为我的思想现在不能完成任务:)所以我需要一些提示/帮助!这可能很简单,但我的头还没有点击.
用户将在AEST中输入日期和时间.还有一个应用程序集"默认"时区(因为它可能需要更改),目前设置为"AUS东部标准时间"
因此,我们在美国的服务器上有一个没有时区和定义的系统时区的用户字符串(因此本地不匹配,无法更改或使用)
现在我需要的是一种方式来说"使用时区X解析这个用户输入的字符串"我不能只输入+10或+11作为偏移量,因为日期可以是夏令时之内或之外; 即使对于相同的时区,肯定会在+10和+11之间进行更改!
当前的AEST时间也可能在DST之内或之外,因此我不能将UTC日期转换为当前的AEST时间并获取"zzz"字符串并将其附加,因为日期将在一小时后关闭以输入任何内容当前DST设置.
现在代码实际上就是这样:
TimeZoneInfo ConvTo = TimeZoneInfo.FindSystemTimeZoneById(ConfigurationManager.AppSettings["DefaultTimeZone"]);
DateTimeOffset getDate = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, ConvTo);
string TimeZoneId = " " + getDate.ToString("zzz");
DateTimeOffset cvStartDate = DateTimeOffset.MinValue; DateTimeOffset.TryParse(StartDate + TimeZoneId, out cvStartDate);
Run Code Online (Sandbox Code Playgroud)
然后我通过检查它是否仍然== DateTimeOffset.MinValue或将其转换为UTC并添加到数据库来检查日期是否无效,它将在显示时转换回AEST.然而,有些日期是一小时,其他日期是完美的(如预期的那样):)
解决这个问题最优雅的方法是什么?
编辑:
为了帮助解释这个问题,我写了一些测试代码作为Windows测试应用程序:
// User entered date
string EnteredDate = "2011/01/01 10:00:00 AM";
// Get the timezone we want to use
TimeZoneInfo myTimeZone = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");
// Find the timezone string of the selected timezone to parse the user string
// This is the …Run Code Online (Sandbox Code Playgroud) 我知道DateTimeOffset存储UTC日期/时间和偏移量.我也从MSDN博客文章中了解到,DateTimeOffset应该用于"使用夏令时".
我正在努力理解的是DateTimeOffset"夏令时"的工作原理.我的理解,很少有,是夏令时是一个政治决定,不能从纯粹的抵消中推断出来.如果它只存储一个偏移,那么这个结构对DST是否友好呢?
我认为可能有一种方法可以将TimeZoneInfo类与DateTimeOffset结合使用.我该怎么办?
最后,有什么更好的方法可以实现以下目标吗?
(我看过Jon Skeet关于Noda-Time的一些帖子,但我认为它还没有准备好生产,我不知道它是否能很好地融入我们现有的解决方案).
这是我们的场景.该服务器是出于在英国时间运行的不幸遗留原因.我们的客户开始从澳大利亚投入运营,其中有多个时区.其他国家可以随时投入使用.
我们有一个基于Hardcodet调度程序的调度程序(使用DateTimeOffset).它工作得很好.但是,在我们的数据库中,我们只存储足够的数据来构造DateTime对象(见下文),在我们的子类和管道代码中我们只使用DateTime,因为最初我们只支持英国用户.
该调度程序负责固定和动员工厂设备.因此,预定事件在用户的DST调整后的当地时间运行至关重要.
用户在我们的网站上输入时间表; 目前,它作为星期几,小时和分钟存储在数据库中.当读取数据时,我们为该日,小时和分钟的下一次出现创建一个DateTime对象.我可以自由地改变db结构以另外存储偏移量或时区.
当该日期和时间到达时,调度程序发送命令(并重试一段时间).它然后在下周的同一天和时间再次运行(虽然该服务实际上已经被回收,然后代码将再次运行).
我需要实现的是使用从Hardcodet子类调度的调度程序在该时区调整的本地日期和时间触发调度事件.如果DateTimeOffset确实是DST感知的,那么我需要做的就是存储一个偏移并改变我们的管道代码以使用这个结构,但我得到的印象并不是那么简单.(我们或许可以从工厂的GPS位置获取当前时区,但这是另一天的讨论:)).
我有一个我解析的字符串DateTime.strptime.字符串中Date的时区是CET,但Ruby创建了一个UTC DateTime对象,当然它的偏移量为2小时.
目前我正在解决这个问题,DateTime.strptime().change(:offset => "+0020")但我很确定这不是它的工作方式.
有人可以用正确的方法来启发我吗?
我在ASP.NET MVC3控制器中有以下代码:
public PartialViewResult GetCalendar(int? month, int? year)
{
var test = new DateTime((year.HasValue ? year.Value : 1), (month.HasValue ? month.Value : 1), 1);
return PartialView("Calendar", new DateTimeOffset(test));
}
Run Code Online (Sandbox Code Playgroud)
我的观点模型是 DateTimeOffset?
抛出异常的原因是什么?
我正在考虑使用新的java 8 Date Time API.我google了一下,发现jodaTime是java的好选择,但仍然有兴趣看看这个新的API是如何工作的.
我存储UTC值的所有时间,我的数据存储,并根据用户的时区他们被转换为本地时区的具体价值.我可以找到许多文章,展示如何使用新的Java Date Time API.但是我不确定API是否会处理DST更改?或者我们有更好的处理日期的方法吗?
我刚学的新日期API,所以认为在处理日期时间和用户时区的基础上,显示它听到你的想法的.
我们的应用程序是一个很大的n层ASP.NET MVC应用程序,它严重依赖于Dates和(local)Times.到目前为止,我们已经使用DateTime了所有模型,这些模型运行良好,因为多年来我们严格地是一个国家网站,处理单个时区.
现在情况发生了变化,我们正在为国际观众敞开大门.第一个想法是"哦,废话.我们需要重构我们的整个解决方案!"
我们打开了LinQPad并开始绘制各种转换器,根据基于用户的配置文件中用户的TimeZone ID值创建的对象,将常规DateTime对象转换为DateTimeOffset对象TimeZoneInfo.
我们计算过,我们可以将所有DateTime属性的车型进入DateTimeOffset,并用它做.毕竟,我们现在拥有了存储和显示用户本地日期和时间所需的所有信息.
许多代码片段都受到Rick Strahl关于这一主题的博客文章的启发.
但后来我读到了马特约翰逊的出色评论.他验证了我打算转而DateTimeOffset声称:"DateTimeOffset在Web应用程序中至关重要".
关于Noda Time,Matt说:
说到Noda Time,我不同意你的意见,你必须更换整个系统中的所有内容.当然,如果你这样做,你将有更少的机会犯错误,但你肯定可以在有意义的地方使用Noda Time.我个人致力于使用IANA时区进行时区转换的系统(例如"America/Los_Angeles"),但跟踪DateTime和DateTimeOffset类型中的所有其他内容.实际上很常见的是Noda Time在应用程序逻辑中广泛使用,但完全脱离了DTO和持久层.在某些技术中,如实体框架,如果您愿意,则无法直接使用Noda Time - 因为没有地方可以将其连接起来.
这可以直接针对我们,因为我们现在正处于这种情况,包括我们选择使用IANA时区.
我们的主要目标是创建最复杂的工作流程来处理不同时区的日期和时间.在我们的服务,存储库和控制器中尽可能避免时区计算.
简而言之,该计划是接受来自我们前端的本地日期和时间,在将信息保存到数据库之前,尽快将它们转换为a ZonedDateTime并将其转换为DateTimeOffset尽可能晚.
确定正确的关键因素ZonedDateTime是TimeZoneIdUser模型中的属性.
public class ApplicationUser : IdentityUser
{
[Required]
public string TimezoneId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
为了防止大量重复代码,我们的计划是创建将本地转换DateTime …
datetimeoffset ×10
c# ×5
datetime ×4
timezone ×4
.net ×2
nodatime ×2
asp.net-mvc ×1
dst ×1
exception ×1
java ×1
json.net ×1
ruby ×1
scheduling ×1
sql ×1
sql-server ×1
strptime ×1
t-sql ×1
utc ×1