【问题标题】:TimeZoneInfo.ConvertTime works for US users but not for users in IrelandTimeZoneInfo.ConvertTime 适用于美国用户,但不适用于爱尔兰用户
【发布时间】:2019-05-07 08:35:26
【问题描述】:

我有一个应用程序,用户可以在其中查询数据库以查找测试结果。当他们双击其中一个结果时,它会打开另一个表单来显示数据。我在亚利桑那州开发了这个,数据库测试时间为亚利桑那州和爱尔兰的用户显示了亚利桑那时间。打开的第二个表单的一部分需要访问一个日志文件,而爱尔兰日志文件的问题是文件名中列出的时间是 GMT 而不是 AZ 时间。

例如,数据库将测试时间显示为 12/05/2018 08:31 AM,但爱尔兰测试的日志文件名是 12/05/2018 15:31。为了在开发时处理这个问题,我添加了从测试时间到日志文件时间的更正,如下所示:

 var IRTimeZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
 var IRMetroDateCor = TimeZoneInfo.ConvertTime(testtime, IRTimeZone)

这在我运行应用程序时成功运行 - 它找到了没有问题的日志文件。我刚刚将它部署到爱尔兰供他们测试,通过一些故障排除我们发现 ConvertTime 线没有做任何事情。时间仍然是 2018 年 12 月 5 日上午 8 点 31 分。

关于为什么这会在这里起作用但在那里不起作用的任何想法?其他方式来处理这个问题,使其适用于两个网站?

【问题讨论】:

  • 文化因 PC 设置而异。爱尔兰使用 dd/MM/yyyy,而美国使用 MM/dd/yyyy。
  • 这似乎不是这里的问题。在上述之后,我花时间转换为格式为“yyyMMddHHmmss”的字符串,因为这实际上是日志文件名的开始方式。问题是它在此之后为我转换为 20181205153131 而对他们来说它保持在 20181205083131。
  • 这没什么区别。 PC 将 DateTime 存储为 UTC 时间中的数字。当日期时间输入/输出到字符串时,转换 ToString() 是使用 PC 的时区设置完成的。所以从爱尔兰时间到 MST(山地标准时间)的转换是 7 小时。如果您显示包含时区值的时间,您会看到差异。
  • 时间(和时区)很复杂。你如何坚持时间,在UTC,或作为一些本地时间。您的短语 "database test times show" 让我觉得您的数据库中有亚利桑那时间。如果您想让它工作,您将真的希望将时间保留为 UTC 时间,并将其从/本地时间转换为每个用户。如果您在数据库中有 AZ 时间,那么您将需要从该时间转换为用户的本地时间以进行显示(这很难始终保持正确)。
  • testtime 取自 datagridview 单元格,如下所示:testtime = Convert.ToDateTime(dataGridViewTestList.Rows[e.RowIndex].Cells[6].Value);

标签: c# .net winforms timezone


【解决方案1】:

根据您在问题 cmets 中提供的信息:

testtime 取自 datagridview 单元格,如下所示:

testtime = Convert.ToDateTime(dataGridViewTestList.Rows[e.RowIndex].Cells[6].Value);

DataGridViewCellValue 属性是object 类型,这意味着它可以是任何东西。在这种情况下,它可能是特定格式的string,或者它已经是DateTime。这在很大程度上取决于您首先如何填充DataGridView

  • 如果单元格值已经是DateTime,那么Convert.ToDateTime 只是通过原样传递。您不妨使用(DateTime) theValue 而不是Convert.ToDateTime(theValue) 进行投射。你会得到相同的结果。

    • 结果值的.Kind 属性将与输入值的相同。它可能是DateTimeKind.UtcDateTimeKind.LocalDateTimeKind.Unspecified 中的任何一个。
  • 如果单元格值为string,则Convert.ToDateTime解析字符串,使用当前区域性。相当于调用DateTime.Parse(theValue),只是你没有得到任何用于控制解析的额外参数。

    • 如果输入字符串中有任何时区信息,则结果值的.Kind 属性将为DateTimeKind.Local,否则为DateTimeKind.Unspecified。不可能是DateTimeKind.Utc,出自Convert.ToDateTime

如您所见,根据您获取DateTime 值的方式,其.Kind 属性可能会有所不同。这很重要,因为它控制TimeZoneInfo.ConvertTime 的行为,如in the documentation 所述(滚动到“备注”部分)。

重要的是,请注意如果KindUnspecified,那么它的处理方式与Local 相同。因此,在您的情况下可能发生的情况是,转换总是从当地时间(无论可能是什么)到爱尔兰时间。所以对于爱尔兰用户来说,它似乎根本没有改变。

如果打算从亚利桑那时间到爱尔兰时间总是,那么您需要指定两个时区,并且需要确保输入 Kind 始终为 DateTimeKind.Unspecified

// This is needed if the Kind isn't already Unspecified
DateTime timeInArizona = DateTimeKind.SpecifyKind(testtime, DateTimeKind.Unspecified);

// Get the from and to time zone  (yes, the IDs have weird naming conventions)
TimeZoneInfo arizonaTimeZone = TimeZoneInfo.FindSystemTimeZoneById("US Mountain Standard Time");
TimeZoneInfo irelandTimeZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");

// Do the conversion, specifying both time zones
DateTime timeInIreland = TimeZoneInfo.ConvertTime(timeInArizona, arizonaTimeZone, irelandTimeZone);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-01
    • 1970-01-01
    • 2013-11-03
    • 2014-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多