有人问过,但我正在努力掌握如何在网络应用程序中处理时区的概念。我有一个跟踪项目进度的系统。我的 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 ?
希望有人能指导我。