如果用户选择提前x个小时的时区,那么我希望保存的日期会从屏幕上选择的日期发生变化。
例如。他们从日历弹出窗口中选择 UTC + 2 Athens 和25/02/2016
的日期,然后记录的日期将为24/02/2016
。
我已将原因缩小到选定的日期时间记录为例如25/02/2016 00:00:00
并且偏差为2小时这一事实,这将它带到24/02/2016 22:00:00
从未使用过时区或UTC日期/时间,这非常令人困惑。
以下是代码
oObject.RefDate = itTimeAndDate.ParseDateAndTimeNoUTCMap(Request, TextBox_RefDate.Text);
if (!string.IsNullOrEmpty(oObject.TimeZoneDetails))
{
TimeZoneInfo oTimeZone = TimeZoneInfo.FindSystemTimeZoneById(oObject.TimeZoneDetails);
oObject.RefDate = itTimeAndDate.GetUTCUsingTimeZone(oTimeZone, oObject.RefDate);
}
从RefDate
*(以下代码)* 返回后, 25/02/2016 00:00:00
等同于ParseDateAndTimeNoUTCMap
之类的内容
static public itDateTime ParseDateAndTimeNoUTCMap(HttpRequest oTheRequest, string sValue)
{
DateTime? oResult = ParseDateAndTimeNoUTCMapNull(oTheRequest, sValue);
if (oResult != null)
return new itDateTime(oResult.Value);
return null;
}
/// <summary>
/// Translate a string that has been entered by a user to a UTC date / time - mapping using the
/// current time zone
/// </summary>
/// <param name="oTheRequest">Request context</param>
/// <param name="sValue">Date / time string entered by a user</param>
/// <returns>UTC date / time object</returns>
static public DateTime? ParseDateAndTimeNoUTCMapNull(HttpRequest oTheRequest, string sValue)
{
try
{
if (string.IsNullOrEmpty(sValue))
return null;
sValue = sValue.Trim();
if (string.IsNullOrEmpty(sValue))
return null;
if (oTheRequest != null)
{
const DateTimeStyles iStyles = DateTimeStyles.AllowInnerWhite | DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite;
// Create array of CultureInfo objects
CultureInfo[] aCultures = new CultureInfo[oTheRequest.UserLanguages.Length + 1];
for (int iCount = oTheRequest.UserLanguages.GetLowerBound(0); iCount <= oTheRequest.UserLanguages.GetUpperBound(0);
iCount++)
{
string sLocale = oTheRequest.UserLanguages[iCount];
if (!string.IsNullOrEmpty(sLocale))
{
// Remove quality specifier, if present.
if (sLocale.Contains(";"))
sLocale = sLocale.Substring(0, sLocale.IndexOf(';'));
try
{
aCultures[iCount] = new CultureInfo(sLocale, false);
}
catch (Exception) { }
}
else
{
aCultures[iCount] = CultureInfo.CurrentCulture;
}
}
aCultures[oTheRequest.UserLanguages.Length] = CultureInfo.InvariantCulture;
// Parse input using each culture.
foreach (CultureInfo culture in aCultures)
{
DateTime oInputDate;
if (DateTime.TryParse(sValue, culture.DateTimeFormat, iStyles, out oInputDate))
return oInputDate;
}
}
return DateTime.Parse(sValue);
}
catch (Exception)
{
}
return null;
}
从上面返回后,执行以下行 -
TimeZoneInfo oTimeZone = TimeZoneInfo.FindSystemTimeZoneById(oObject.TimeZoneDetails);
oObject.RefDate = itTimeAndDate.GetUTCUsingTimeZone(oTimeZone, oObject.RefDate);
在GetUTCUsingTimeZone
范围内,问题似乎发生在我身上。
static public itDateTime GetUTCUsingTimeZone(TimeZoneInfo oTimeZone, itDateTime oDateTime)
{
if (oDateTime == null || oTimeZone == null)
return oDateTime;
DateTime oLocal = DateTime.SpecifyKind(oDateTime.Value, DateTimeKind.Unspecified);
DateTime oResult = TimeZoneInfo.ConvertTimeToUtc(oLocal, oTimeZone);
return new itDateTime(oResult);
}
我已检查TimezoneInfo
的偏移值,oResult
始终等于oLocal param
- 偏移量。因此25/02/2016 00:00:00
偏移3小时将等同于24/02/2016 21:00:00
当偏移是-hours时,它会直接进入另一个,所以o Result = oLocal + the offset
,如果这是有道理的。因此,在这些情况下不会发生日期变更的主要问题。
显然这不是我想要的。我希望日期是用户为他们的时区选择的。 以前有人见过这样的东西吗?任何可能的解决方案?
我不完全确定我做错了什么。
答案 0 :(得分:0)
修复是在从数据库中获取值并重新显示之前运行以下命令 -
static public itDateTime FixUTCUsingTimeZone(TimeZoneInfo oTimeZone, itDateTime oDateTime)
{
if (oDateTime == null || oTimeZone == null)
return oDateTime;
DateTime oTime = DateTime.SpecifyKind(oDateTime.Value, DateTimeKind.Unspecified);
DateTime oResult = TimeZoneInfo.ConvertTimeFromUtc(oTime, oTimeZone);
return new itDateTime(oResult);
}
所以基本上只是执行前面执行的ConvertTimeToUtc的反向操作。不知道为什么最初没有这样做,但是你去了。
答案 1 :(得分:0)
如果您需要维护正确的时区,则应使用DateTimeOffset
类型而不是DateTime
类型。
DateTimeOffset
维持与UTC的偏移,因此您永远不会丢失您的时区信息,并且有许多有用的方法,例如
UtcDateTime
从马口:
https://msdn.microsoft.com/en-us/library/system.datetimeoffset(v=vs.110).aspx
https://docs.microsoft.com/en-us/dotnet/standard/datetime/choosing-between-datetime