如何得到一天的开始和结束时间

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

因此,对于 pdr = 20090521-20090523,将得到“2009052100:00:00”和“2009052323: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);
}
133184 次浏览

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.

这差不多就是我要做的,只是做一些小的调整(真的没什么大不了的,只是吹毛求疵) :

  • 应该使用返回 false而不是抛出异常的 TryParse()/TryParseExact()方法。
  • FormatExceptionException更具体
  • 不需要检查 Llength = = 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;
}

如果你只是担心.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

那么评论中提到的精确度问题就不那么重要了。在这种情况下,结束日期不是范围的一部分,而是外部边界。

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

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();
}

我很惊讶 不正确的回答怎么会得到这么多的赞:

Wrong value

正确的版本如下:

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


public static DateTime EndOfDay(this DateTime theDate)
{
return theDate.Date.AddDays(1).AddTicks(-1);
}

我觉得我们做错了。根本没有末日这回事。AddTick(-1)只在没有比刻度小的时间间隔的约定下工作。这取决于实现。不可否认,这个问题伴随着一个参考实现而来,即。NetFrameworkDateTime类,但是我们仍然应该将此作为一个线索,即我们真正想要的函数不是 EndOfDay()而是 StartOfNextDay()

public static DateTime StartOfNextDay(this DateTime date)
{
return date.Date.AddDays(1);
}

我在 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);

它在 MSSQL 中可以工作,但是在.Net 端不是那么精确。

对于 SQLServer (2008R2测试版) ,此范围可以工作。

星期日’2016-01-1100:00:01.990’ 结束日期’2016-01-1923:59:59.990’

看起来滴答声比一天的最后一秒更大,而且会自动转到第二天。因此,我测试并工作,我制作了一个带有两个日期的虚拟表,用于检查 sql server 捕获哪些值并在存储过程中插入这些参数。

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);
}

在 Java8中,可以使用 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());

上面关于几毫秒的问题可以通过查询第二天的开始日期来解决。

例如:

SELECT * FROM temp WHERE createdDate >= fromDate AND createdDate < toDate

使用下面的扩展方法,您可以将 from 和 to 日期设置为:

DateTimeOffset fromDate = DateTimeOffset.UtcNow.StartOfDay();
DateTimeOffset toDate = DateTimeOffset.UtcNow.EndOfDay();
public static class DateExtentions
{
public static DateTimeOffset StartOfDay(this DateTimeOffset dateTime)
{
return new DateTimeOffset(dateTime.Year, dateTime.Month, dateTime.Day, 0, 0, 0, 0, dateTime.Offset);
}


public static DateTimeOffset EndOfDay(this DateTimeOffset dateTime)
{
return dateTime.StartOfDay().AddDays(1);
}


public static DateTimeOffset StartOfMonth(this DateTimeOffset dateTime)
{
return new DateTimeOffset(dateTime.Year, dateTime.Month, 1, 0, 0, 0, 0, dateTime.Offset);
}


public static DateTimeOffset EndOfMonth(this DateTimeOffset dateTime)
{
return dateTime.StartOfMonth().AddMonths(1);
}


public static DateTimeOffset StartOfYear(this DateTimeOffset dateTime)
{
return new DateTimeOffset(dateTime.Year, 1, 1, 0, 0, 0, 0, dateTime.Offset);
}


public static DateTimeOffset EndOfYear(this DateTimeOffset dateTime)
{
return dateTime.StartOfYear().AddYears(1);
}
}