75

在我的 C# 应用程序中,我传递了一个格式为 yyyymmdd-yyyymmdd 的字符串变量,它表示从和到日期。我想分别获取这些日期的开始时间和结束时间。目前我有以下代码,但想知道是否有更多优雅的解决方案?

所以对于 pdr = 20090521-20090523 将得到“20090521 00:00:00”和“20090523 23:59:59”

private void ValidateDatePeriod(string pdr, out DateTime startDate, 
                                out DateTime endDate)
{
    string[] dates = pdr.Split('-');

    if (dates.Length != 2)
    {
        throw new Exception("Date period is of incorrect format");
    }

    if (dates[0].Length != 8 || dates[1].Length != 8)
    {
        throw new Exception("Split date periods are of incorrect format");
    }

    startDate = DateTime.ParseExact(dates[0] + " 00:00:00", 
        "yyyyMMdd HH:mm:ss", null);
    endDate = DateTime.ParseExact(dates[1] + "23:59:59", 
        "yyyyMMdd HH::mm:ss", null);
}
4

10 回答 10

227

我很惊讶地看到一个不正确的答案如何获得如此多的赞成票:

错误的值

正确的版本如下:

public static DateTime StartOfDay(this DateTime theDate)
{
    return theDate.Date;
}

public static DateTime EndOfDay(this DateTime theDate)
{
    return theDate.Date.AddDays(1).AddTicks(-1);
}
于 2013-12-13T11:42:07.373 回答
43

您可以在某处定义两个扩展方法,在一个实用程序类中,如下所示:

public static DateTime EndOfDay(this DateTime date)
{
    return new DateTime(date.Year, date.Month, date.Day, 23, 59, 59, 999);
}

public static DateTime StartOfDay(this DateTime date)
{
    return new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, 0);
}

然后在代码中使用它们,如下所示:

public DoSomething()
{
    DateTime endOfThisDay = DateTime.Now.EndOfDay();
}
于 2009-05-24T08:51:14.837 回答
25

如果您只担心 .Net 精度...

startDate = DateTime.ParseExact(dates[0], "yyyyMMdd");
endDate = DateTime.ParseExact(dates[1], "yyyyMMdd").AddTicks(-1).AddDays(1);

您真的不需要将额外的值连接到时间部分的字符串上。


作为附录,如果您将其用于针对例如数据库的查询...

startDate = DateTime.ParseExact(dates[0], "yyyyMMdd");
endDate = DateTime.ParseExact(dates[1], "yyyyMMdd").AddDays(1);

询问...

WHERE "startDate" >= @startDate AND "endDate" < @endDate

那么评论中提到的精度问题就无关紧要了。在这种情况下,endDate不是范围的一部分,而是外部边界。

于 2009-05-24T02:29:02.117 回答
17
public static class DateTimeExtension {        
    public static DateTime StartOfTheDay(this DateTime d) => new DateTime(d.Year, d.Month, d.Day, 0, 0,0);
    public static DateTime EndOfTheDay(this DateTime d) => new DateTime(d.Year, d.Month, d.Day, 23, 59,59);
}
于 2019-04-23T12:37:53.803 回答
15

DateTime对象有一个名为的属性Date,它将只返回日期部分。(时间部分默认为上午 12:00)。

我建议作为一个更优雅的解决方案(恕我直言),如果您想在最后一天允许任何日期时间,那么您将 1 天添加到日期,并比较以允许大于或等于开始日期的时间,但严格小于比结束日期(加上 1 天)。

// Calling code.  beginDateTime and endDateTime are already set.
// beginDateTime and endDateTime are inclusive.
// targetDateTime is the date you want to check.
beginDateTime = beginDateTime.Date;
endDateTime = endDateTime.Date.AddDays(1);

if ( beginDateTime <= targetDateTime &&
     targetDateTime < endDateTime )
   // Do something.
于 2009-05-24T00:55:51.743 回答
5

我在 C# 中使用以下内容

public static DateTime GetStartOfDay(DateTime dateTime)
{
    return new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 0, 0, 0, 0);
}
public static DateTime GetEndOfDay(DateTime dateTime)
{
    return new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59, 999);
}

然后在 MS SQL 中,我执行以下操作:

if datepart(ms, @dateEnd) = 0
   set @dateEnd = dateadd(ms, -3, @dateEnd)

这将导致 MS SQL 时间为 23:59:59.997,这是成为第二天之前的最长时间。

你可以简单地使用:

new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59, 999);

这将在 MS SQL 中工作,但这在 .Net 方面并不准确。

于 2015-03-04T19:41:04.617 回答
4

这几乎就是我会做的,稍加调整(真的没什么大不了的,只是吹毛求疵):

  • 应该使用 / 方法返回而TryParse()不是抛出异常。TryParseExact()false
  • FormatException比更具体Exception
  • 无需检查 Length == 8,因为ParseExact()/TryParseExact()会这样做
  • "00:00:00"并且"23:59:59"不需要
  • return true/false你是否能够解析,而不是抛出异常(记得检查从这个方法返回的值!)

代码:

private bool ValidateDatePeriod(string pdr, out DateTime startDate, 
                        out DateTime endDate)
{
   string[] dates = pdr.Split('-');

   if (dates.Length != 2)
   {
       return false;
   }

   // no need to check for Length == 8 because the following will do it anyway
   // no need for "00:00:00" or "23:59:59" either, I prefer AddDays(1)

   if(!DateTime.TryParseExact(dates[0], "yyyyMMdd", null, DateTimeStyles.None, out startDate))
      return false;

   if(!DateTime.TryParseExact(dates[1], "yyyyMMdd", null, DateTimeStyles.None, out endDate))
      return false;

   endDate = endDate.AddDays(1);
   return true;
}
于 2009-05-24T02:18:24.227 回答
3

我认为我们做错了。没有一天结束这样的事情。AddTick(-1)仅在没有小于刻度的时间间隔的约定下有效。这取决于实现。诚然,这个问题带有一个参考实现,即 .Net FrameworkDateTime类,但我们仍然应该以此为线索,我们真正想要的功能不是EndOfDay()StartOfNextDay()

public static DateTime StartOfNextDay(this DateTime date)
{
    return date.Date.AddDays(1);
}
于 2014-03-27T15:55:19.893 回答
0

对于 SQL Server(经过 2008 R2 版测试),此范围有效。

StarDate '2016-01-11 00:00:01.990' EndDate '2016-01-19 23:59:59.990'

似乎滴答声大于一天的最后一秒,并自动舍入到第二天。所以我测试并工作,我制作了一个带有两个日期的虚拟表,用于检查 sql server 捕获哪些值并将这些参数插入到存储过程中。

于 2016-01-27T05:40:29.233 回答
0

在 Java 8 中,您可以使用 LocalDate 执行此操作,如下所示:

    LocalDate localDateStart = LocalDate.now();
    Date startDate = Date.from(localDateStart.atStartOfDay(ZoneId.systemDefault()).toInstant());

    LocalDate localDateEnd = localDateStart.plusDays(1);
    Date endDate = Date.from(localDateEnd.atStartOfDay(ZoneId.systemDefault()).toInstant());
于 2020-10-26T07:25:32.360 回答