如时区标签wiki中所述,有两种不同的时区样式.
Microsoft提供的用于Windows和.Net TimeZoneInfo类的那些由诸如的值标识"Eastern Standard Time".
IANA在TZDB中提供的内容由诸如此类的值标识TimeZoneInfo.
许多基于Internet的API使用IANA时区,但由于多种原因,可能需要将其转换为Windows时区ID,反之亦然.
如何在.Net中实现这一目标?
我真的希望能够在我的Entity Framework Code First数据库项目中使用NodaTime,但还没有找到一种"干净"的方法来实现它.我真正想做的是:
public class Photoshoot
{
public Guid PhotoshootId{get; set;}
public LocalDate ShootDate{get; set;} //ef ignores this property
}
Run Code Online (Sandbox Code Playgroud)
是否有任何支持或推荐的方法将NodaTime与EF Code First一起使用?
我们的应用程序旨在处理来自不同地理位置的用户.
我们无法检测当前最终用户当地时间和时区对其进行操作的情况.他们选择不同的文化,如sv-se,en-us,ta-In甚至他们从欧洲/伦敦时区访问..
我们在美国托管服务器托管它,应用程序用户来自 Norway/Denmark/Sweden/UK/USA/India
问题是我们用来DateTime.Now存储记录创建/更新日期等.
由于服务器在美国运行,所有用户数据都保存为美国时间:(
在SO中进行研究后,我们决定将所有历史日期存储在DB中 DateTime.UtcNow
问题:

创建了一条记录29 Dec 2013, 3:15 P.M Swedish time.
public ActionResult Save(BookingViewModel model)
{
Booking booking = new Booking();
booking.BookingDateTime = model.BookingDateTime; //10 Jan 2014 2:00 P.M
booking.Name = model.Name;
booking.CurrentUserId = (User)Session["currentUser"].UserId;
//USA Server runs in Pacific Time Zone, UTC-08:00
booking.CreatedDateTime = DateTime.UtcNow; //29 Dec 2013, 6:15 A.M
BookingRepository.Save(booking);
return View("Index");
}
Run Code Online (Sandbox Code Playgroud)
我们希望向在India/Sweden/USA登录的用户显示相同的历史记录时间.
截至目前,我们正在使用当前文化用户登录并从配置文件中选择时区并使用TimeZoneInfo类进行转换
<appSettings>
<add key="sv-se" value="W. Europe Standard Time" />
<add key="ta-IN" value="India Standard …Run Code Online (Sandbox Code Playgroud) 我正试图让Jon Skeet(以及其他人)使用Noda Time框架.
我正试图现在存储当前(即时).Instant是从长时间刻度创建的,但是现在的Ticks数量是多少呢?
是吗:
Instant now = new Instant(DateTime.Now.ToUniversalTime().Ticks);
Run Code Online (Sandbox Code Playgroud)
还是?
Instant now = Instant.FromDateTimeUtc(DateTime.Now.ToUniversalTime());
Run Code Online (Sandbox Code Playgroud)
它们是等价的,我甚至做得对吗?
PS,如果Jon回答这个问题 - 我想提出一个Instant.Now属性.
PS2我知道标题包含一个标签,但它不会让我有一个简短的"Instant.Now"标题.
我知道DateTimeOffset存储UTC日期/时间和偏移量.我也从MSDN博客文章中了解到,DateTimeOffset应该用于"使用夏令时".
我正在努力理解的是DateTimeOffset"夏令时"的工作原理.我的理解,很少有,是夏令时是一个政治决定,不能从纯粹的抵消中推断出来.如果它只存储一个偏移,那么这个结构对DST是否友好呢?
我认为可能有一种方法可以将TimeZoneInfo类与DateTimeOffset结合使用.我该怎么办?
最后,有什么更好的方法可以实现以下目标吗?
(我看过Jon Skeet关于Noda-Time的一些帖子,但我认为它还没有准备好生产,我不知道它是否能很好地融入我们现有的解决方案).
这是我们的场景.该服务器是出于在英国时间运行的不幸遗留原因.我们的客户开始从澳大利亚投入运营,其中有多个时区.其他国家可以随时投入使用.
我们有一个基于Hardcodet调度程序的调度程序(使用DateTimeOffset).它工作得很好.但是,在我们的数据库中,我们只存储足够的数据来构造DateTime对象(见下文),在我们的子类和管道代码中我们只使用DateTime,因为最初我们只支持英国用户.
该调度程序负责固定和动员工厂设备.因此,预定事件在用户的DST调整后的当地时间运行至关重要.
用户在我们的网站上输入时间表; 目前,它作为星期几,小时和分钟存储在数据库中.当读取数据时,我们为该日,小时和分钟的下一次出现创建一个DateTime对象.我可以自由地改变db结构以另外存储偏移量或时区.
当该日期和时间到达时,调度程序发送命令(并重试一段时间).它然后在下周的同一天和时间再次运行(虽然该服务实际上已经被回收,然后代码将再次运行).
我需要实现的是使用从Hardcodet子类调度的调度程序在该时区调整的本地日期和时间触发调度事件.如果DateTimeOffset确实是DST感知的,那么我需要做的就是存储一个偏移并改变我们的管道代码以使用这个结构,但我得到的印象并不是那么简单.(我们或许可以从工厂的GPS位置获取当前时区,但这是另一天的讨论:)).
LocalDateTime在Noda Time中获得系统时间的惯用方法是什么?我能想到的最直接的方法是
var dt = DateTime.Now
LocalDateTime systemTime = new LocalDateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute);
Run Code Online (Sandbox Code Playgroud)
但鉴于Noda Time的全部目的是用具有更好语义的东西替换DateTime,我认为有一种首选方法,而不DateTime是以上述方式使用.我能用Noda的设施做到最好的是
var zone = NodaTime.TimeZones.BclDateTimeZone.ForSystemDefault();
LocalDateTime systemTime = SystemClock.Instance.Now.InZone(zone).LocalDateTime;
Run Code Online (Sandbox Code Playgroud)
但这似乎很冗长.
我想在我的应用程序中开始使用NodaTime来管理时间,瞬间和一般时间本地化.
有时我会将时间戳保留在SQL Server 2008数据库中.我传统上使用UTC中的datetime2字段.这些时间戳将使用Noda创建.似乎这个日期转换为Noda's Instant可能是不可取的.
我应该用什么类型来坚持下去?
如果我在SQL中使用非整数,那么我的App层和DAL之间可能存在转换问题.但是,如果我坚持整数Noda瞬间,我将在相同的层之间进行逻辑耦合......并且我将无法在SQL中执行简单的日期聚合而不将其带入应用层或CLR.
Noda认为,在UTC中无法可靠地描述时刻,因为UTC中从未发生过某些时间.
我希望将Noda时间用于一个相当简单的应用程序,但是我很难找到任何文档来处理一个非常基本的用例:
我有一个登录用户,并将在设置中存储他们的首选时区.来自客户端的任何日期/时间以已知的文本格式(例如"dd/MM/yyyy HH:mm"),具有已知的时区id(例如"Europe/London").我计划将这些时间转换为UTC/Noda Instants,以防止需要在数据库中存储每个日期的时区信息.
首先,这听起来像是一种明智的做法吗?我可以自由地改变任何东西,所以很乐意设置一个更好/更明智的课程.数据库是MongoDb,使用C#驱动程序.
我试过的是沿着这些方向,但努力克服第一步!
var userSubmittedDateTimeString = "2013/05/09 10:45";
var userFormat = "yyyy/MM/dd HH:mm";
var userTimeZone = "Europe/London";
//noda code here to convert to UTC
//Then back again:
Run Code Online (Sandbox Code Playgroud)
我知道有人会问"你有什么尝试",我所拥有的是各种失败的转换.很高兴被指向"Noda时间入门"页面!
建议表示"今天"的LocalDate实例的建议方法是什么.我期待在LocalDate类中有一个静态的"Now"或"Today"属性,但是没有.我目前的方法是使用DateTime.Now:
var now = DateTime.Now;
LocalDate today = new LocalDate(now.Year, now.Month, now.Day);
Run Code Online (Sandbox Code Playgroud)
有没有更好的办法?
我们的应用程序是一个很大的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 …