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

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. zabbix 二次开发(添加menu)

    zabbix 二次开发--- 在zabbix菜单栏中增加 CMDB 菜单,该菜单下有个子栏目 CMDB overview,如图: 实现此效果,我们需要修改两个地方:menu.inc.php 和 mai ...

  2. CDH添加es服务

    地址:https://blog.csdn.net/guoliduo/article/details/105072857 注意:目前只支持cdh5.x的版本安装es,cdh6.x暂不支持.

  3. 调用微信红包接口,本地可以服务器不可以。 请求被中止: 未能创建 SSL/TLS 安全通道

    微信红包的地址接口地址是: https://api.mch.weixin.qq.com/pay/micropay 当时造成这个不能用的原因是:我把服务器从windows server 2008升级到w ...

  4. python 浅拷贝与深拷贝

    赋值引用 >>> a= {1:[1,2]}>>> b = a>>> b[2]=3>>> b {1: [1, 2], 2: 3} ...

  5. div中多行内容垂直居中显示

    div中多行内容垂直居中显示 一.css 样式 .wrap { height: 200px; width: 200px; border: 1px solid #232323; display: fle ...

  6. web前端常用的五种方式搭建本地静态html页面服务器

    方式一:live-server live-server是一款npm工具,可以在项目目录启动一个node服务,然后直接在浏览器中预览,并且自动全局监听实时更新. 两种安装方式: 全局安装 npm i l ...

  7. Linux下Shell脚本实现统一管理服务启停重启

    公司今年开始了大批量的裁员,人心惶惶,所以强迫自己学习点新知识,刚好领导给找了个事情,让写个脚本实现一键启停Linux服务器上的服务,于是开始研究这个怎么搞. 最开始的时候,有点想当然了,觉得一键启停 ...

  8. CSS & JS Effect – Hero Banner Swiper

    效果 重点 1. 一张图片, 一个 content 定位居中作为一个 slide 2. slider 用了 JavaScript Library – Swiper 3. 当 slide active ...

  9. Asp.net Core – CSS Isolation

    前言 ASP.NET Core 6.0 Razor Pages 新功能, 我是用 webpack 做打包的, 所以这个对我没有什么帮助. 但是了解一下是可以的. 希望 .NET 会继续发展的更好, 多 ...

  10. go语言中变量的作用域

    Go 语言中的变量作用域规则决定了变量在程序的哪些部分是可见的和可以访问的.理解这些规则对于编写清晰.维护性高的代码非常重要.下面是一个系统性的解释. 变量的作用域类型 包级作用域: 包级作用域的变量 ...