日期时间的噩梦,C#中任何彻底的模块或控件都有助于缓解疼痛?

时间:2009-11-28 08:29:01

标签: c# asp.net datetime

再一次,我必须创建一个日期模块,再一次,我生活在完善它的恐怖之中,是我还是日期和时间编程专业中最肮脏的动物,它是潜伏在门后面的野兽,我希望我永远不必处理:(

有没有人知道我可以从以下几个方面处理日期的重要来源:

  • 用户输入日期时间和时区
  • 系统转换为通用时间并保存在数据源中
  • 系统检索转换为开发人员选择的本地时间的通用时间(而不是服务器或客户端位置,可能不是正确的显示区域)
  • 系统应考虑日光时间节省差异
  • 不能依赖“DateTime”解析,因为它在本地服务器时间方面解析波希米亚
  • 必须让开发人员能够处理两种形状:日期时间和字符串对象

我查看了blogengine.net以了解它们是如何处理的,但它太过分了,它们在设置数据源中节省了数小时的时间差,这绝对是不准确的......任何来源都有帮助吗?

我已经在创建使用CultureInfo,TimeZoneInfo,DateTimeOffset的必要方法方面走得很远......但是当我把它放到测试中时,它失败了!感谢帮助

修改

在挤压一些之后,我把它缩小到这个:

public string PrettyDate(DateTime s, string format)
{
    // this one parses to local then returns according to timezone as a string
    s = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(s, "AUS Eastern Standard Time");
    CultureInfo Culture = CultureInfo.CreateSpecificCulture("en-au");
    return s.ToString(format , Culture);
}

问题是,我知道传递的日期是UTC时间,因为我正在使用

DateTimeOffset.Parse(s, _dtfi).UtcDateTime;
// where dtfi has "yyyy-MM-ddTHH:mmzzz" as its FullDateTimePattern

当我在我的日期时间调用该函数时,如下所示:

AuDate.Instance.PrettyDate(el.EventDate,"yyyy-MM-dd HH:mm zzz");

在我的机器上我得到:

2009-11-26 15:01 +11:00
服务器上的

我得到了:

2009-11-26 15:01 -08:00

我发现这非常特别!为什么时区不正确?其他一切都到位了!我错过了什么吗?

4 个答案:

答案 0 :(得分:3)

我对你的指示的评论。

  • 用户输入日期时间和时区
    @ 确定无问题

  • 系统转换为通用时间并保存在数据源中 @ 确定无问题

  • 系统检索转换为开发人员选择的本地时间的通用时间(不是服务器或客户端位置,可能不是正确的显示区域)
    @ 这是要求吗?为什么不直接检索

  • 系统应考虑日光时间节省差异 @ 可由DaylightTime ClassTimeZone Class等处理

  • 不能依赖“DateTime”解析,因为它在本地服务器时间方面解析波希米亚语 @ 然后不要依赖DateTime Parsing

  • 必须赋予开发人员处理两种形状的能力:日期时间和字符串对象
    @ DateTime Class作为基础应该足够好,使用TimeZone / TimeZoneInfo / DaylightTime / DateTimeOffset等来增强它

答案 1 :(得分:2)

我感到很痛苦 - 这就是为什么我参与Noda Time项目,为.NET带来功能齐全的日期和时间API。然而,那刚刚起步。如果你仍然困在一年的时间,希望Noda Time将是答案:)

正常的.NET情况比我们现在有DateTimeOffsetTimeZoneInfo更好,但它仍然有点缺乏。

然而,只要你正确地使用TimeZoneInfo两次,它应该没问题。我不确定DateTime解析是否应该太糟糕 - 我认为它应该将其解析为DateTimeKind.Unspecified,除非您在数据中指定其他内容。然后,您可以使用TimeZoneInfo将其转换为UTC。

你能提供一个简短但完整的程序来显示你遇到的问题吗?

答案 2 :(得分:2)

实际上,我发现.NET日期/时间功能非常好。我对你的麻烦感到困惑。

你究竟想做什么DateTimeOffsetTimeZoneInfo不能为你做什么?

  • “用户输入日期时间和时区” - 检查! DateTimeDateTimeOffset可以在此处使用。
  • “系统转换为通用时间并保存在数据源中” - 检查!同样,DateTimeDateTimeOffset对您有用,但如果您想存储时区偏移,大多数数据库后端都需要一些特殊处理。如果您已经将其转换为UTC,只需将其存储为SQL Server中的datetime字段或另一个RDBMS中的等效字段,并且不要担心存储它是UTC的事实。
  • “系统检索转换为开发人员选择的本地时间的通用时间” - 检查!只需为您想要的当地时间构建TimeZoneInfo,然后拨打TimeZoneInfo.ConvertTime
  • “系统应考虑日光时间节省差异” - 检查!这就是TimeZoneInfo.AdjustmentRule的用途。
  • “不能依赖于”DateTime“解析,因为它在本地服务器时间方面解析波希米亚” - ???首先,“bohemiangly”甚至不是一个字。您可以使用DateTime.ParseExact自定义日期时间的解析方式。
  • “必须让开发人员能够处理两种形状:日期时间和字符串对象” - 为什么?只保留一个内部表示然后只转换输入和输出有什么问题?我无法想到对日期/时间值的任何操作,通过对字符串进行操作会更容易。

简而言之,我认为你只是在处理日常/时间数据处理的复杂性。

答案 3 :(得分:0)

感谢Jon Skeet让我走上了正确的道路,我以前从来不知道这一点,但现在我知道,DateTime对象并不保留时区信息!所以每当我使用它时,我已经丢失了日期时间偏移信息,但是DateTimeOffset对象保留了时区位,所以我的所有对象都应该使用它,我真的认为datetimeoffset对象有点限制,我想发布一个关于datetimedatetimeoffset之间有什么不同的问题,我应该这样做!

现在我使用以下代码检索正确的区域:

string s = "2009-11-26T04:01:00.0000000Z";
DateTimeOffset d = DateTimeOffset.Parse(s);

TimeZoneInfo LocalTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");
DateTimeOffset newdate = TimeZoneInfo.ConvertTime(d, LocalTimeZoneInfo);
return newdate.ToString("yyyy-MM-dd HH:mm zzz");

谢谢大家的意见