关于c#:DateTime.MaxValue.Ticks传递给构造函数时更改

DateTime.MaxValue.Ticks changes when passed to constructor

我试图将DateTime.MaxValue传递给一个构造函数,但由于某种原因,当它传递时,Ticks属性从315537897599999999更改为3155378975990000000,使得比较起来很难使用。

1
2
3
4
5
6
7
DateTime dt = DateTime.MaxValue; //here it is 315537897599999999

OfferSetting setting = new OfferSetting(settingCode
    , (Equals(row["AccountId"],"")) ? null : row["AccountId"].ToString()
    , (Equals(row["Arguments"],"")) ? null : row["Arguments"].ToString()
    , (Equals(row["StartDate"],"") || Equals(row["StartDate"], DBNull.Value)) ? DateTime.MinValue : Convert.ToDateTime(row["StartDate"])
    , (Equals(row["EndDate"],"") || Equals(row["StartDate"], DBNull.Value)) ? dt : Convert.ToDateTime(row["EndDate"]));

进入OfferSetting的构造函数后,变为3155378975990000000

1
2
3
4
5
6
7
8
9
10
11
public OfferSetting(SettingCode settingCode, string accountId, string arguments, DateTime startDate, DateTime endDate)
    : base(MoeState.New)
{
    this.Id ="-1";
    this.OfferSettingId ="-1";
    this.SettingCode = settingCode;
    this.AccountId = accountId;
    this.Arguments = arguments;
    this.StartDate = startDate;
    this.EndDate = endDate; //here it is 3155378975990000000
}

有什么想法吗?


我没有责备-我只是试了试,但不能让它责备。您将需要进行调试,如果这样做很容易,请重写代码以将行["enddate"]分配给变量(即使是临时的),这样您至少可以看到该变量中的内容。

仅供参考,在您的第二种情况下,您似乎正在测试第["enddate"]行和第["startdate"]行,这可能是导致问题的原因。

(Equals(row["EndDate"],"") || Equals(row["StartDate"], DBNull.Value)) ? dt : Convert.ToDateTime(row["EndDate"]));

正如其他人所建议的:

  • 尝试使用可为空而不是MaxValue。您可能会遇到不同时区和地区的问题,甚至没有意识到(特别是当您的代码在不同的机器上运行时)。
  • 考虑使用datetimeoffset而不是datetime,因为它表示"即时时间"而不是"日历时间"。更多讨论请参见此处。(您最好还是使用nullable。)


简单地通过一个构造函数参数传递一个值绝对不能改变这个值,所以您可以消除它的那部分。

更可能的是,存在精度损失问题。这可能发生在将值存储到数据库中或检索该值时。

在存储方面,如果您确实需要存储DateTime.MaxValue的全部精度,那么请确保您的数据库中使用的数据类型可以支持它。例如,如果您使用的是SQL Server,那么应该使用datetime2类型,而不是datetime类型。

在检索方面,您的一些代码似乎遭受了一种常见的反模式。

  • 不要这样做:

    1
    DateTime dt = Convert.ToDateTime(row["yourfield"].ToString());
  • 相反,请执行以下操作:

    1
    DateTime dt = (DateTime) row["yourfield"];

当您转换为字符串,然后解析该字符串时,可能会丢失精度。此外,在某些情况下,特定于文化的格式或非公历日历可能会受到影响。只需拆开它,就可以保持原来的类型。不需要字符串。

其他类型也一样,包括整数、布尔值和字符串。基础数据库客户端已经进行了从本机数据库类型到适当的.NET类型的最佳转换。不需要再做那个工作了。


我明白了,我只是个白痴,它把错误的值传递给构造函数。


可以为空的datetime结构将命名为datetime?例如

1
DateTime? ndt=null;

在拨动实际值字段之前,还需要检查(hasValue())。

1
if(ndt.HasValue()){/*do what you meant to */}