Asp.Net、SQL 和时区

2023-12-21

有人问过,但我正在努力掌握如何在网络应用程序中处理时区的概念。我有一个跟踪项目进度的系统。我的 SQL Server 数据库中有一个 ProjectStartDate DATE。 (还有一些字段和表格,但让我们重点关注其中一个)。

服务器位于美国某地。我住在澳大利亚。

Calling SELECT GETDATE()返回“2013-08-11 14:40:50.630” 我的系统时钟显示“2013-08-12 07:40”

在我的数据库中,所有表上都有“CreateDateTime”列。当我将其存储在我的 C# 代码中时,我使用CreateDate = DateTime.UtcNow

我使用它,因为我听说使用 UTC 更好。

但是,当用户看到日历控件并且他们选择项目的开始日期时,我会存储用户选择的内容。没有转换...正如我所说,StartDate 是数据库中的 DATE 类型。

问题是,如果今天启动了一个项目 - 我的前端说当前项目尚未启动,因为服务器仍处于昨天。

我认为日期应该像我存储它们一样存储。但也许我需要以某种方式获取用户时区,并将其应用到 UI 级别?

我看到的问题是:

  • 我不知道用户的时区。添加一些东西以允许他们选择它?
  • 项目的状态可能在存储过程中确定,那么我什么时候可以应用转换?在过程中,它可能会进行检查,如果 StartDate

我大部分时间使用 EntityFramework 和 Linq 来获取数据。我需要一种从 SQL 意义上和 .Net 意义上插入和检索数据的策略。

我添加了代码来让用户根据此选择他们的时区:

public List<TimeZoneDto> GetTimeZones()
{
    var zones = TimeZoneInfo.GetSystemTimeZones();
    var result = zones.Select(tz => new TimeZoneDto
        {
            Id = tz.Id, 
            Description = tz.DisplayName
        }).ToList();

    return result;
}

然后,这就会保留在他们的个人资料中。

正如下面的答案中所建议的,所有日期都存储为 UTC。

我仍然很困惑如何处理往返数据库和客户端的日期。这是我如何存储记录的示例:

public int SaveNonAvailibility(PersonNonAvailibilityDto n)
{
    person_non_availibility o;

    if (n.Id == 0)
    {
        o = new person_non_availibility
            {
                PersonId = n.PersonId,
                Reason = n.Reason,
                StartDate = n.StartDate,
                EndDate = n.EndDate,
                NonAvailibilityTypeId = n.NonAvailibilityTypeId,
                CreateUser = _userId,
                CreateDate = DateTime.UtcNow

            };
        _context.person_non_availibility.Add(o);
    }
    else
    {
        o = (from c in _context.person_non_availibility where c.Id == n.Id select c).FirstOrDefault();
        o.StartDate = n.StartDate;
        o.EndDate = n.EndDate;
        o.Reason = n.Reason;
        o.NonAvailibilityTypeId = n.NonAvailibilityTypeId;
        o.LastUpdateDate = DateTime.UtcNow;
        o.LastUpdateUser = _userId;
        o.Deleted = n.Deleted ? DateTime.UtcNow : (DateTime?)null;
    }
    _context.SaveChanges();
    return o.Id;
}

当一个人无法工作时,这种方法基本上可以节省时间。请注意我存储 LastUpdateDate 的方式。另外,“开始”和“结束”日期。这些日期更多是“商务”日期。

在选择和日期检查方面,这是我遇到的问题。在此示例中,我根据 NOW 获取个人收费率。

public decimal CurrentRate
{
    get
    {
        if (ResourceCosts != null)
        {
            var i = ResourceCosts.FirstOrDefault(t => DateTime.UtcNow <= (t.EndDate.HasValue ? t.EndDate.Value : DateTime.UtcNow) && DateTime.UtcNow >= t.StartDate);
            if (i != null) return i.Cost;
            return 0;
        }
        return 0;
    }
}

所以,我在这里想做的是,根据当前日期,我想查看他的费率(由于他的收费,我们的费率可能是从 1 月 1 日到 1 月 15 日为 100 美元,然后从 1 月 16 日到 1 月 110 美元) 1 月 31 日。所以,我查找今天适用的汇率(如果有)。这不适用于跨时区,也许在这里我需要根据“DateTime.UTCNow”进行一些日期操作?

请注意,我现在根据上面存储用户时区的代码知道了用户时区。我可以在这里用它吗?也许,当用户登录时,从他的个人资料中获取日期信息(Zimezone 信息),然后有一个全局共享函数,根据从 UTC 日期添加或删除小时数来返回用户日期时间......并使用该函数我在哪里做 DateTime.UTCNow ?

希望有人能指导我。


您可能会发现没有一种“正确”的方法可以处理所有这些问题。对于您在问题中描述的几个不同问题,有多种方法。我将尝试澄清几点。

  • 首先,永远不要试图去思考当地时间在服务器上。您的代码和数据不必根据部署位置进行更改。您说您的服务器位于美国,但需要考虑多个时区,并且许多服务器将其时区设置为 UTC,无论其物理位置如何。

    你应该避免GETDATE() or SYSDATETIME()在 SQL Server 中。如果您需要 SQL 中的当前时间戳,请使用GETUTCDATE() http://technet.microsoft.com/en-us/library/ms178635.aspx or SYSUTCDATETIME() http://technet.microsoft.com/en-us/library/bb630387.aspx。如果由于某种原因服务器的时区对您很重要,请使用SYSDATETIMEOFFSET() http://technet.microsoft.com/en-us/library/bb677334.aspx反而。

    同样,避免使用DateTime.Now来自任何服务器端代码的.Net。使用DateTime.UtcNow http://msdn.microsoft.com/en-us/library/system.datetime.utcnow.aspx or DateTimeOffset.UtcNow http://msdn.microsoft.com/en-us/library/system.datetimeoffset.utcnow.aspx对于 UTC 时间戳,或使用DateTimeOffset.Now http://msdn.microsoft.com/en-us/library/system.datetimeoffset.now.aspx如果由于某种原因服务器的时区对您很重要。

    您可以在我的博客文章中阅读更多相关内容:针对 DateTime.Now 的案例 http://codeofmatt.com/2013/04/25/the-case-against-datetime-now/

  • 接下来,我们来谈谈您正在使用的数据类型。这dateSQL Server 中的类型仅存储日期。就是这样。没有时间,没有偏移,也没有时区。一个例子是2013-08-11。当你真正指的是整体时你应该使用它日历日期。 “今天”没有世界范围内统一的语境。相反,每个人根据自己的时区都有自己的含义。此外,并非每个日历日的长度都是 24 小时。一天的长度可能为 23、23.5、24、24.5 或 25 小时,具体取决于特定时区如何应用夏令时,以及您是否正在评估 DST 转换的日期。

    在.Net中 - 没有Date类型,所以一个 SQLdate被转换为DateTime时间设置为午夜(00:00:00),并将种类设置为Unspecified。但不要欺骗自己 - 时间并不是突然变成午夜,我们只是将时间填为零。这可能会导致很多错误和混乱。 (如果你想避免这种情况,你可以尝试野田时间 http://nodatime.org,其中有一个LocalDate为此目的键入。)

  • 您真正需要考虑但没有在问题中定义的是:

    What exact项目开始的那一刻?

    现在你只是说2013-08-11,这并不指特定的时间点。你的意思是那一天的开始特别的时区?或者你的意思是根据user's时区?这些可能不是同一件事。您无法与任何人的“现在”(UTC、本地或其他)进行比较,除非您知道您正在谈论的时间点。

    如果该项目在全球范围内的某个确切时间开始,那么最简单的事情就是存储一个datetime (or datetime2) 包含 UTC 精确时间的类型。所以你可能会说一个项目开始于2013-08-10T14:00:00Z- 时间正好是澳大利亚悉尼 8 月 11 日午夜。在 .Net 中,您可以使用DateTime键入.Kind set to Utc.

    表示这一点的另一种方法是存储datetimeoffset值为2013-08-11T00:00:00+10:00- 这是同一时刻,但使用偏移量为您提供预先转换的值。 (悉尼当天的时间为 UTC+10)。你会使用DateTimeOffset键入以在 .Net 中使用它。

    但是,如果项目根据用户的不同在不同的时间启动,那么这并不是一个准确的时间点。这更像是一个“浮动”的开始。如果来自世界各地的用户被分配到同一个项目,那么某些用户可能会先于其他用户开始。如果这是您的意图,那么您可以使用date如果所有项目都在午夜开始,请键入,或者您可以使用datetime or (datetime2)类型的项目可能在不同时间开始。在您的 .Net 代码中,您将使用DateTime键入.Kind set to Unspecified.

  • 关于获取用户的时区,您能做的最好的事情就是询问他们。尽管存在常见的误解 - 您不能仅从浏览器获取它。您从浏览器中只能看出它们的内容current偏移是。 (阅读“时区!=偏移”部分时区标签维基 https://stackoverflow.com/tags/timezone/info).

    当询问用户他们的时区时,如果您决定使用 Windows 时区,您可以从TimeZoneInfo.GetSystemTimeZones http://msdn.microsoft.com/en-us/library/system.timezoneinfo.getsystemtimezones.aspx方法。这.Id是您存储在数据库中的密钥,并且您显示.DisplayName给用户。稍后您可以使用TimeZoneInfo.FindSystemTimeZoneById http://msdn.microsoft.com/en-us/library/system.timezoneinfo.findsystemtimezonebyid.aspx方法得到一个TimeZoneInfo http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx可用于转换的对象。

    如果您想更精确,可以使用 IANA 时区而不是 Windows 时区。为此,我建议使用基于地图的时区选择器控件,例如this one https://github.com/dosx/timezone-picker。您也可以使用js时区检测 https://bitbucket.org/pellepim/jstimezonedetect猜测您的控件的默认值。在您将使用的服务器上野田时间 http://nodatime.org/执行时区转换。

  • 有一种方法不需要时区转换。基本上,你做一切以世界标准时间 (UTC) 表示。这包括将 UTC 时间传输到浏览器。然后您可以使用 JavaScript 来获取用户的当前时间in UTC并与之比较。

    您可以使用JavaScript的各种功能Date如果您愿意,可以使用类来执行此操作。但您可能会发现使用诸如此类的库更容易moment.js http://momentjs.com/.

    虽然这种方法对于很多事情都是可行的,但安全性并不是其中之一。您的用户可以轻松更改计算机的时钟来解决此问题。

  • 另一种方法是将服务器端与 UTC 进行比较。如果您的数据库中有准确的 UTC 开始时间,那么您可以检查DateTime.UtcNow在您的 .Net 代码中并使用它来决定要做什么。您不需要用户的时区来进行此比较,但如果您想向他们展示这在他们的当地时间中意味着什么,则需要它。

我希望这能消除混乱,不要让事情变得更糟! :) 如果您还有其他疑问,请编辑您的问题或在评论中提问。

UPDATE

针对您更新的问题,我建议您尝试以下操作:

var timeZoneId = "Eastern Standard Time"; // from your user's selection
var timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
var nowInTimeZone = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, timeZone);
var todayInTimeZone = nowInTimeZone.Date;

var i = ResourceCosts.FirstOrDefault(t => t.StartDate <= todayInTimeZone &&
            (!t.EndDate.HasValue || t.EndDate >= todayInTimeZone));

当然,这意味着在您的StartDate and EndDate字段,您不会将它们存储为 UTC,而是存储为与用户相关的“业务日期”。这些仅在您应用时区时与特定时刻对齐,因此相同的 UTC 时间戳可能会出现在不同的日期,具体取决于用户所在的时区。

此外,您使用的是完全包含的范围,这对于这些类型的日历日期范围通常是可以的。但请确保您意识到可能存在重叠。所以如果你有2013-01-01 - 2013-02-01 and 2013-02-01 - 2013-03-01,然后就有那么一天2013-02-01那是在both ranges.

解决这个问题的常见方法是使用半开区间,[start,end)。换句话说,start <= now && end > now。但是,当使用完整的日期和时间而不仅仅是日期时,这种情况更为常见。您可能不需要这样做,但您至少应该针对您的特定场景考虑一下。

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

Asp.Net、SQL 和时区 的相关文章

  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • 重载<<的返回值

    include
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 如何跨多个表强制执行 CHECK 约束

    我有一个在 Microsoft SQL Server 2012 Express 中记录奶牛繁殖信息的数据库 显然 一头牛只有在出生后才能配种 并且在其一生中可能会配种多次 我需要在我的数据库中强制执行这些约束 我目前已经根据下图安排了一个架
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • 如何修改现有表以添加时区

    我有一个包含 500 多个表的大型应用程序 我必须将应用程序转换为时区感知 当前应用程序使用new java util Date GETDATE 与服务器的时区 即没有任何时区支持 我已将这项任务分为几个步骤 以便于开发 我确定的第一个步骤
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • VB6+SQL-Server:如何使用 ADODB.Command 执行带有命名参数的查询?

    我一直在尝试使用 ADODB Command 执行参数化查询 我知道我可以使用 对于参数 但我的查询相当大 我真的不想跟踪参数的确切顺序 我尝试了类似以下的操作 objCmd CommandType adCmdText objCmd Com

随机推荐

  • Python 文本阴影

    我使用 PIL 在图像上添加了一些文本 我想添加一个文本阴影 具有一定的阴影半径和阴影不透明度 在绘制一些文本之前 我已经能够通过绘制阴影来伪造这一点 它效果不太好 然后将其放置在文本上方一点点 draw text x y 2 text f
  • 从 Python 3.7 conda 环境中在 Spyder 下导入 numpy 时出现 ImportError

    我创建了一个 conda 环境 名为python3在我的 Ubuntu 虚拟机上使用 conda create n python3 python 3 7 我在这个环境下安装了几个包 包括numpy 打字时conda list numpy 显
  • Facebook FQL“like”表最多返回 100 行?

    好的 标题主要说明了一切 我想获得我给人们的喜欢的数量 为此我正在执行如下查询 SELECT object id FROM like WHERE user id me 但是 对于大型帐户 即使我添加 它也总是返回 100LIMIT 1000
  • Jest-Expo 在示例中崩溃(React.createElement:类型无效 - 需要一个字符串)

    我很困惑为什么示例测试没有运行 我在这里使用 Expo Web 和 typescript 我的前端使用运行良好expo start web App tsx const App gt return
  • 将knockout.js observablearray 对象传递给MVC 控制器操作?

    我正在使用 MVC 中的淘汰赛 我试图将可观察的对象数组从淘汰赛传递回我的 MVC 控制器操作以保存到数据库 如果我通过 ko toJSON viewModel ArrayName 将数组从淘汰赛传递到我的控制器操作 它将在我的控制器参数中
  • 将 NaN 值插入 MySQL 数据库

    我有一些数据包含 NULL 浮点数和偶尔的 Nan 我正在尝试使用 python 和 MySqldb 将此数据插入到 MySQL 数据库中 这是插入语句 for row in zip currents voltages row id lis
  • 更改单选按钮名称 javascript 在 IE 中不起作用

    我在 jsp 页面中有一些单选按钮 页面加载后 我运行一个 javascript 方法来查找某些单选按钮并更改其名称 以便它们像单选按钮组一样工作 我这样做是因为单选按钮位于 jsf 表内 并且在编码时我无法访问 name 属性 并且我希望
  • Resharper 7:MSTest 不起作用 - “测试未运行”

    自从我升级到 VS2012 和 Resharper 7 以来 我之前工作的 MS 测试不再运行 测试在 ASP NET 环境中运行 我使用以下属性 TestMethod HostType ASP NET AspNetDevelopmentS
  • 在 Excel 中创建序列列

    我有一列包含名称的列 我想添加一列来根据名称计算每行的序列 因此 如果一个名称出现多次 即 4 次 则该名称的第一行将具有序列 1 第二行将具有序列 2 依此类推 Name Sequence Andrew 1 Andrew 2 Andrew
  • Chef 中的引导问题

    我已经使用 Chef 设置了基本的基础设施 这包括本地厨师服务器 基于 ubuntu 工作站和基于 ubuntu 的服务器 用作节点 请注意 整个基础设施都位于我办公室网络的防火墙后面 我已经为服务器访问互联网做了必要的代理设置 所以这就是
  • QT KernelBase!RaiseException 位于 0x759fc41f

    评论多于问题 下面描述了我今晚遇到的一个问题以及我如何 纠正 它 这些事件需要几个小时的时间才能解决 由于该网站是我最喜欢的信息来源之一 因此认为这篇文章可能对其他人有益 欢迎任何有关诊断 QT Creator 运行时异常的建设性意见 该异
  • 当属性 Visibility 更改时为 StackPanel 制作动画

    在 WPF 3 5 带有 SP1 中 我只是当我更改属性可见性时 我想为 StackPanel 制作动画 我不知道这个 StackPanel 的高度 因为它的内容决定了它的高度 因此 当我将 StackPanel 的属性更改为 Visibl
  • 使用 jQuery .load 函数刷新元素而不重复它

    当用户点击提交按钮时 div forum应该刷新 不刷新页面 然而 由于某种原因 它反而创建了一个新的 div forum在原始 div 中 如下所示 虽然我知道我可以通过在 div 周围添加一个容器来防止这种情况 forum 我想知道是否
  • 使用 NAudio 将流数据保存到 WAV 文件

    我想将传入的流数据保存到硬盘驱动器上的 WAV 文件中 如何更改下面的代码才能将流录制到有效的 WAV 文件中 来自演示here http naudio codeplex com SourceControl changeset view a
  • 收到 icmp 请求,但没有回复 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 这个问题似乎不是关于主要由程序员使用的特定编程问题 软件算法或软件工具 help on topic 如果您认为该问题与主题相关另一个 St
  • 如何处理ggplot2中的“data of class uneval”错误?

    在尝试将新行覆盖到现有行时ggplot 我收到以下错误 Error ggplot2 doesn t know how to deal with data of class uneval 我的代码的第一部分工作正常 下图是来自美国中西部电力市
  • AVPlayer 播放 iOS 7 后台通知中的音频

    I have audio fetch and remote notification set in UIBackgroundModes我通过以下方式成功接收了我的应用程序在后台 未激活 的远程通知 void application UIAp
  • 在 Step Function 内循环

    我试图在循环中调用步骤函数中的几个步骤 但我无法弄清楚我需要如何执行此操作 这是我现在所拥有的 我需要添加另一个 lambda 函数 GetReviews 然后它将循环调用 CreateReview SendNotification 我该怎
  • 使用 UniformGrid 的列表框 - 项目未居中

    我有一个使用 UniformGrid 作为 ItemsPanelTemplate 的列表框 这是一个照片列表 我希望照片在网格的每个单元格的中心水平居中 但似乎无论我做什么 图像都会与每个单元格的左侧对齐 这是我当前的 XAML
  • Asp.Net、SQL 和时区

    有人问过 但我正在努力掌握如何在网络应用程序中处理时区的概念 我有一个跟踪项目进度的系统 我的 SQL Server 数据库中有一个 ProjectStartDate DATE 还有一些字段和表格 但让我们重点关注其中一个 服务器位于美国某