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 和时区 的相关文章

  • Qt-Qlist 检查包含自定义类

    有没有办法覆盖加载自定义类的 Qt QList 的比较机制 即在 java 中你只需要重写一个比较方法 我有一个带有我的自定义类模型的 QList QList
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • 从父类调用子类方法

    a doStuff 方法是否可以在不编辑 A 类的情况下打印 B did stuff 如果是这样 我该怎么做 class Program static void Main string args A a new A B b new B a
  • Newtonsoft JSON PreserveReferences处理自定义等于用法

    我目前在使用 Newtonsoft Json 时遇到一些问题 我想要的很简单 将要序列化的对象与所有属性和子属性进行比较以确保相等 我现在尝试创建自己的 EqualityComparer 但它仅与父对象的属性进行比较 另外 我尝试编写自己的
  • 将布尔参数传递给 SQL Server 存储过程

    我早些时候问过这个问题 我以为我找到了问题所在 但我没有 我在将布尔参数传递给存储过程时遇到问题 这是我的 C 代码 public bool upload false protected void showDate object sende
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 为什么#pragma optimize("", off)

    我正在审查一个 C MFC 项目 在某些文件的开头有这样一行 pragma optimize off 我知道这会关闭所有以下功能的优化 但这样做的动机通常是什么 我专门使用它来在一组特定代码中获得更好的调试信息 并在优化的情况下编译应用程序
  • 指针问题(仅在发布版本中)

    不确定如何描述这一点 但我在这里 由于某种原因 当尝试创建我的游戏的发布版本进行测试时 它的敌人创建方面不起作用 Enemies e level1 3 e level1 0 Enemies sdlLib 500 2 3 128 250 32
  • 将目录压缩为单个文件的方法有哪些

    不知道怎么问 所以我会解释一下情况 我需要存储一些压缩文件 最初的想法是创建一个文件夹并存储所需数量的压缩文件 并创建一个文件来保存有关每个压缩文件的数据 但是 我不被允许创建许多文件 只能有一个 我决定创建一个压缩文件 其中包含有关进一步
  • 如果使用 SingleOrDefault() 并在数字列表中搜索不在列表中的数字,如何返回 null?

    使用查询正数列表时SingleOrDefault 当在列表中找不到数字时 如何返回 null 或像 1 这样的自定义值 而不是类型的默认值 在本例中为 0 你可以使用 var first theIntegers Cast
  • 使用 asp.net 发送 20,000 多封电子邮件

    我正在编写一个应用程序 需要向从我们的数据库中选择的学生发送大量电子邮件 每封电子邮件都将进行个性化 包括他们的姓名 学习课程等 因此需要一次发送一个 我可以在 SmtpClient 上循环执行此操作 但我担心我尝试发送的数字最终会遇到超时
  • 使用 System.Text.Json 即时格式化 JSON 流

    我有一个未缩进的 Json 字符串 例如 hash 123 id 456 我想缩进字符串并将其序列化为 JSON 文件 天真地 我可以使用缩进字符串Newtonsoft如下 using Newtonsoft Json Linq JToken
  • vector 超出范围后不清除内存

    我遇到了以下问题 我不确定我是否错了或者它是一个非常奇怪的错误 我填充了一个巨大的字符串数组 并希望在某个点将其清除 这是一个最小的例子 include
  • C# 中的递归自定义配置

    我正在尝试创建一个遵循以下递归结构的自定义配置部分
  • 需要哪个版本的 Visual C++ 运行时库?

    microsoft 的最新 vcredist 2010 版 是否包含以前的版本 2008 SP1 和 2005 SP1 还是我需要安装全部 3 个版本 谢谢 你需要所有这些
  • const、span 和迭代器的问题

    我尝试编写一个按索引迭代容器的迭代器 AIt and a const It两者都允许更改容器的内容 AConst it and a const Const it两者都禁止更改容器的内容 之后 我尝试写一个span
  • ASP.NET MVC 6 (ASP.NET 5) 中的 Application_PreSendRequestHeaders 和 Application_BeginRequest

    如何在 ASP NET 5 MVC6 中使用这些方法 在 MVC5 中 我在 Global asax 中使用了它 现在呢 也许是入门班 protected void Application PreSendRequestHeaders obj
  • C 中的异或运算符

    在进行按位操作时 我在确定何时使用 XOR 运算符时遇到一些困难 按位与和或非常简单 当您想要屏蔽位时 请使用按位 AND 常见用例是 IP 寻址和子网掩码 当您想要打开位时 请使用包含或 然而 XOR 总是让我明白 我觉得如果在面试中被问
  • 使用 libcurl 检查 SFTP 站点上是否存在文件

    我使用 C 和 libcurl 进行 SFTP FTPS 传输 在上传文件之前 我需要检查文件是否存在而不实际下载它 如果该文件不存在 我会遇到以下问题 set up curlhandle for the public private ke
  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我

随机推荐

  • 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 还有一些字段和表格 但让我们重点关注其中一个 服务器位于美国某