书接上回,我们继续来分享一些关于特殊时间获取的常用扩展方法。

01
、获取当天的开始时间

当天的开始时间指00:00:00时刻,因此只需要获取DateTime的Date属性只获取时间即可,具体代码如下:

//获取当天的开始时间
public static DateTime GetStartDateTimeOfDay(this DateTime dateTime)
{
    return dateTime.Date;
}

我们进行一个简单的单元测试,具体代码如下:

[Fact]
public void GetStartDateTimeOfDay()
{
    var datetime = new DateTime(2024, 11, 7, 14, 10, 10);
    var start = datetime.GetStartDateTimeOfDay();
    Assert.Equal(new DateTime(2024, 11, 7), start);
}

02
、获取当天的结束时间

该方法时候获取一天中最后一刻,也就是第二天的前一刻,我们可以用第二天的开始时间减去最小时间单位得到当天的结束时间,具体代码如下:

//获取当天的结束时间
public static DateTime GetEndDateTimeOfDay(this DateTime dateTime)
{
    return dateTime.Date.AddDays(1).AddTicks(-1);
}

下面我们通过单元测试验证,时间部分是否为“23:59:59 9999999”,具体代码如下:

[Fact]
public void GetEndDateTimeOfDay()
{
    var date4 = new DateTime(2024, 11, 7, 14, 10, 10);
    var end = date4.GetEndDateTimeOfDay();
    Assert.Equal("2024-11-07 23:59:59 9999999", end.ToString("yyyy-MM-dd HH:mm:ss fffffff"));
}

03
、获取当前日期所在周的第一天(周一)

要想获得当前日期所在周的周一,只需要知道当前是周几,然后计算出和周一相差几天,最后使用AddDays方法即可。

首先我们可以通过DayOfWeek获取到日期是周几枚举值,但是这个枚举值对应的int值是

0 = Sunday 周日, 1 = Monday 周一, ..., 6 = Saturday 周六。其中周日的0就显得很异类,处理起来也就比较麻烦。

因此如果当前日期是周日那么就会出现周日减周一等于0减1等于-1的情况,所有我们需要加7来保证结果为正数。

同样如果当前日期是周六那么就会出现周六减周一等于6减1加7等于12的情况,所以我们需要同取余%7,来保证两者相差在一周天数之内。

具体代码如下:

//获取当前日期所在周的第一天(周一)
public static DateTime GetFirstDayDateTimeOfWeek(this DateTime dateTime)
{
    //0 = Sunday 周日, 1 = Monday 周一, ..., 6 = Saturday 周六
    //首先获取当前日期星期枚举值,然后计算其和周一枚举值差值
    //结果+7,保证结果为正数
    //结果%7,保证结果在0-6之间,对于一周七天,从而表示要回退多少天到周一
    //+7 %7 巧妙的把周日当7处理,最后再转为0
    var diff = ((int)dateTime.DayOfWeek - (int)DayOfWeek.Monday + 7) % 7;
    return dateTime.AddDays(-diff).Date;
}

下面我们需要进行详细的单元测试,我们进行了四种情况的测试分别是:

(1) 验证当前日期是周五,而周一在上一个月的情况;

(2) 验证当前日期就是周一的情况;

(3) 验证当前日期是周四,而周一在当月的情况

(4) 验证当前日期是周日,而周一在当月的情况

具体代码如下:

[Fact]
public void GetFirstDayDateTimeOfWeek()
{
    //验证当前日期是周五,而周一在上一个月的情况
    var friday = new DateTime(2024, 11, 1, 14, 10, 10);
    var day_friday = friday.GetFirstDayDateTimeOfWeek();
    Assert.Equal(new DateTime(2024, 10, 28), day_friday);
    //验证当前日期就是周一的情况
    var monday = new DateTime(2024, 11, 4, 4, 10, 10);
    var day_monday = monday.GetFirstDayDateTimeOfWeek();
    Assert.Equal(new DateTime(2024, 11, 4), day_monday);
    //验证当前日期是周四的情况
    var thursday = new DateTime(2024, 11, 7, 4, 10, 10);
    var day_thursday = thursday.GetFirstDayDateTimeOfWeek();
    Assert.Equal(new DateTime(2024, 11, 4), day_thursday);
    //验证当前日期是周日的情况
    var sunday = new DateTime(2024, 11, 10, 4, 10, 10);
    var day_sunday = sunday.GetFirstDayDateTimeOfWeek();
    Assert.Equal(new DateTime(2024, 11, 4), day_sunday);
}

04
、获取当前日期所在周的最后一天(周日)

该方法和上面获取周一的思想一样,我们可以把周日枚举值就当作7来处理,具体代码如下:

//获取当前日期所在周的最后一天(周日)
public static DateTime GetLastDayDateTimeOfWeek(this DateTime dateTime)
{
    //0 = Sunday 周日, 1 = Monday 周一, ..., 6 = Saturday 周六
    //首先计算还差几天到周日
    //结果%7,保证结果在0-6之间
    //当周日时dateTime.DayOfWeek为0,(7-0)% 7 = 0
    //巧妙的把周日当7处理,最后再转为0
    var diff = (7 - (int)dateTime.DayOfWeek) % 7;
    return dateTime.AddDays(diff).Date;
}

同样的我们做类似获取周一的四种情况单元测试,具体代码如下:

[Fact]
public void GetLastDayDateTimeOfWeek()
{
    //验证当前日期是周六,而周日在下一个月的情况
    var sunday = new DateTime(2024, 11, 30, 14, 10, 10);
    var day_sunday = sunday.GetLastDayDateTimeOfWeek();
    Assert.Equal(new DateTime(2024, 12, 1), day_sunday);
    //验证当前日期就是周一的情况
    var monday = new DateTime(2024, 11, 4, 4, 10, 10);
    var day_monday = monday.GetLastDayDateTimeOfWeek();
    Assert.Equal(new DateTime(2024, 11, 10), day_monday);
    //验证当前日期是周四的情况
    var thursday = new DateTime(2024, 11, 7, 4, 10, 10);
    var day_thursday = thursday.GetLastDayDateTimeOfWeek();
    Assert.Equal(new DateTime(2024, 11, 10), day_thursday);
    //验证当前日期是周日的情况
    var sunday1 = new DateTime(2024, 11, 10, 4, 10, 10);
    var day_thursday1 = sunday1.GetLastDayDateTimeOfWeek();
    Assert.Equal(new DateTime(2024, 11, 10), day_thursday1);
}

05
、获取当前日期所在月的第一天

这个方法比较简单,只需要使用当前日期的年份和月份,然后直接构建当月第一天,具体代码如下:

//获取当前日期所在月的第一天
public static DateTime GetFirstDayDateTimeOfMonth(this DateTime dateTime)
{
    return new DateTime(dateTime.Year, dateTime.Month, 1, 0, 0, 0, 0, DateTimeKind.Local);
}

这个方法太简单了,我们就不列出单元测试代码了。

06
、获取当前日期所在月的最后一天

该方便也不复杂,可以先通过DaysInMonth获取当前月的总天数,然后再构建当月最后一天,具体代码如下:

//获取当前日期所在月的最后一天
public static DateTime GetLastDayDateTimeOfMonth(this DateTime dateTime)
{
    //获取当前月的总天数
    var days = DateTime.DaysInMonth(dateTime.Year, dateTime.Month);
    return new DateTime(dateTime.Year, dateTime.Month, days, 0, 0, 0, 0, DateTimeKind.Local);
}

同样的我们这个方法也不复杂,我们就不列举单元测试了。

07
、获取当前日期所在季度的第一天

如果想要获取当前日期所在季度的第一天那么首先需要获取当前日期所在季度的第一个月是多少。

我们知道三个月为一季度,因此我们可以使用当前月份除以3,如果这样直接除就会得到:1/3=0,2/3=0,3/3=1,这样1月到3月就不在同一个季度里,所以我们使用(moth - 1)/ 3,计算出0、1、2、3表示4个季度,这样就可以计算出当前日期所在第几个季度。

计算出所在季度后我们还需要计算出当前季度的第一个月即1月、4月、7月、10月,然后找出这4个月份与上面表示4个季度值的关系即可,最终得到如下公式:(moth - 1)/ 3 * 3 +1,即为当前日期所在季度的第一个月。

最后就是直接构建日期,具体代码如下:

//获取当前日期所在季度的第一天
public static DateTime GetFirstDayDateTimeOfQuarter(this DateTime dateTime)
{
    //计算当前日期所在季度的起始月
    var firstMonth = (dateTime.Month - 1) / 3 * 3 + 1;
    return new DateTime(dateTime.Year, firstMonth, 1, 0, 0, 0, 0, DateTimeKind.Local);
}

然后我们分别对这个方法做以下三种情况的单元测试:

(1) 一个季度第一个月取第一天的情况;

(2) 一个季度第二个月取中间的一天的情况;

(3) 一个季度第三个月取最后一天的情况;

[Fact]
public void GetFirstDayDateTimeOfQuarter()
{
    //一个季度第一个月取第一天的情况
    var month1 = new DateTime(2024, 10, 1, 14, 10, 10);
    var day_month1 = month1.GetFirstDayDateTimeOfQuarter();
    Assert.Equal(new DateTime(2024, 10, 1), day_month1);
    //一个季度第二个月取中间的一天的情况
    var month2 = new DateTime(2024, 11, 17, 4, 10, 10);
    var day_month2 = month2.GetFirstDayDateTimeOfQuarter();
    Assert.Equal(new DateTime(2024, 10, 1), day_month2);
    //一个季度第三个月取最后一天的情况
    var month3 = new DateTime(2024, 12, 31, 4, 10, 10);
    var day_month3 = month3.GetFirstDayDateTimeOfQuarter();
    Assert.Equal(new DateTime(2024, 10, 1), day_month3);
}

08
、获取当前日期所在季度的最后一天

该方法和上面获取季度的第一天思想一样,只是此方法获取当前日期所在季度的最后月份的计算公式有所差异,公式为:(moth + 2)/ 3 * 3,具体代码如下:

//获取当前日期所在季度的最后一天
public static DateTime GetLastDayDateTimeOfQuarter(this DateTime dateTime)
{
    //计算当前日期所在季度的最后月
    var lastMonth = (dateTime.Month + 2) / 3 * 3;
    //获取当前月的总天数
    var days = DateTime.DaysInMonth(dateTime.Year, lastMonth);
    return new DateTime(dateTime.Year, lastMonth, days, 0, 0, 0, 0, DateTimeKind.Local);
}

同样的我们对其进行三种情况单元测试,具体代码如下:

[Fact]
public void GetLastDayDateTimeOfQuarter()
{
    //一个季度第一个月取第一天的情况
    var month1 = new DateTime(2024, 10, 1, 14, 10, 10);
    var day_month1 = month1.GetLastDayDateTimeOfQuarter();
    Assert.Equal(new DateTime(2024, 12, 31), day_month1);
    //一个季度第二个月取中间的一天的情况
    var month2 = new DateTime(2024, 11, 17, 4, 10, 10);
    var day_month2 = month2.GetLastDayDateTimeOfQuarter();
    Assert.Equal(new DateTime(2024, 12, 31), day_month2);
    //一个季度第三个月取最后一天的情况
    var month3 = new DateTime(2024, 12, 31, 4, 10, 10);
    var day_month3 = month3.GetLastDayDateTimeOfQuarter();
    Assert.Equal(new DateTime(2024, 12, 31), day_month3);
}

09
、获取当前日期所在年的第一天

该方法比较简单,直接用当前日期所在年份和1月1号直接构建即可,代码如下:

//获取当前日期所在年的第一天
public static DateTime GetFirstDayDateTimeOfYear(this DateTime dateTime)
{
    return new DateTime(dateTime.Year, 1, 1, 0, 0, 0, 0, DateTimeKind.Local);
}

10
、获取当前日期所在年的最后一天

该方法也比较简单,直接用当前日期所在年份和12月31号直接构建即可,代码如下:

//获取当前日期所在年的最后一天
public static DateTime GetLastDayDateTimeOfYear(this DateTime dateTime)
{
    return new DateTime(dateTime.Year, 12, 31, 0, 0, 0, 0, DateTimeKind.Local);
}

稍晚些时候我会把库上传至Nuget,大家可以直接使用Ideal.Core.Common。


:测试方法代码以及示例源码都已经上传至代码库,有兴趣的可以看看。
https://gitee.com/hugogoos/Ideal

标签: none

添加新评论