I am facing an issue in timezone. Right now I am saving time zone from client side and stored all DateTime in UTC. It's working properly but when I am trying to convert DateTime for UTC behind time zones like CST, EST, EDT it showing wrong data.
我正面临着一个时区问题。现在我从客户端保存时区,并将所有DateTime存储在UTC中。它工作正常,但是当我试图在CST、EST和EDT等时区之后转换UTC的DateTime时,它会显示错误的数据。
Issue - Let's assume if I did any task at 10 PM EDT and it would be saved in DB as 2 AM(as per UTC) but when I am trying to fetch data for a day and passing current UTC date.
让我们假设如果我在10 PM EDT上执行任何任务,它将在DB中被保存为2 AM(与UTC一样),但是当我试图获取一天的数据并通过当前UTC日期时。
My question is If am trying to fetch data for a day like 11 midnight( from EST) to the current time, but my conversion from UTC to EST is wrong due to UTC 12midnight is yesterday's 8 PM(as EDT 4hr behind from UTC). (From Date[UTC convert to EDT] - 06/07/2017 08:00pm) and To Date - 06/07/2017 11:00 pm) Due to this conversion I am getting data from 8 pm to 11 pm only <- I am expecting from date is 06/07/2017 04:00 AM as per UTC.
我的问题是,我是否试图获取一天的数据,比如从东部时间午夜11点(从东部时间)到现在的时间,但是我从东部时间12点转换到东部时间是错误的,因为东部时间是昨天晚上8点(东部时间4小时)。(从日期[UTC转换为EDT] - 06/07/2017 08:00pm)到日期- 06/07/2017 11:00 pm)由于此转换,我只收到从晚上8点到晚上11点的数据<-我预计从日期开始的日期是:06/07/2017 04:00 am。
Code - Below is the code for conversion. In from date I have taken utcnow.date only and from a date
代码-下面是转换的代码。从现在开始,我一直在使用utc。只有日期和日期
Javascript code -
Javascript代码,
function setTimezoneCOOKIE() {
try {
var timezone_COOKIE = "timezoneoffset";
var timeZOneName= "timezonename"
var tz = jstz.determine();
var aa = tz.name();
// if the timezone COOKIE not exists create one.
if (!$.COOKIE(timezone_COOKIE)) {
// create a new COOKIE
$.COOKIE(timezone_COOKIE, new Date().getTimezoneOffset());
$.COOKIE(timeZoneName, aa);
}
else {
var storedOffset = parseInt($.COOKIE(timezone_COOKIE));
var currentOffset = new Date().getTimezoneOffset();
if (storedOffset !== currentOffset) {
$.COOKIE(timezone_COOKIE, new Date().getTimezoneOffset());
$.COOKIE(timeZoneName, aa);
location.reload();
}
else {
$.COOKIE(timeZoneName, aa);
}
}
}
c# code -
c#代码,
fromDate =Convert.ToDateTime(fromDate).ToClientTimeZoneinDateTime().ToString();
toDate = Convert.ToDateTime(toDate).ToClientTimeZoneinDateTime().ToString();
ObjectParameter totalRecords = new ObjectParameter("TotalRecords", typeof(int));
var DetailsList = objDetailsList.GetDetails(loginUserId,locationId, userId, taskType, pageIndex, numberOfRows, sortColumnName, sortOrderBy, textSearch, totalRecords, fromDate, toDate);
if (DetailsList.Count() > 0)
{
string output = BuildJQGridResults(DetailsList, numberOfRows, pageIndex, Convert.ToInt32(totalRecords.Value));
response.Write(output);
}
else
{
JQGridResults result = new JQGridResults();
List rows = new List();
result.rows = rows.ToArray();
result.page = 0;
result.total = 0;
result.records = 0;
response.Write(new JavascriptSerializer().Serialize(result));
}
Below is the method of converting UTC time to client timezone
下面是将UTC时间转换为客户端时区的方法
public static DateTime ToClientTimeZoneinDateTime(this DateTime dt)
{
try {
if (System.Web.HttpContext.Current.Request.COOKIEs["timezoneoffset"] != null || System.Web.HttpContext.Current.Request.COOKIEs["timezonename"] != null)
{
var timezOnename= System.Web.HttpContext.Current.Request.COOKIEs["timezonename"].Value;
timezOnename= timezonename.Replace("%2F", "/");
var timezoneLocal1 = FindTimezoneName(timezonename);
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(timezoneLocal1);
bool isCurrentlyDaylightSavings = tzi.IsDaylightSavingTime(dt);
if (isCurrentlyDaylightSavings == true)
dt.AddHours(1);
var timeOffSet = System.Web.HttpContext.Current.Request.COOKIEs["timezoneoffset"].Value;
var offset = int.Parse(timeOffSet.ToString());
dt = dt.AddMinutes(-1 * offset);
return dt;
}
return dt.ToLocalTime();
}
catch (Exception)
{
return DateTime.UtcNow;
}
}
No doubt as Timezone handled properly but facing an issue for behind timezone from UTC if end user trying to fetch data after 8 PM EDT. I have attached screenshot as well.
毫无疑问,时区处理得很好,但是如果最终用户试图在东部时间晚上8点以后获取数据,那么就会面临来自UTC的时区后面的问题。我也附上了截图。
Below img of before conversion -
低于img之前的转换-
Above img of after conversion -
以上img的后转换-
How do I need to handle this situation?
我该如何处理这种情况?
1
The main problem is that you're converting the wrong direction. You are converting from UTC to the user's time zone, but your input is in the user's time zone, so you need to convert the other direction - from the user's time zone to UTC. Then your query will show better results.
主要的问题是你转换了错误的方向。您正在从UTC转换到用户的时区,但是您的输入位于用户的时区,所以您需要转换到另一个方向——从用户的时区转换到UTC。然后您的查询将显示更好的结果。
A few other things:
其他一些事情:
Don't convert time zones by trying to add/subtract minutes or hours manually. Use the conversion functions offered on TimeZoneInfo
, such as ConvertTimeFromUtc
, ConvertTimeToUtc
, etc. There's no need to test for DST.
不要通过手动添加/减去分钟或小时来转换时区。使用TimeZoneInfo提供的转换函数,如ConvertTimeFromUtc、ConvertTimeToUtc等。不需要对DST进行测试。
The try/catch shouldn't be in your code at all. Throw an exception if you can't perform the operation. Don't mask important errors by swallowing exceptions.
try/catch不应该出现在代码中。如果无法执行操作,则抛出异常。不要通过吞咽异常来掩盖重要的错误。
dt.ToLocalTime()
shouldn't be in your code either. Never rely on the server's local time zone.
tolocaltime()也不应该出现在您的代码中。不要依赖服务器的本地时区。
The offset returned by new Date().getTimezoneOffset()
is the user's current offset. You cannot assume that it's the correct offset for the dates chosen. You don't that anyway, as you're already getting the time zone name. (You don't need the timezoneoffset
COOKIE at all.)
new Date(). gettimezoneoffset()返回的偏移量是用户当前的偏移量。您不能假定它是所选日期的正确偏移量。不管怎样,你已经得到了时区的名称。(你根本不需要timezoneoffset COOKIE。)
The time zone name returned by jstz.determine()
on the client-side is going to be an IANA tzdb identifier, such as America/Los_Angeles
. These aren't going to work on the server-side with TimeZoneInfo.FindSystemTimeZoneById
(unless you are running .NET Core on Linux or Mac). Conversion to a Windows time zone is required. I see you have a FindTimeZoneName
function, which I assume is performing the conversion. You didn't show the details in your code, but I highly recommend you use my TimeZoneConverter library to implement that, as it's maintained with changes to time zones.
客户端的jstz. decide()返回的时区名称将是一个IANA tzdb标识符,例如America/Los_Angeles。这些不会在服务器端使用TimeZoneInfo。FindSystemTimeZoneById(除非您在Linux或Mac上运行。net内核)。需要转换到Windows时区。我看到您有一个FindTimeZoneName函数,我假设它正在执行转换。您没有在代码中显示细节,但是我强烈建议您使用我的TimeZoneConverter库来实现它,因为它是通过对时区的更改来维护的。
Reading COOKIEs and time zone conversion are separate concerns. Don't bundle them together.
读取COOKIE和时区转换是不同的关注点。不要捆绑在一起。
Ultimately, you should have something like this:
最终,你应该拥有这样的东西:
public static DateTime FromTimeZoneToUtc(this DateTime dt, string timeZone)
{
var windowsId = TimeZoneConverter.TZConvert.IanaToWindows(timeZone);
var tzi = TimeZoneInfo.FindSystemTimeZoneById(windowsId);
return TimeZoneInfo.ConvertTimeFromUtc(dt, tzi);
}
Or, even better, if you use Noda Time, then you don't need to convert time zones at all.
或者更好的是,如果你使用野田时间,那么你根本不需要转换时区。
public static DateTime FromTimeZoneToUtc(this DateTime dt, string timeZone)
{
var tz = DateTimeZoneProviders.Tzdb[timeZone];
var local = LocalDateTime.FromDateTime(dt);
return local.InZoneLeniently(tz).ToDateTimeUtc();
}