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

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. 推荐2款实用的持续集成与部署(CI&CD)自动化工具

    前言 最近DotNetGuide技术社区交流群有不少同学在咨询:持续集成与部署(CI&CD)自动化工具有什么好用的推荐?今天大姚给大家推荐2款实用且免费的持续集成与部署(CI&CD)自 ...

  2. 【测试平台开发】——06Flask后端api开发实战(三)——API接口关联数据库

    本章节演示如何创建接口服务,用接口关联数据库数据,包括get请求和post请求. 一.Flask-RESTful插件 restful api是用于在前端与后台进行通信的一套规范.使用这个规范可以让前后 ...

  3. pyspark 数据类型及转换

    spark 有哪些数据类型 https://spark.apache.org/docs/latest/sql-reference.html Spark 数据类型 Data Types Spark SQ ...

  4. ES7学习笔记(二)ES的集群原理

    发现 发现是节点之间彼此发现,形成集群的一个过程.这个过程发生的场景有很多,比如:你启动了一个集群节点,或者一个节点确认主节点已经挂掉了,或者一个新的主节点被选举了. 咱们在配置集群的时候在配置文件中 ...

  5. shell脚本字符串截取方法整理

    首先先声明一个变量str,下面演示以该变量为例: str='https://www.baidu.com/about.html' 1.#号截取,删除左边字符,保留右边字符 echo ${str#*//} ...

  6. HTML & CSS – Practice Projects

    前言 学完了 w3school 就要练练手了. 这篇是记入我学习的过程, 和知识点. update: 2022-02-27 用文章来表达太难了, 用视频比较合理. 所以我就没有继续写了. 这里记入几篇 ...

  7. Java SE 23 新增特性

    Java SE 23 新增特性 作者:Grey 原文地址: 博客园:Java SE 23 新增特性 CSDN:Java SE 23 新增特性 源码 源仓库: Github:java_new_featu ...

  8. Parquet.Net: 将 Apache Parquet 移植到 .NET

    Parquet.Net 是一个用于读取和写入 Apache Parquet 文件的纯 .NET 库,使用MIT协议开源,github仓库:https://github.com/aloneguid/pa ...

  9. 5G网元功能与接口

    5G网元功能与接口 5G移动通信整体网络架构 5G网络功能之间的信息交互可以基于两种方式表示:其一为基于服务表示:其二为基于点对点表示.实时部署时,也可以采用两种方式相结合的表示方式. 并不是所有的接 ...

  10. [OI] 平衡树

    1. 二叉查找树 二叉查找树的思想和优先队列比较像,都是把若干个数据按一定规则插到一棵树里,然后就可以维护特定的信息. 在优先队列的大根堆实现里,我们让每棵子树的根节点都大于它的儿子,这样就可以保证根 ...