【问题标题】:handling null values of datetime处理日期时间的空值
【发布时间】:2012-06-05 19:03:22
【问题描述】:

我有一个 Linq 查询,它由我从数据库中提取的这个日期时间字段组成

           TerminationDate = base.ConvertFromUtcToCentral(r.TerminationDate.ToString())

使用的函数是这样设计的

           public DateTime ConvertFromUtcToCentral(string UtcTime)
    {

        if (UtcTime != "")
        {
            DateTime?  retValue = TimeZoneInfo.ConvertTimeFromUtc(Convert.ToDateTime
                                                       (UtcTime), USTimeZones.Central);

            return Convert.ToDateTime(retValue);
        }
        else
            return Convert.ToDateTime(null);

    }

但每当我返回 null 时,它都会在网格中显示我将此查询分配给的最小日期。但是,当它为 null 时,它应该只显示 null 而不是 min date。你能告诉我如何处理这个问题吗?如果使用三元运算符更好,请告诉我。

限制:不能更改函数重运行类型,因为它在多个地方使用

【问题讨论】:

  • 如果 DateTime 实际上为 NULL,则作为字符串 UtcTime 传递的内容是什么?
  • 如果数据库中的 UtcTime 实际上为空,则将传递空字符串 ""
  • r.TerminationDate 的类型到底是什么,为什么要把它转换成string,然后又从string 转换成DateTime
  • 据我所知,没有办法让它显示为空,因为 DateTime 空值与我认为是 1900 年 1 月 1 日上午 12:00 的最小值相同沿着这些思路。是否有特定原因需要它返回 null 而不是 min date?如果是这样,在哪里需要有空值?在数据库中还是在您的代码中?
  • 一个函数在多个地方使用不应该阻止你重构它,如果这是要求的话。在这种情况下,这似乎是最合理的前进方式。

标签: c# asp.net linq


【解决方案1】:

由于您要返回值类型 DateTime,因此您不能返回 null。您可以更改函数以返回可为空的 DateTime (DateTime?)、引发异常或返回 DateTime 的默认值 default(DateTime)。恕我直言,我会抛出 System.ArgumentException,因为要转换的空字符串显然不会产生输出。

【讨论】:

  • 仅供参考:Convert.ToDateTime(null) 确实返回 DateTime.MinValue,这也恰好是 default(DateTime) 的值。
  • @hangy 哎呀我的错。下次需要慢慢读题。
  • :) 无论如何,抛出异常实际上会改变方法的行为,并以某种方式改变类的公共接口。与在某些 GUI 中显示的 DateTime.MinValue 相比,这样的重大更改可能会导致更多问题(用户错误报告)。
【解决方案2】:

也许您可以尝试返回null。 让你的函数返回DateTime?, 所以你可以用return null代替return Convert.ToDateTime(null);

抱歉英语不好!

【讨论】:

  • 该函数用于不同查询的多个地方。所以,现在很难修改函数
  • +1。 @Nishanth,您能否根据您的限制更新您的问题 - 到目前为止,更改返回类型是唯一合理的方法,因为 DateTime 值类型没有特殊的“null”值(最小值是您在没有可空类型的情况下可以获得的最接近的值)。
  • 如果函数在多个地方使用,为什么不直接调用函数并传入参数呢?函数的全部意义在于代码重用,因此您应该只更改一次函数。
【解决方案3】:

由于你不能改变函数的限制,那么你可以在:

TerminationDate = ( base.ConvertFromUtcToCentral(r.TerminationDate.ToString()) == default(DateTime) ? (DateTime?) null : (DateTime ?) base.ConvertFromUtcToCentral(r.TerminationDate.ToString()) );

我不喜欢这样,因为它调用了两次函数。我可能会写一个包装器方法来做这样的事情

public static DateTime? WrapperConvertFromUtcToCentral(string UtcTime)
{
    DateTime value = ConvertFromUtcToCentral(string UtcTime);

    if (value == default(DateTime))
         return (DateTime?)null;
    else
         return (DateTime?)value;
}

TerminationDate = WrapperConvertFromUtcToCentral(r.TerminationDate.ToString())        

这样你只调用一次原始函数。

【讨论】:

  • 一个包装器是我想到的第一件事——我同意在条件允许的情况下它是一个优雅的解决方案
【解决方案4】:

最近的编辑和 cmets 表明 TerminationDate 可能是 DateTime?。也许添加一个新的重载来显式处理DateTimeDateTime 值并正确返回DateTimeDateTime??我发现您无法轻松更改此方法的返回类型,因此添加这些新的重载并在您的应用程序中逐渐使用它们可能是使用更好的数据类型的好方法。

public DateTime ConvertFromUtcToCentral(string UtcTime)
{
    return !string.IsNullOrEmpty(UtcTime)
        ? this.ConvertFromUtcToCentral(Convert.ToDateTime(UtcTime))
        : default(DateTime);
}

public DateTime? ConvertFromUtcToCentral(DateTime? UtcTime)
{
    return UtcTime.HasValue
        ? this.ConvertFromUtcToCentral(UtcTime.Value)
        : (DateTime?)null;
}

public DateTime ConvertFromUtcToCentral(DateTime UtcTime)
{
    return TimeZoneInfo.ConvertTimeFromUtc(UtcTime, USTimeZones.Central);
}

如果不更改返回类型,则始终需要从方法中获取非空 DateTime 值,除非 - 正如 user957902 建议的那样 - 你开始抛出 Exceptions。 :) 如果您不能使用它,您还可以修改消费应用程序以将DateTime.MinValue 视为null 并且不显示任何内容。

是否使用三元运算符可能是个人喜好问题 - 在像这样的简单情况下,我确实喜欢使用它(我的示例中的换行符纯粹是为了在 SO 上更容易阅读),因为它很漂亮易于阅读,并且只有两条路径可以走峡谷。

【讨论】:

    【解决方案5】:

    不能为 DateTime 分配空值,因为它不是可以为空的类型 在将其发布回数据库时尝试分配 DBNull.Value 而不是 null

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-01
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多