如何优雅地处理时区

2024-03-10

我有一个网站托管在与使用该应用程序的用户不同的时区。除此之外,用户还可以拥有特定的时区。我想知道其他 SO 用户和应用程序如何处理这个问题?最明显的部分是在数据库内部,日期/时间以 UTC 存储。在服务器上时,所有日期/时间都应以 UTC 格式处理。然而,我看到了我正在努力克服的三个问题:

  1. 获取 UTC 中的当前时间(使用以下命令可以轻松解决)DateTime.UtcNow).

  2. 从数据库中提取日期/时间并将其显示给用户。有潜在的lots在不同视图上打印日期的调用。我正在考虑视图和控制器之间的某个层可以解决这个问题。或者有一个自定义扩展方法DateTime(见下文)。主要的缺点是every在视图中使用日期时间的位置,必须调用扩展方法!

    这也会增加使用类似的东西的难度JsonResult。你不能再轻易打电话Json(myEnumerable),它必须是Json(myEnumerable.Select(transformAllDates))。也许 AutoMapper 在这种情况下可以提供帮助?

  3. 获取用户的输入(本地至 UTC)。例如,发布带有日期的表单需要先将日期转换为 UTC。第一个想到的就是创建自定义ModelBinder.

这是我想在视图中使用的扩展:

public static class DateTimeExtensions
{
    public static DateTime UtcToLocal(this DateTime source, 
        TimeZoneInfo localTimeZone)
    {
        return TimeZoneInfo.ConvertTimeFromUtc(source, localTimeZone);
    }

    public static DateTime LocalToUtc(this DateTime source, 
        TimeZoneInfo localTimeZone)
    {
        source = DateTime.SpecifyKind(source, DateTimeKind.Unspecified);
        return TimeZoneInfo.ConvertTimeToUtc(source, localTimeZone);
    }
}

我认为考虑到许多应用程序现在都是基于云的,其中服务器的本地时间可能与预期的时区有很大不同,处理时区将是一件很常见的事情。

这个问题之前已经被优雅地解决了吗?我有什么遗漏的吗?非常感谢想法和想法。

EDIT:为了消除一些混乱,我想添加一些更多细节。现在的问题不是how将UTC时间存储在数据库中,更多的是从UTC->本地和本地->UTC的过程。正如 @Max Zerbini 指出的那样,将 UTC->Local 代码放入视图中显然是明智的,但使用的是DateTimeExtensions真的是答案吗?当从用户那里获取输入时,接受日期作为用户的本地时间(因为这就是 JS 将使用的)然后使用ModelBinder转换为UTC?用户的时区存储在数据库中并且可以轻松检索。


并不是说这是一个建议,它更多的是共享一个范式,但最重要的是攻击性的我见过的在 Web 应用程序中处理时区信息的方式(这并非 ASP.NET MVC 独有的)如下:

  • 服务器上的所有日期时间均为 UTC。 这意味着使用,就像你说的,DateTime.UtcNow.

  • 尝试尽可能少地信任客户端向服务器传递日期。例如,如果您需要“现在”,请不要在客户端上创建日期然后将其传递到服务器。在 GET 中创建一个日期并将其传递给 ViewModel 或在 POST 中创建日期DateTime.UtcNow.

到目前为止,票价相当标准,但这就是事情变得“有趣”的地方。

  • 如果您必须接受来自客户端的日期,请使用 javascript 确保您发布到服务器的数据采用 UTC。客户端知道它所在的时区,因此它可以以合理的精度将时间转换为 UTC。

  • 渲染视图时,他们使用 HTML5<time>元素,它们永远不会直接在 ViewModel 中渲染日期时间。它的实施如下HtmlHelper扩展名,类似Html.Time(Model.when)。它会呈现<time datetime='[utctime]' data-date-format='[datetimeformat]'></time>.

    然后他们会使用 JavaScript 将 UTC 时间转换为客户端本地时间。该脚本会找到所有<time>元素并使用date-formatdata 属性来格式化日期并填充元素的内容。

这样,他们就不必跟踪、存储或管理客户的时区。服务器不关心客户端所在的时区,也不必进行任何时区转换。它只是输出 UTC 并让客户端将其转换为合理的值。这对于浏览器来说很容易,因为它知道它所在的时区。如果客户端更改了他/她的时区,Web 应用程序将自动更新自身。他们存储的唯一内容是用户区域设置的日期时间格式字符串。

我并不是说这是最好的方法,但这是一种我以前从未见过的不同方法。也许你会从中收集到一些有趣的想法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何优雅地处理时区 的相关文章

  • 通过单个 GPIO 引脚转储闪存

    我正在使用 Infineon 的 XMC4500 Relax Kit 并尝试通过单个 GPIO 引脚提取固件 我非常天真的想法是通过 GPIO 引脚一次转储一位 然后用逻辑分析仪以某种方式 嗅探 数据 伪代码 while word by w
  • 关闭 XDOCUMENT 的实例

    我收到这个错误 该进程无法访问文件 C test Person xml 因为它是 被另一个进程使用 IOException 未处理 保存文件内容后如何关闭 xml 文件的实例 using System using System Collec
  • C# 中附加/分离事件处理程序的不同方式有什么区别

    我的问题有两个部分 首先 我们可以通过以下两种方式附加事件处理程序 myObject MyEvent new EventHandler MyHandler myObject MyEvent MyHandler 据我了解 这两者是等价的 在第
  • C 中的模仿函数重写

    具体来说 函数重写能够调用基本重写方法 这有两部分 一个是预编译的库代码 1 另一个是库的用户代码 2 我在这里实现了一个尽可能最小的经典 Person 和 Employee 示例 非常感谢了解 OOP 概念的铁杆 C 开发人员的回应 我正
  • 将成员函数作为参数传递/c++

    我想用 C 实现一个类b可以通过封装该迭代器类型的成员集进行某种迭代 喜欢 b object for each x do function f so 函数 f会得到每个人的x成员并做任何事情 比方说 void function f x me
  • .net Framework (.net 4.0) 中定义 Base 3 数字的类

    我正在寻找一些可以用来定义 3 基数 三进制数 的类 有什么我可以在 net 框架中使用的东西或者我需要写一些东西吗 谢谢你的帮助 您可以使用解析Convert ToInt32 s base http msdn microsoft com
  • 如何使用泛型类型的 DataContractSerializer 编写自定义序列化器?

    我想编写一个自定义序列化器 用于将会话状态存储到Azure 缓存 预览版 这意味着这个自定义序列化器必须实现IDataCacheObjectSerializer 如果我错了 请告诉我 我需要编写这个自定义序列化程序的原因是我需要序列化一些包
  • 在“using”语句中使用各种类型 (C#)

    自从C usingstatements只是try finally dispose 的语法糖 为什么它接受多个对象仅当它们属于同一类型时 我不明白 因为它们需要的只是 IDisposable 如果它们都实现 IDisposable 应该没问题
  • 线程安全的 C++ 堆栈

    我是 C 新手 正在编写一个多线程应用程序 不同的编写者将对象推入堆栈 读者将它们从堆栈中拉出 或至少将指针推入对象 C 中是否有任何内置结构可以在不添加锁定代码等的情况下处理此问题 如果没有 那么 Boost 库呢 EDIT 你好 感谢您
  • 为什么重载方法在 ref 仅符合 CLS 方面有所不同

    公共语言规范对方法重载非常严格 仅允许根据其参数的数量和类型来重载方法 如果是泛型方法 则根据其泛型参数的数量进行重载 根据 csc 为什么此代码符合 CLS 无 CS3006 警告 using System assembly CLSCom
  • 更改其他页面的主窗口内容

    在 WPF 应用程序的主窗口中 我有一个 Badged 元素 来自材料设计 这是我的代码
  • 有没有办法设置 log4net 内存附加程序可以包含的最大错误消息数?

    我想向根记录器添加一个内存附加程序 以便我可以连接到应用程序并获取最后 10 个事件 我只想保留最后 10 个 我担心这个附加程序会消耗太多内存 该应用程序设计为 24 7 运行 或者还有别的办法吗 您需要创建一个自定义附加程序来存储有限数
  • 如何将字符串转换为 Indian Money 格式?

    我正在尝试将字符串转换为印度货币格式 例如如果输入为 1234567 则输出应为 12 34 567 我编写了以下代码 但它没有给出预期的输出 CultureInfo hindi new CultureInfo hi IN string t
  • 是什么原因导致 Linq 错误:此方法无法转换为存储表达式?

    我有一堆具有相同 select 语句的 Linq to Entity 方法 所以我想我会很聪明 并将其分离到它自己的方法中以减少冗余 但是当我尝试运行代码时 我得到了以下内容错误 该方法不能转化为 商店表达式 这是我创建的方法 public
  • 我应该如何在 VB.NET 中进行转换?

    所有这些都相等吗 在什么情况下我应该选择其中一个而不是其他 var ToString CStr 变量 CType 变量 字符串 DirectCast 变量 字符串 编辑 来自的建议不是我自己 https stackoverflow com
  • asp.net c# 防止在从服务器端代码更改索引时触发 selectedindexchanged 事件

    我在同一个 aspx 页面上有两个下拉列表控件
  • 无法通过 LINQ to Entities 使用某些功能?

    我正在尝试使用 LINQ 查询在项目上实现搜索功能 由于数据有时包含带有重音符号和其他符号的字符 因此我创建了一种方法来删除这些字符以进行搜索 这是我的代码 var addresses from a in db Addresses join
  • C++ 标准中短语“构造函数没有名称”的含义

    在尝试理解 C 标准中的 构造函数没有名称 这句话时 我似乎在 clang 中发现了一个错误 有人可以证实这一点吗 VS2015 and gcc rejects this code and I think they it are is co
  • c# 替代方案中 cfusion_encrypt 中填充的密钥是什么?

    我找到了从这里复制 C 中的 cfusion encrypt 函数的答案 ColdFusion cfusion encrypt 和 cfusion decrypt C 替代方案 https stackoverflow com questio
  • 创建带有部分的选项卡式侧边栏 WPF

    我正在尝试创建一个带有部分的选项卡式侧边栏 如 WPF 中的以下内容 我考虑过几种方法 但是有没有更简单 更优雅的方法呢 方法一 列表框 Using a ListBox并将 SelectedItem 绑定到右侧内容控件所绑定的值 为了区分标

随机推荐