在使用 WCF 服务和数据表序列化/反序列化时停止日期时间的自动本地化
本文关键字:日期 时间 本地化 反序列化 WCF 服务 序列化 数据表 | 更新日期: 2023-09-27 18:35:04
我无法弄清楚这一点,这让我发疯了。为什么数据类型对象会这样做,这超出了我的范围。我觉得处理时区的指定类型就足够了。无论如何,这是我的设置。我有一个 WCF 服务,该服务将序列化的数据表提供给我的应用。数据通过 Web 界面输入。如果我将 12/12/2014 11:00 AM 放入数据库,它将通过 Web 服务将数据表中的 12/12/2014 12:00 PM 严格返回给我的应用。
我该如何阻止这种情况!?
事件链:
- 登录到 Web 界面,选择立即执行任务(传递 DateTime.Now)或稍后执行任务(解析用户选择的日期时间常量的字符串表示形式)。我将时区存储在单独的列中。注意:DateTime.Now 不会由序列化程序自动本地化,另一个 WILL 会。
- 任务设置正确。所有日期都正确反映在数据库中。目前还没有差异。
- 任务在设置的正确时间执行。因为我正在处理这些任务设置为执行的时区差异。这是顺利的工作。任务在应该执行的时候执行。
- 看看手机。时间不对了。我断点,并且来自已序列化和反序列化的数据表中的 Web 服务的数据不正确。这将是一个小时的休息时间(CMT到EST)。
我尝试过在不同的地方改变这种类型,但没有任何效果。
我希望我放入数据库的内容与显示的内容完全相同。我通过简单的算术处理数据库逻辑中的时区转换。不需要这种自动化。
对于这样一个老问题,我厌倦了挖掘堆积如山的工作解决方法,这些解决方法都不起作用,或者有足够好地解释该做什么以及如何处理这个问题的决议。
尽管需要很多调整,但我还是得到了它。这也适用于我的特定设置,可能不适用于所有人。
我的设置:日期时间从数据库所在的同一时区的 Web 界面传递到数据库。在同一时区中运行的 Windows 服务根据"显示时间"字段循环并拉出任务。然后从任何时区的手机应用程序中提取此数据,并以多长时间前的形式显示值,例如 1 分钟前、2 小时前等。手机应用是唯一与 WCF 服务接口的应用。由于 Windows 服务驻留在同一台服务器上,因此它不需要任何中间人。
首先在网站上输入这些"任务"时,日期时间由以下内容获得。
Double selectedTimezone = 0D;
Double offsetTimezone = 0D;
TimeZoneInfo timezoneInfo = TimeZoneInfo.Local;
selectedTimezone = Double.Parse(DDL_EndTimezone.SelectedValue.ToString());
/* Obtain the timezone offset for server to user.
For me this is -1: -6 (CST) to -5 (EST) */
offsetTimezone = (timezoneInfo.BaseUtcOffset.TotalHours - selectedTimezone);
/* Parse the date time from the selected user
inputs. */
if (!chkSendMessageNow.Checked)
start = DateTime.Parse(txtBeginDate.Text + " " + cmdBeginHour.SelectedValue.ToString() + ":" + cmdBeginMinute.SelectedValue.ToString() + ":" + "00");
else
start = DateTime.Parse(DateTime.Now.ToString("MM/dd/yyyy") + " " + DateTime.Now.Hour.ToString() + ":" + DateTime.Now.Minute.ToString() + ":" + "00");
end = DateTime.Parse(txtEndDate.Text + " " + DDL_EndHour.SelectedValue.ToString() + ":" + DDL_EndMin.SelectedValue.ToString() + ":" + "00");
/* Ensure these are "local" kind. I quote because
this is local time for user, not where the
site is hosted. */
start = DateTime.SpecifyKind(start, DateTimeKind.Local);
end = DateTime.SpecifyKind(end, DateTimeKind.Local);
/* Convert the start and end to UTC from
the timezone of the user with the
adjusted server to user timezone
offset. */
start = start.AddHours(offsetTimezone).AddHours(-1 * selectedTimezone);
end = end.AddHours(offsetTimezone).AddHours(-1 * selectedTimezone);
/* Specify this is UTC. */
start = DateTime.SpecifyKind(start, DateTimeKind.Utc);
end = DateTime.SpecifyKind(end, DateTimeKind.Utc);
现在这些都保存到数据库中。
在 WCF 服务的服务器上,我拉取了数据表,但在返回要序列化的输出之前调整了 DateTime 列,如下所示。此步骤可能不是必需的,并且是先前尝试的残留步骤。但我没有搞砸它,因为它正在工作。
Int32 upperBound = (output.Rows.Count - 1);
DateTime showAfter = DateTime.MinValue;
DateTime showBefore = DateTime.MinValue;
for (Int32 i = upperBound; (i >= 0); i--)
{
showAfter = (DateTime)output.Rows[i]["ShowAfter"];
showBefore = (DateTime)output.Rows[i]["ShowBefore"];
showAfter = DateTime.SpecifyKind(showAfter, DateTimeKind.Utc);
showBefore = DateTime.SpecifyKind(showBefore, DateTimeKind.Utc);
output.Rows[i]["ShowAfter"] = showAfter;
output.Rows[i]["ShowBefore"] = showBefore;
}
最后在应用程序中显示反序列化时正确本地化的时间。我执行以下操作。
DateTime showAfter = DateTime.MinValue;
showAfter = Convert.ToDateTime(_dataTable.Rows[position]["ShowAfter"]);
showAfter = DateTime.SpecifyKind(showAfter, DateTimeKind.Utc);
showAfter = showAfter.ToLocalTime();