【发布时间】:2016-06-06 21:08:12
【问题描述】:
如果用户选择的时区早于 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 时,它会直接进入另一个方向,所以 oResult = oLocal + the offset,如果这有意义的话。因此,在这些情况下不会发生日期更改的主要问题。
显然这不是我想要的。我希望日期是用户为其时区选择的日期。 有没有人见过这样的东西?任何可能的解决方案?
我不完全确定我做错了什么。
【问题讨论】:
-
itTimeAndDate结构/类是什么样的? -
不清楚。 Date 并没有真正的 TimeZone ... DateTime 值。您使用哪种 UI 组件,包含 TZ 的预期用途是什么?
-
如果您找到答案,您应该“回答您自己的问题”...(即自己添加答案)
-
三双三秒@rogerdpack 的评论 - 尽管很多人这样做(他们不应该),但将答案放入问题中是不好的做法,不鼓励。另一方面,鼓励自我回答,因此请将答案作为答案。
-
通常,我发现“你应该使用 X”cmets 很烦人,但是在 C# 中编写了很多 DateTime 处理代码后,我发现 NodaTime 非常有用。可能值得一看。 -- nodatime.org