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

01、获取当前日期所在月的第一个指定星期几

该方法和前面介绍的获取当前日期所在周的第一天(周一)核心思想是一样的,只是把求周一改成求周几而已,当然其中有些小细节需要注意,比如求所在周的第一天则两天都在同一周,而求所在月第一个指定周则可能两天在不同周,具体代码如下:

//获取当前日期所在月的第一个指定星期几
public static DateTime GetFirstDayOfWeekDateTimeInMonth(this DateTime dateTime, DayOfWeek dayOfWeek)
{
//获取当前日期所在月的第一天
var firstDayOfMonth = dateTime.GetFirstDayDateTimeOfMonth();
//计算目标日期与当月第一天相差天数
var diff = ((int)dayOfWeek - (int)firstDayOfMonth.DayOfWeek + 7) % 7;
return firstDayOfMonth.AddDays(diff);
}

下面我们还需要做详细的单元测试,我们分别测试指定周一和周日两个特殊日期,然后再分别测试三种特殊情况:

指定周一测试:

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

(2) 验证当前日期是本月第一个周一的情况;

(3) 验证当前日期是周日,并且在本月第一个周一之后的情况;

指定周日测试:

(1) 验证当前日期是周五,并且在本月第一个周日之前的情况;

(2) 验证当前日期是本月第一个周日的情况;

(3) 验证当前日期是周一,并且在本月第一个周日之后的情况;

具体代码如下:

[Fact]
public void GetFirstDayOfWeekDateTimeInMonth()
{
//验证当前日期是周五,而周一在下一周的情况
var friday_monday = new DateTime(2024, 11, 1, 14, 10, 10);
var day_friday_monday = friday_monday.GetFirstDayOfWeekDateTimeInMonth(DayOfWeek.Monday);
Assert.Equal(new DateTime(2024, 11, 4), day_friday_monday);
//验证当前日期是本月第一个周一的情况
var monday_monday = new DateTime(2024, 11, 4, 4, 10, 10);
var day_monday_monday = monday_monday.GetFirstDayOfWeekDateTimeInMonth(DayOfWeek.Monday);
Assert.Equal(new DateTime(2024, 11, 4), day_monday_monday);
//验证当前日期是周日,并且在本月第一个周一之后的情况
var sunday_monday = new DateTime(2024, 11, 30, 4, 10, 10);
var day_sunday_monday = sunday_monday.GetFirstDayOfWeekDateTimeInMonth(DayOfWeek.Monday);
Assert.Equal(new DateTime(2024, 11, 4), day_sunday_monday);
//验证当前日期是周五,并且在本月第一个周日之前的情况
var friday_sunday = new DateTime(2024, 11, 1, 14, 10, 10);
var day_friday_sunday = friday_sunday.GetFirstDayOfWeekDateTimeInMonth(DayOfWeek.Sunday);
Assert.Equal(new DateTime(2024, 11, 3), day_friday_sunday);
//验证当前日期是本月第一个周日的情况
var sunday_sunday = new DateTime(2024, 11, 30, 4, 10, 10);
var day_sunday_sunday = sunday_sunday.GetFirstDayOfWeekDateTimeInMonth(DayOfWeek.Sunday);
Assert.Equal(new DateTime(2024, 11, 3), day_sunday_sunday);
//验证当前日期是周一,并且在本月第一个周日之后的情况
var monday_sunday = new DateTime(2024, 11, 4, 4, 10, 10);
var day_monday_sunday = monday_sunday.GetFirstDayOfWeekDateTimeInMonth(DayOfWeek.Sunday);
Assert.Equal(new DateTime(2024, 11, 3), day_monday_sunday);
}

02、获取当前日期所在月的最后一个指定星期几

该方法和上一个求第一个指定星期几核心思想是一样的,具体代码如下:

//获取当前日期所在月的最后一个指定星期几
public static DateTime GetLastDayOfWeekDateTimeInMonth(this DateTime dateTime, DayOfWeek dayOfWeek)
{
//获取当前日期所在月的最后一天
var lastDayOfMonth = dateTime.GetLastDayDateTimeOfMonth();
//计算目标日期与当月最后一天相差天数
var diff = ((int)lastDayOfMonth.DayOfWeek - (int)dayOfWeek + 7) % 7;
return lastDayOfMonth.AddDays(-diff);
}

单元测试可以参考求第一个指定星期几,这里就不赘述了。

03、获取当前日期上一个指定星期几

求上一个指定周几,其实也不复杂,首先计算出当前日期与目标星期几相差的天数,其中有个小细节需要注意,就是如果两个日期相同,则需要把相差天数改为7,具体代码如下:

//获取当前日期上一个指定星期几
public static DateTime GetPreviousDayDateTimeOfWeek(this DateTime dateTime, DayOfWeek dayOfWeek)
{
//计算当前日期与目标星期几相差天数
var diff = ((int)dateTime.DayOfWeek - (int)dayOfWeek + 7) % 7;
//如果相差0天表示当前日期和目标星期几相同,需要改为7
diff = diff == 0 ? 7 : diff;
return dateTime.AddDays(-diff).Date;
}

我们分别对以下四种情况做单元测试:

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

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

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

(4) 验证当前日期是周六,并且是当月最后一天的情况;

具体代码如下:

[Fact]
public void GetPreviousDayDateTimeOfWeek()
{
//验证当前日期是周一,而上一个周一在上一月的情况
var monday = new DateTime(2024, 11, 1, 14, 10, 10);
var day_monday = monday.GetPreviousDayDateTimeOfWeek(DayOfWeek.Monday);
Assert.Equal(new DateTime(2024, 10, 28), day_monday);
//验证当前日期是周一,而上一个周一在当月的情况
var monday1 = new DateTime(2024, 11, 25, 14, 10, 10);
var day_monday1 = monday1.GetPreviousDayDateTimeOfWeek(DayOfWeek.Monday);
Assert.Equal(new DateTime(2024, 11, 18), day_monday1);
//验证当前日期是周日,而上一个周一在当月的情况
var sunday = new DateTime(2024, 11, 24, 4, 10, 10);
var day_sunday = sunday.GetPreviousDayDateTimeOfWeek(DayOfWeek.Monday);
Assert.Equal(new DateTime(2024, 11, 18), day_sunday);
//验证当前日期是周六,并且是当月最后一天的情况
var saturday = new DateTime(2024, 11, 30, 4, 10, 10);
var day_saturday = saturday.GetPreviousDayDateTimeOfWeek(DayOfWeek.Monday);
Assert.Equal(new DateTime(2024, 11, 25), day_saturday);
}

04、获取当前日期下一个指定星期几

该方法和上面获取上一个指定星期几核心思想相同,具体代码如下:

//获取当前日期下一个最近指定星期几
public static DateTime GetNextDayDateTimeOfWeek(this DateTime dateTime, DayOfWeek dayOfWeek)
{
//计算目标日期与当月最后一天相差天数
var diff = ((int)dayOfWeek - (int)dateTime.DayOfWeek + 7) % 7;
//如果相差0天表示当前日期和目标星期几相同,需要改为7
diff = diff == 0 ? 7 : diff;
return dateTime.AddDays(diff).Date;
}

单元测试也可以参考求上一个指定星期几,这里就不再赘述了。

05、获取当前日期是其所在月的第几周

该方法的核心思想是,获取当前日期和当月第一天相差多少天,然后用相差的天数除以7即可获得当前是第几周。

但是这里有个比较麻烦的事情是如果第一周不满一周呢,比如当月的第一周第一天是2024-11-01周五,而今天是2024-11-07周四,应该是当月的第二周,但是如果直接计算两天的差再除以7结果显然是不对的。

因此我们首先需要把第一周不满一周的天数补上,即前面还有4天。

如此就是(7+4)/7=1…4,即所在第二周,其中商表示完整的周,余数则表示不完整的周。如果转为公式则为:days/7 + (days%7 > 0 ? 1 : 0),我们对这个公式简化后得到:(days + 6)/7,具体实现代码如下:

//获取当前日期是其所在月的第几周
public static int GetWeekOfMonth(this DateTime dateTime)
{
//获取当前日期所在月的第一天
var firstDayOfMonth = dateTime.GetFirstDayDateTimeOfMonth();
//首先设定周一为一周的开始
//计算当前月第一天与周一相差天数
//即第一周如果不满一周还差多少天
var diff = ((int)firstDayOfMonth.DayOfWeek - (int)DayOfWeek.Monday + 7) % 7;
//用第一周不满的差值加上当前日期的天数之和计算当前为当月第几周
//然后计算 总天数/7的商,如果有余数则再加1
//公式为:n/7 + (n%7 > 0 ? 1 : 0)
//上面公式可以简化为 (n+6)/7
return (diff + dateTime.Day + 6) / 7;
}

下面我们对其进行以下几种情况详细的单元测试:

(1) 验证当前日期是周五,且是当月第一天的情况;

(2) 验证当前日期是周日,且在当月第一周的情况;

(3) 验证当前日期是周一,且在当月第三周的情况;

(4) 验证当前日期是周日,且在当月第三周的情况;

(5) 验证当前日期是周六,且是当月最后一天的情况;

具体代码如下:

[Fact]
public void GetWeekOfMonth()
{
//验证当前日期是周五,且是当月第一天的情况
var friday = new DateTime(2024, 11, 1, 14, 10, 10);
var day_friday = friday.GetWeekOfMonth();
Assert.Equal(1, day_friday);
//验证当前日期是周日,且在当月第一周的情况
var sunday = new DateTime(2024, 11, 3, 14, 10, 10);
var day_sunday = sunday.GetWeekOfMonth();
Assert.Equal(1, day_sunday);
//验证当前日期是周一,且在当月第三周的情况
var monday = new DateTime(2024, 11, 11, 4, 10, 10);
var day_monday = monday.GetWeekOfMonth();
Assert.Equal(3, day_monday);
//验证当前日期是周日,且在当月第三周的情况
var date17 = new DateTime(2024, 11, 17, 4, 10, 10);
var day17 = date17.GetWeekOfMonth();
Assert.Equal(3, day17);
//验证当前日期是周六,且是当月最后一天的情况
var sunday1 = new DateTime(2024, 11, 30, 4, 10, 10);
var day_sunday1 = sunday1.GetWeekOfMonth();
Assert.Equal(5, day_sunday1);
}

06、获取当前日期是其所在年的第几周(ISO 8601 标准)

在ISO 8601 标准规定中,每周从星期一开始,且每年最少有 52 周,每年的第一周是包含该年第一天的那一周,且该周必须至少有四天。

获取当然日期所在年的第几周可以通过调用C#中文化信息中日历组件中GetWeekOfYear方法,具体代码如下:

//获取当前日期是其所在年的第几周(ISO 8601 标准)
public static int GetWeekOfYear(this DateTime dateTime)
{
var currentCulture = CultureInfo.CurrentCulture;
return currentCulture.Calendar.GetWeekOfYear(dateTime, currentCulture.DateTimeFormat.CalendarWeekRule, currentCulture.DateTimeFormat.FirstDayOfWeek);
}

07、获取当前日期所在月份的周数

该方法实现的核心思想是首先获取当前日期所在月份的第一天和最后一天,然后分别计算其所在当年第几周,最后相减即可得到,具体代码如下:

//获取当前日期所在月份的周数
public static int GetWeeksInMonth(this DateTime dateTime)
{
//获取当前日期所在月的第一天
var firstDayOfMonth = dateTime.GetFirstDayDateTimeOfMonth();
//获取当前日期所在月的最后一天
var lastDayOfMonth = dateTime.GetLastDayDateTimeOfMonth();
//获取当月第一天在全年中的周数
var firstWeek = firstDayOfMonth.GetWeekOfYear();
//获取当月最后一天在全年中的周数
var lastWeek = lastDayOfMonth.GetWeekOfYear();
return lastWeek - firstWeek + 1;
}

08、判断当前日期是否是周末

该方法比较简单,只是判断当前是否是否为周六或周日,具体代码如下:

//判断当前日期是否是周末
public static bool IsWeekend(this DateTime dateTime)
{
return dateTime.DayOfWeek == DayOfWeek.Saturday || dateTime.DayOfWeek == DayOfWeek.Sunday;
}

09、判断当前日期所在年是否是闰年

该方法调用了C#内置方法IsLeapYear,具体代码如下:

//判断当前日期所在年是否是闰年
public static bool IsLeapYear(this DateTime dateTime)
{
return DateTime.IsLeapYear(dateTime.Year);
}

10、获取当前日期所在季度

该方法也比较简单,只需要应用一个小公式即可求的,具体代码如下:

//获取当前日期所在季度
public static int GetQuarter(this DateTime dateTime)
{
return (dateTime.Month - 1) / 3 + 1;
}

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

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

开源 - Ideal库 -获取特殊时间扩展方法(四)的更多相关文章

  1. C++11新特性,利用std::chrono精简传统获取系统时间的方法

    一.传统的获取系统时间的方法 传统的C++获取时间的方法须要分平台来定义. 相信百度代码也不少. 我自己写了下,例如以下. const std::string getCurrentSystemTime ...

  2. Rails时间扩展方法

    1.时间扩展方法: beginning_of_day,end_of_day等等 Time.now.end_of_day 2.ruby类型判断 is_a?(类型) 如:b.is_a?(Array)

  3. JS简单获取当前日期时间的方法(yyyy-MM-dd hh:mm:ss)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...

  4. C/C++获取本地时间常见方法

    跨平台方法 方法一:手动暴力法 #include <iostream> using namespace std; #include <time.h> time_t t = ti ...

  5. C# 如何获取日期时间各种方法

    我们可以通过使用DataTime这个类来获取当前的时间.通过调用类中的各种方法我们可以获取不同的时间:如:日期(2019-01-09).时间(16:02:12).日期+时间(2019-01-09 16 ...

  6. 使用 jquery 获取当前时间的方法

    我们在写一些效果时,经常要用到 jquery 获取当前时间,但是jquery 目前并没有提供直接获取当前时间的 api 或者函数,所以我们还是得用原生的 javascript 时间对象 Date 来获 ...

  7. [置顶] 获取系统时间的方法--linux

    一. localtime 函数获取(年/月/日/时/分/秒)数值. 1.感性认识 #include<time.h>     //C语言的头文件 #include<stdio.h> ...

  8. php获取当前时间的方法

    1.获取当前时间 date('Y-m-d H:i:s', time())   2.字符串转时间 date('Y-m-d H:i:s',strtotime('2018-8-21 22:00:00'))

  9. 开源且功能强大的C# 扩展方法类库Pure.Ext,包含1000+个拓展方法 (支持.Net Framework和.Net Core)

    先上地址 Github: https://github.com/purestackorg/pure.ext Gitee: https://gitee.com/purestack/pure.ext 扩展 ...

  10. C#获取获取北京时间多种方法

    #region 获取网络时间 ///<summary> /// 获取中国国家授时中心网络服务器时间发布的当前时间 ///</summary> ///<returns> ...

随机推荐

  1. JavaScript设计模式样例二十 —— 中介者模式

    中介者模式(Mediator Pattern) 定义:用来降低多个对象和类之间的通信复杂性.目的:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独 ...

  2. WM_CONTEXTMENU

    通知用户希望显示上下文菜单的窗口. 用户可能已在窗口中单击鼠标右键 (右键单击) .按 Shift+F10 或按应用程序键 (上下文菜单键) 某些键盘上可用 #define WM_CONTEXTMEN ...

  3. 学习设计微服务:api认证

    前言最近再学习微服务,所以把自己的个人站点https://www.ttblog.site/拆分成微服务.目前正在思考微服务里面的认证与授权,网上百度到都是根据用户名和密码来实现的,考虑到实际的原因,我 ...

  4. OpenTelemetry 实战:从零实现应用指标监控

    前言 在上一篇文章:OpenTelemetry 实战:从零实现分布式链路追踪讲解了链路相关的实战,本次我们继续跟进如何使用 OpenTelemetry 集成 metrics 监控. 建议对指标监控不太 ...

  5. 通过DashScope API调用将多种模态转换为向量

    本文介绍如何通过模型服务灵积DashScope进行 多模态向量生成 ,并入库至向量检索服务DashVector中进行向量检索. 模型服务灵积DashScope,通过灵活.易用的模型API服务,让各种模 ...

  6. 详解JVM 内存结构与实战调优总结

    详解JVM 内存结构与实战调优总结 GC优化案例做个总结: 1在进行GC优化之前,需要确认项目的架构和代码等已经没有优化空间.我们不能指望一个系统架构有缺陷或者代码层次优化没有穷尽的应用,通过GC优化 ...

  7. OData – 大杂烩

    前言 本篇记入一些 OData 的小东西. Query string too long OData 使用 GET 请求,然后搭配 query string $filter, $select, $exp ...

  8. TypeScript – Get Started

    前言 我学 TypeScript 的时候是 Angular 2.0 beta 的年代... 现在 Angular 都快 14 了. 但由于已经有 1 年半没有写 Angular 和 TypeScrip ...

  9. SQL Server 冗余维护

    介绍 冗余是维护的魔鬼, 是性能优化的天使 常见的冗余有 1. computed column 2. principal 的识别字段 3. cross computed 4. cascade soft ...

  10. tailwindcss 经验

    树摇时扫描的文件范围 根据 tailwindcss.config.js 中 content 的配置,跟打包软件加载的模块无关.即未使用的模块中的 class 也会被包含进来.