開源 - Ideal庫 - 特殊時間擴充套件方法(三)

IT规划师發表於2024-11-11

書接上回,我們繼續來分享一些關於特殊時間獲取的常用擴充套件方法。

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

相關文章