jjzjj

c# - 如果时区规则更改,以前保存的日期时间的 UTC 到本地时间转换

coder 2024-06-03 原文

我正在数据库中存储一个产品。所有日期(sql server datetime)都是 UTC,连同我存储该产品时区 ID 的日期。用户在列表中输入产品“从”和“直到”可用的日期。 所以我做了类似的事情:

// Convert user's datetime to UTC
var userEnteredDateTime = DateTime.Parse("11/11/2014 9:00:00");
// TimeZoneInfo id will be stored along with the UTC datetime
var tz = TimeZoneInfo.FindSystemTimeZoneById("FLE Standard Time");
// following produces: 9/11/2014 7:00:00 AM (winter time - 1h back)
var utcDateTime = TimeZoneInfo.ConvertTimeToUtc(userEnteredDateTime, tz);

并保存记录。假设用户在 8 月 1 日执行此操作,而他与 UTC 的时区偏移量仍为 +03:00,但是为 future 列表保存的日期具有正确的 +02:00 值,因为转换考虑了“冬季”那个时期的时间。

问题是,如果我在 2014 年 11 月 11 日尝试将该产品的“开始”和“结束”日期转换为产品的本地时区,我将获得什么日期时间值,例如,由于一些新的规则转换到冬令时被放弃,因此时区仍然是 +03:00 而不是 +02:00?

// Convert back
var userLocalTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, tz);

我会得到上午 10 点还是正确的上午 9 点,因为 OS/.NET 补丁会处理这个问题?

谢谢!

P.S.:TimeZoneInfo 有 ToSerializedString() 方法,如果我宁愿存储这个值而不是时区 ID,这是否可以保证通过 UTC 日期时间 + 序列化时区信息我将始终能够转换为用户的原始日期时间输入?

最佳答案

在您描述的场景中,您将到达上午 10:00。时区转换函数不会知道最初输入的值是上午 9:00,因为您只保存了 UTC 时间上午 7:00。

这说明了“始终存储 UTC”建议存在缺陷的情况之一。当您处理 future 事件时,它并不总是有效。问题是政府经常改变他们对时区的看法。有时他们会发出合理的通知(例如美国,2007 年),但有时他们不会(例如埃及,2014 年)。

当您最初将本地时间转换为 UTC 时,您有意决定相信时区规则不会改变。换句话说,您决定仅根据您当时所知的时区规则将事件分配给通用时间轴。

避免这种情况的方法很简单: future 的事件应该在本地时间安排。现在,我的意思不是“本地到你的计算机”,而是“本地到用户”,所以你需要知道用户的时区,你还应该在某处存储时区的 ID。

如果事件落入 daylight saving time 的前向或后向过渡,您还需要决定要做什么。 .这对于重复模式尤其重要。

但最终,您需要确定何时举办事件。或者在您的情况下,您需要决定事件是否已经过去。您可以通过几种不同的方式完成此操作:

选项 1

  • 您可以计算每个本地时间对应的 UTC 值,并将其保存在单独的字段中。

  • 在某个周期(每天、每周等),您可以根据本地值和您当前对时区规则的理解重新计算即将到来的 UTC 值。或者,如果您手动应用时区更新,则可以选择重新计算当时的所有内容。

选项 2

  • 您可以将值存储为 DateTimeOffset 类型而不是 DateTime。它将包含原始本地时间,以及您根据输入时所知道的时区规则计算的偏移量。

  • DateTimeOffset 值可以很容易地被强制转换回 UTC,因此它们往往能很好地实现这一点。您可以在 DateTime vs DateTimeOffset 中阅读更多内容.

  • 就像在选项 1 中一样,您将定期或在时区数据更新后重新访问这些值,并调整偏移量以与新的时区数据保持一致。

  • 这是我通常推荐的,特别是如果您使用的数据库支持 DateTimeOffset 类型,例如 SQL Server 或 RavenDB。

选项 3

  • 您可以将值存储为本地 DateTime

  • 查询时,您将计算目标时区的当前时间并与该值进行比较。

    DateTime now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, targetTZ);
    bool passed = now >= eventTime;
    
  • 此选项的缺点是,如果您在许多不同时区都有事件,则可能需要进行大量查询。

  • 您可能还会遇到接近回退 DST 转换的值的问题,因此在使用此方法时要小心。

我反对序列化时区本身的想法。如果时区改变了,那么它就改变了。假装它没有不是一个好的解决方法。

关于c# - 如果时区规则更改,以前保存的日期时间的 UTC 到本地时间转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25253445/

有关c# - 如果时区规则更改,以前保存的日期时间的 UTC 到本地时间转换的更多相关文章

  1. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  2. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  3. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

  4. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  5. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  6. ruby - 检查日期是否在过去 7 天内 - 2

    我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/

  7. ruby-on-rails - 将 Ruby 中的日期/时间格式化为 YYYY-MM-DD HH :MM:SS - 2

    这个问题在这里已经有了答案:Railsformattingdate(4个答案)关闭4年前。我想格式化Time.Now函数以显示YYYY-MM-DDHH:MM:SS而不是:“2018-03-0909:47:19+0000”该函数需要放在时间中.现在功能。require‘roo’require‘roo-xls’require‘byebug’file_name=ARGV.first||“Template.xlsx”excel_file=Roo::Spreadsheet.open(“./#{file_name}“,extension::xlsx)xml=Nokogiri::XML::Build

  8. ruby-on-rails - 如果我将 ruby​​ 版本 2.5.1 与 rails 版本 2.3.18 一起使用会怎样? - 2

    如果我使用ruby​​版本2.5.1和Rails版本2.3.18会怎样?我有基于rails2.3.18和ruby​​1.9.2p320构建的rails应用程序,我只想升级ruby的版本,而不是rails,这可能吗?我必须面对哪些挑战? 最佳答案 GitHub维护apublicfork它有针对旧Rails版本的分支,有各种变化,它们一直在运行。有一段时间,他们在较新的Ruby版本上运行较旧的Rails版本,而不是最初支持的版本,因此您可能会发现一些关于需要向后移植的有用提示。不过,他们现在已经有几年没有使用2.3了,所以充其量只能让更

  9. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  10. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

随机推荐