开源 - Ideal库 - 常用时间转换扩展方法

开源 - Ideal库 - 常用时间转换扩展方法(一)

从事软件开发这么多年,平时也积累了一些方便自己快速开发的帮助类,一直在想着以什么方式分享出来,因此有了这个系列文章,后面我将以《开源-Ideal库》系列文章分享一些我认为比较成熟、比较方便、比较好的代码,如果感觉有借鉴的地方可以集成到自己的公共代码库中,同时我也会以Nuget包的方式发布出来,以供直接下载使用。

主要包括:公共、文档、ORM、SqlSugar、定时任务、Redis、Mqtt、SignalR等库封装,后面可能还会适当删减。

今天我们将分享公共库中关于时间转换的相关封装,主要是关于本地与UTC的日期、时间与时间戳和字符串之间的相互转换。

01、日期时间转时间戳(秒)

该方法是把日期时间DateTime转成10位时间戳,即秒级时间戳,代码如下:

/// <summary>
/// 日期时间转时间戳(秒)
/// </summary>
/// <param name="dateTime">日期时间</param>
/// <returns>时间戳(秒)</returns>
public static long ToUnixTimestampBySeconds(this DateTime dateTime)
{
    var dto = new DateTimeOffset(dateTime);
    return dto.ToUnixTimeSeconds();
}

02、日期时间转时间戳(毫秒)

该方法是把日期时间DateTime转为13位时间戳,即毫秒级时间戳,代码如下:

/// <summary>
/// 日期时间转时间戳(毫秒)
/// </summary> 
/// <param name="dateTime">日期时间</param>
/// <returns>时间戳(毫秒)</returns>
public static long ToUnixTimestampByMilliseconds(this DateTime dateTime)
{
    var dto = new DateTimeOffset(dateTime);
    return dto.ToUnixTimeMilliseconds();
}

03、时间戳(秒)转本地日期时间

该方法是把10位秒级时间戳转为本地日期时间DateTime,代码如下:

/// <summary>
/// 时间戳(秒)转本地日期时间
/// </summary>
/// <param name="timestamp">时间戳(秒)</param>
/// <returns>本地日期时间</returns>
public static DateTime ToLocalTimeDateTimeBySeconds(this long timestamp)
{
    var dto = DateTimeOffset.FromUnixTimeSeconds(timestamp);
    return dto.ToLocalTime().DateTime;
}

04、时间戳(毫秒)转本地日期时间

该方法是把13位毫秒级时间戳转为本地日期时间DateTime,代码如下:

/// <summary>
/// 时间戳(毫秒)转本地日期时间
/// </summary> 
/// <param name="timestamp">时间戳(毫秒)</param>
/// <returns>本地日期时间</returns>
public static DateTime ToLocalTimeDateTimeByMilliseconds(this long timestamp)
{
    var dto = DateTimeOffset.FromUnixTimeMilliseconds(timestamp);
    return dto.ToLocalTime().DateTime;
}

05、时间戳(秒)转UTC日期时间

该方法是把10位秒级时间戳转为UTC日期时间DateTime,代码如下:

/// <summary>
/// 时间戳(秒)转UTC日期时间
/// </summary> 
/// <param name="timestamp">时间戳(秒)</param>
/// <returns>UTC日期时间</returns>
public static DateTime ToUniversalTimeDateTimeBySeconds(this long timestamp)
{
    var dto = DateTimeOffset.FromUnixTimeSeconds(timestamp);
    return dto.ToUniversalTime().DateTime;
}

06、时间戳(毫秒)转UTC日期时间

该方法是把13位毫秒级时间戳转为UTC日期时间DateTime,代码如下:

/// <summary>
/// 时间戳(毫秒)转UTC日期时间
/// </summary> 
/// <param name="timestamp">时间戳(毫秒)</param>
/// <returns>UTC日期时间</returns>
public static DateTime ToUniversalTimeDateTimeByMilliseconds(this long timestamp)
{
    var dto = DateTimeOffset.FromUnixTimeMilliseconds(timestamp);
    return dto.ToUniversalTime().DateTime;
}

07、时间戳(秒)转本地日期

该方法是把10位秒级时间戳转为本地日期DateOnly,代码如下:

/// <summary>
/// 时间戳(秒)转本地日期
/// </summary> 
/// <param name="timestamp">时间戳(秒)</param>
/// <returns>本地日期</returns>
public static DateOnly ToLocalTimeDateBySeconds(this long timestamp)
{
    var dt = timestamp.ToLocalTimeDateTimeBySeconds();
    return DateOnly.FromDateTime(dt);
}

08、时间戳(毫秒)转本地日期

该方法是把13位毫秒级时间戳转为本地日期DateOnly,代码如下:

/// <summary>
/// 时间戳(毫秒)转本地日期
/// </summary> 
/// <param name="timestamp">时间戳(毫秒)</param>
/// <returns>本地日期</returns>
public static DateOnly ToLocalTimeDateByMilliseconds(this long timestamp)
{
    var dt = timestamp.ToLocalTimeDateTimeByMilliseconds();
    return DateOnly.FromDateTime(dt);
}

09、时间戳(秒)转UTC日期

该方法是把10位秒级时间戳转为UTC日期DateOnly,代码如下:

/// <summary>
/// 时间戳(秒)转UTC日期
/// </summary> 
/// <param name="timestamp">时间戳(秒)</param>
/// <returns>UTC日期</returns>
public static DateOnly ToUniversalTimeDateBySeconds(this long timestamp)
{
    var dt = timestamp.ToUniversalTimeDateTimeBySeconds();
    return DateOnly.FromDateTime(dt);
}

10、时间戳(毫秒)转UTC日期

该方法是把13位毫秒级时间戳转为UTC日期DateOnly,代码如下:

/// <summary>
/// 时间戳(毫秒)转UTC日期
/// </summary> 
/// <param name="timestamp">时间戳(毫秒)</param>
/// <returns>UTC日期</returns>
public static DateOnly ToUniversalTimeDateByMilliseconds(this long timestamp)
{
    var dt = timestamp.ToUniversalTimeDateTimeByMilliseconds();
    return DateOnly.FromDateTime(dt);
}

11、时间戳(秒)转本地时间

该方法是把10位秒级时间戳转为本地时间TimeOnly,代码如下:

/// <summary>
/// 时间戳(秒)转本地时间
/// </summary> 
/// <param name="timestamp">时间戳(秒)</param>
/// <returns>本地时间</returns>
public static TimeOnly ToLocalTimeTimeBySeconds(this long timestamp)
{
    var dt = timestamp.ToLocalTimeDateTimeBySeconds();
    return TimeOnly.FromDateTime(dt);
}

12、时间戳(毫秒)转本地时间

该方法是把13位毫秒级时间戳转为本地时间TimeOnly,代码如下:

/// <summary>
/// 时间戳(毫秒)转本地时间
/// </summary> 
/// <param name="timestamp">时间戳(毫秒)</param>
/// <returns>本地时间</returns>
public static TimeOnly ToLocalTimeTimeByMilliseconds(this long timestamp)
{
    var dt = timestamp.ToLocalTimeDateTimeByMilliseconds();
    return TimeOnly.FromDateTime(dt);
}

13、时间戳(秒)转UTC时间

该方法是把10位秒级时间戳转为UTC时间TimeOnly,代码如下:

/// <summary>
/// 时间戳(秒)转UTC时间
/// </summary> 
/// <param name="timestamp">时间戳(秒)</param>
/// <returns>UTC时间</returns>
public static TimeOnly ToUniversalTimeTimeBySeconds(this long timestamp)
{
    var dt = timestamp.ToUniversalTimeDateTimeBySeconds();
    return TimeOnly.FromDateTime(dt);
}

14、时间戳(毫秒)转UTC时间

该方法是把13位毫秒级时间戳转为UTC时间TimeOnly,代码如下:

/// <summary>
/// 时间戳(毫秒)转UTC时间
/// </summary> 
/// <param name="timestamp">时间戳(毫秒)</param>
/// <returns>UTC时间</returns>
public static TimeOnly ToUniversalTimeTimeByMilliseconds(this long timestamp)
{
    var dt = timestamp.ToUniversalTimeDateTimeByMilliseconds();
    return TimeOnly.FromDateTime(dt);
}

15、字符串转日期时间,转换失败则返回空

该方法是把字符串转为日期时间DateTime,转换失败则返回空,具体代码如下:

/// <summary>
/// 字符串转日期时间,转换失败则返回空
/// </summary>
/// <param name="source">需转换的字符串</param>
/// <returns>日期时间</returns>
public static DateTime? ToDateTime(this string source)
{
    if (DateTime.TryParse(source, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date))
    {
        return date;
    }
    return default;
}

16、字符串转日期时间,转换失败则返回默认日期时间

该方法是把字符串转为日期时间DateTime,转换失败则返回默认日期时间,具体代码如下:

/// <summary>
/// 字符串转日期时间,转换失败则返回默认值
/// </summary>
/// <param name="source">需转换的字符串</param>
/// <param name="dateTime">默认日期时间</param>
/// <returns>日期时间</returns>
public static DateTime ToDateTimeOrDefault(this string source, DateTime dateTime)
{
    if (DateTime.TryParse(source, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date))
    {
        return date;
    }
    return dateTime;
}

17、字符串转日期,转换失败则返回空

该方法是把字符串转为日期DateOnly,转换失败则返回空,具体代码如下:

/// <summary>
/// 字符串转日期,转换失败则返回空
/// </summary>
/// <param name="source">需转换的字符串</param>
/// <returns>日期</returns>
public static DateOnly? ToDateOnly(this string source)
{
    if (DateOnly.TryParse(source, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date))
    {
        return date;
    }
    return default;
}

18、字符串转日期,转换失败则返回默认日期

该方法是把字符串转为日期DateOnly,转换失败则返回默日期,具体代码如下:

/// <summary>
/// 字符串转日期,转换失败则返回默认日期
/// </summary>
/// <param name="source">需转换的字符串</param>
/// <param name="dateOnly">默认日期</param>
/// <returns>日期</returns>
public static DateOnly ToDateOnlyOrDefault(this string source, DateOnly dateOnly)
{
    if (DateOnly.TryParse(source, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date))
    {
        return date;
    }
    return dateOnly;
}

19、字符串转时间,转换失败则返回空

该方法是把字符串转为日期TimeOnly,转换失败则返回空,具体代码如下:

/// <summary>
/// 字符串转时间,转换失败则返回空
/// </summary>
/// <param name="source">需转换的字符串</param>
/// <returns>时间</returns>
public static TimeOnly? ToTimeOnly(this string source)
{
    if (TimeOnly.TryParse(source, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date))
    {
        return date;
    }
    return default;
}

20、字符串转时间,转换失败则返回默认时间

该方法是把字符串转为日期TimeOnly,转换失败则返回默认时间,具体代码如下:

/// <summary>
/// 字符串转时间,转换失败则返回默认时间
/// </summary>
/// <param name="source">需转换的字符串</param>
/// <param name="timeOnly">默认时间</param>
/// <returns>时间</returns>
public static TimeOnly ToTimeOnlyOrDefault(this string source, TimeOnly timeOnly)
{
    if (TimeOnly.TryParse(source, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date))
    {
        return date;
    }
    return timeOnly;
}

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

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

 

2024-11-11 09:14:26【出处】:https://www.cnblogs.com/hugogoos/p/18531206

=======================================================================================

开源 - Ideal库 - 常用时间转换扩展方法(二)

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

01、时间转日期时间 TimeOnly

该方式是把TimeOnly类型转为DateTime类型,其中日期部分使用系统当前日期,时间部分则使用TimeOnly,具体代码如下:

//时间转日期时间,默认使用当前日期+时间转为日期时间格式
public static DateTime ToDateTime(this TimeOnly timeOnly)
{
    return DateOnly.FromDateTime(DateTime.Now).ToDateTime(timeOnly);
}

02、日期+时间转为日期时间 TimeOnly

该方法是直接对TimeOnly时间进行扩展,取用其时间,然后补全指定DateOnly日期,最后转为DateTime,代码如下:

//日期+时间转为日期时间
public static DateTime ToDateTime(this TimeOnly timeOnly, DateOnly dateOnly)
{
    return dateOnly.ToDateTime(timeOnly);
}

03、日期时间中日期部分+时间转日期时间 TimeOnly

该方法是对TimeOnly时间进行扩展,取其时间,然后补全指定DateTime中的日期部分,最后再转为DateTime,代码如下:

//日期时间中日期部分+时间转日期时间格式
public static DateTime ToDateTime(this TimeOnly timeOnly, DateTime dateTime)
{
    return DateOnly.FromDateTime(dateTime).ToDateTime(timeOnly);
}

04、日期转日期时间 DateOnly

该方式是把DateOnly类型转为DateTime类型,其中日期部分使用DateOnly,时间部分则使用系统当前时间,具体代码如下:

//日期转日期时间,日期+默认使用当前时间转为日期时间格式
public static DateTime ToDateTime(this DateOnly dateOnly)
{
    return dateOnly.ToDateTime(TimeOnly.FromDateTime(DateTime.Now));
}

05、日期+日期时间中时间部分转日期时间 DateOnly

该方法是对DateOnly日期进行扩展,取其日期,然后补全指定DateTime中的时间部分,最后再转为DateTime,代码如下:

//日期+日期时间中时间部分转日期时间
public static DateTime ToDateTime(this DateOnly dateOnly, DateTime dateTime)
{
    return dateOnly.ToDateTime(TimeOnly.FromDateTime(dateTime));
}

06、日期时间中日期部分+时间转日期时间 DateTime

该方法是对DateTime日期时间进行扩展,取其日期部分,然后补全指定TimeOnly时间,最后再转为DateTime,代码如下:

//日期时间中日期部分+时间转日期时间
public static DateTime ToDateTime(this DateTime dateTime, TimeOnly timeOnly)
{
    return DateOnly.FromDateTime(dateTime).ToDateTime(timeOnly);
}

07、日期+日期时间中时间部分转为日期时间 DateTime

该方法是对DateTime日期时间进行扩展,取其时间部分,然后补全指定DateOnly日期,最后再转为DateTime,代码如下:

//日期+日期时间中时间部分转为日期时间
public static DateTime ToDateTime(this DateTime dateTime, DateOnly dateOnly)
{
    return dateOnly.ToDateTime(TimeOnly.FromDateTime(dateTime));
}

08、日期时间转日期 DateTime

该方法是对DateTime日期时间进行扩展,取其日期部分转为DateOnly,代码如下:

//日期时间转日期,保留日期时间中日期部分
public static DateOnly ToDateOnly(this DateTime dateTime)
{
    return DateOnly.FromDateTime(dateTime);
}

09、日期时间转时间 DateTime

该方法是对DateTime日期时间进行扩展,取其时间部分转为TimeOnly,代码如下:

//日期时间转时间,保留日期时间中时间部分
public static TimeOnly ToTimeOnly(this DateTime dateTime)
{
    return TimeOnly.FromDateTime(dateTime);
}

上面的这些扩展方法虽然大多都是简单调用原生方法,但是通过扩展方法方式提供出来后的确在编码上提升了一些效率,代码也会根据简洁。

10、代码结构设计与组织

代码结构的设计和组织是软件开发过程中重要的一环,它将直接影响代码的可读性、可维护性、扩展性、测试性和团队协作的效率。

到目前为止我们关于时间的扩展方法已经有接近30个方法了,后面还有很多,目前都是放在DateTimeExtension类下面,如下图:

到这里已经能感受到代码结构显得很混乱了,直观感觉就是可读性差,没有结构化必然会导致扩展困难。

可能会有人提出不同观点,这些不就是很多静态方法吗,只有排版整齐就行了,其实不然,我们可以借助一些小技巧把方法集合结构化的管理起来。

结构化的管理一种实现方式就行——分类。下面我们就对现有代码进行分类。

分类是一门技术活,如何选择分类标准很关键,比如我们这里可以根据入参类型分为针对long类型转换、针对DateTime类型转换、针对string类型转换;也可以根据功能分类比如时间和时间戳互相转换是一类,时间和字符串互相转换是一类,DateTime与DateOnly和TimeOnly互相转换是一类等等分类方式。

1、分大类

我的思路是这样的,首先通过部分类partial把DateTimeExtension根据入参类型分成几个大类。

代码整理后效果如下:

2、分小类

分完大类后发现long类型中方法还是很大,因此我们继续对其进行分类,我们根据功能不同分为两类:转为本地日期时间和转为UTC日期时间。我们可以使用代码折叠的预处理指令#region和#endregion来处理处理小分类。

代码整理以后效果如下:

从一开始一堆方法到现在结构层次已经非常清晰了,阅读起来也非常方便,后期维护扩展就可以很容易的快速找到相应地方处理。

11、单元测试

作为一个开源代码,我们首要任务应该保证代码正确性,因此单元测试是必不可少的。单元测试不但可以保证我们代码的正确性,还可以促使我们代码写的跟健壮。

单元测试我们以同样的分类方式进行代码组织,代码大致如下:

因为具体的测试用例都比较简单,这里就不拿出来讲解了。

测试用例编写的越完善,我们代码就越可靠,因此我们在编写单元测试时候,要尽可能覆盖所有逻辑,要尽可能覆盖到一些特例情况,我们想的越多代码质量才能越高。

12、文档

作为一个开源代码,还需要一个好的文档,这样别人才能轻松使用,目前文档还是缺失的,后续我将陆续添加上。

当代码结构设计与组织、单元测试、文档这三部分都做好了,我感觉这个开源代码就达到开源给别人的最低要求了。后面的开源代码我都将围绕这三部分展开,希望可以给大家分享一些高质量的开源代码。

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

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

 

2024-11-11 09:14:45【出处】:https://www.cnblogs.com/hugogoos/p/18535467

=======================================================================================

开源 - Ideal库 - 特殊时间扩展方法(三)

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

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

 

2024-11-11 09:15:09【出处】:https://www.cnblogs.com/hugogoos/p/18538819

=======================================================================================

posted on 2024-11-11 09:19  jack_Meng  阅读(7)  评论(0编辑  收藏  举报

导航