C#中的时间类
Posted 少年。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#中的时间类相关的知识,希望对你有一定的参考价值。
DateTime类
DateTime类是C#中最常用的时间类之一,它表示一个日期和时间。可以使用DateTime.Now属性获取当前时间,也可以使用DateTime.Parse方法将字符串转换为DateTime对象。
// 获取当前时间
DateTime now = DateTime.Now;
// 将字符串转换为DateTime对象
DateTime dateTime = DateTime.Parse("2022-01-01 12:00:00");
// 获取当前时间的年份
int year = now.Year;
// 获取当前时间的月份
int month = now.Month;
// 获取当前时间的日期
int day = now.Day;
// 获取当前时间的小时数
int hour = now.Hour;
// 获取当前时间的分钟数
int minute = now.Minute;
// 获取当前时间的秒数
int second = now.Second;
// 获取当前时间的毫秒数
int millisecond = now.Millisecond;
DateTime类还提供了一些常用的方法和属性,例如:
- DateTime.AddDays(double value):将当前DateTime对象的日期加上指定的天数。
- DateTime.AddHours(double value):将当前DateTime对象的时间加上指定的小时数。
- DateTime.AddMinutes(double value):将当前DateTime对象的时间加上指定的分钟数。
- DateTime.AddSeconds(double value):将当前DateTime对象的时间加上指定的秒数。
- DateTime.Year:获取当前DateTime对象的年份。
- DateTime.Month:获取当前DateTime对象的月份。
- DateTime.Day:获取当前DateTime对象的日期。
- DateTime.Hour:获取当前DateTime对象的小时数。
- DateTime.Minute:获取当前DateTime对象的分钟数。
- DateTime.Second:获取当前DateTime对象的秒数。
TimeSpan类
TimeSpan类表示时间间隔,可以用来计算两个日期之间的时间差。可以使用TimeSpan.FromDays、TimeSpan.FromHours、TimeSpan.FromMinutes、TimeSpan.FromSeconds等方法创建TimeSpan对象。
// 创建一个表示1天的TimeSpan对象
TimeSpan oneDay = TimeSpan.FromDays(1);
// 创建一个表示2小时的TimeSpan对象
TimeSpan twoHours = TimeSpan.FromHours(2);
// 创建一个表示30分钟的TimeSpan对象
TimeSpan thirtyMinutes = TimeSpan.FromMinutes(30);
// 创建一个表示10秒的TimeSpan对象
TimeSpan tenSeconds = TimeSpan.FromSeconds(10);
TimeSpan类还提供了一些常用的方法和属性,例如:
- TimeSpan.TotalDays:获取TimeSpan对象表示的总天数。
- TimeSpan.TotalHours:获取TimeSpan对象表示的总小时数。
- TimeSpan.TotalMinutes:获取TimeSpan对象表示的总分钟数。
- TimeSpan.TotalSeconds:获取TimeSpan对象表示的总秒数。
DateTimeOffset类
DateTimeOffset类表示一个日期和时间,同时包含时区信息。可以使用DateTimeOffset.Now属性获取当前时间,也可以使用DateTimeOffset.Parse方法将字符串转换为DateTimeOffset对象。
// 获取当前时间
DateTimeOffset now = DateTimeOffset.Now
// 将字符串转换为DateTimeOffset对象
DateTimeOffset dateTimeOffset = DateTimeOffset.Parse("2022-01-01 12:00:00 +08:00");
DateTimeOffset类还提供了一些常用的方法和属性,例如:
- DateTimeOffset.ToLocalTime():将当前DateTimeOffset对象转换为本地时间。
- DateTimeOffset.ToUniversalTime():将当前DateTimeOffset对象转换为协调世界时(UTC)时间。
静态类的封装
using System;
namespace ToolBox.DateTimeTool
public static class DateTimeExtend
/// <summary>
/// 获取本日开始时间(0点0分0秒)
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime GetDayStart(this DateTime dateTime)
return dateTime.Date;
/// <summary>
/// 获取本日结束时间(23点59分59秒)
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime GetDayEnd(this DateTime dateTime)
return dateTime.Date.AddDays(1).AddMilliseconds(-1);
/// <summary>
/// 获取本周开始时间
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime GetWeekStart(this DateTime dateTime)
return dateTime.AddDays(-(int)dateTime.DayOfWeek + 1).GetDayStart();
/// <summary>
/// 获取本周结束时间
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime GetWeekEnd(this DateTime dateTime)
return dateTime.AddDays(7 - (int)dateTime.DayOfWeek).GetDayEnd();
/// <summary>
/// 获取本月开始时间
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime GetMonthStart(this DateTime dateTime)
return new DateTime(dateTime.Year, dateTime.Month, 1, 0, 0, 0, 0);
/// <summary>
/// 获取本月结束时间
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime GetMonthEnd(this DateTime dateTime)
return GetMonthStart(dateTime).AddMonths(1).AddMilliseconds(-1);
/// <summary>
/// 获取本季度开始时间
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime GetSeasonStart(this DateTime dateTime)
var time = dateTime.AddMonths(0 - ((dateTime.Month - 1) % 3));
return DateTime.Parse(time.AddDays(-time.Day + 1).ToString("yyyy/MM/dd 00:00:00"));
/// <summary>
/// 获取本季度结束时间
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime GetSeasonEnd(this DateTime dateTime)
var time = dateTime.AddMonths((3 - ((dateTime.Month - 1) % 3) - 1));
return DateTime.Parse(time.AddMonths(1).AddDays(-time.AddMonths(1).Day + 1).AddDays(-1).ToString("yyyy/MM/dd 23:59:59"));
/// <summary>
/// 获取本年开始时间
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime GetYearStart(this DateTime dateTime)
return DateTime.Parse(dateTime.AddDays(-dateTime.DayOfYear + 1).ToString("yyyy/MM/dd 00:00:00"));
/// <summary>
/// 获取本年结束时间
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime GetYearEnd(this DateTime dateTime)
var time2 = dateTime.AddYears(1);
return DateTime.Parse(time2.AddDays(-time2.DayOfYear).ToString("yyyy/MM/dd 23:59:59"));
/// <summary>
/// 北京时间转换成unix时间戳(10位/秒)
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static long BeijingTimeToUnixTimeStamp10(this DateTime dateTime)
return (long)(dateTime - new DateTime(1970, 1, 1, 8, 0, 0)).TotalSeconds;
/// <summary>
/// 格林威治时间转换成unix时间戳(10位/秒)
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static long UtcTimeToUnixTimeStamp10(this DateTime dateTime)
return (long)(dateTime - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
/// <summary>
/// 北京时间转换成unix时间戳(13位/毫秒)
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static long BeijingTimeToUnixTimeStamp13(this DateTime dateTime)
return (long)(dateTime - new DateTime(1970, 1, 1, 8, 0, 0)).TotalMilliseconds;
/// <summary>
/// 格林威治时间转换成unix时间戳(13位/毫秒)
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static long UtcTimeToUnixTimeStamp13(this DateTime dateTime)
return (long)(dateTime - new DateTime(1970, 1, 1, 0, 0, 0)).TotalMilliseconds;
/// <summary>
/// 10位unix时间戳转换成北京时间
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime UnixTimeStamp10ToBeijingTime(this long unixTimeStamp)
return new DateTime(1970, 1, 1, 8, 0, 0).AddSeconds(unixTimeStamp);
/// <summary>
/// 10位unix时间戳转换成格林威治
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime UnixTimeStamp10ToUtcTime(this long unixTimeStamp)
return new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(unixTimeStamp);
/// <summary>
/// 13位unix时间戳转换成北京时间
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime UnixTimeStamp13ToBeijingTime(this long unixTimeStamp)
return new DateTime(1970, 1, 1, 8, 0, 0).AddMilliseconds(unixTimeStamp);
/// <summary>
/// 13位unix时间戳转换成格林威治
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime UnixTimeStamp13ToUtcTime(this long unixTimeStamp)
return new DateTime(1970, 1, 1, 0, 0, 0).AddMilliseconds(unixTimeStamp);
/// <summary>
/// 当前日期所在月份第一个指定星期几的日期
/// </summary>
/// <param name="date">给定日期</param>
/// <param name="dayOfWeek">星期几</param>
/// <returns>所对应的日期</returns>
public static DateTime GetFirstWeekDayOfMonth(this DateTime date, DayOfWeek dayOfWeek)
var dt = date.GetMonthStart();
while (dt.DayOfWeek != dayOfWeek)
dt = dt.AddDays(1);
return dt;
/// <summary>
/// 当前日期所在月份最后1个指定星期几的日期
/// </summary>
/// <param name="date">给定日期</param>
/// <param name="dayOfWeek">星期几</param>
/// <returns>所对应的日期</returns>
public static DateTime GetLastWeekDayOfMonth(this DateTime date, DayOfWeek dayOfWeek)
var dt = date.GetMonthEnd();
while (dt.DayOfWeek != dayOfWeek)
dt = dt.AddDays(-1);
return dt;
/// <summary>
/// 判断是否比指定之间早
/// </summary>
/// <param name="date"></param>
/// <param name="other"></param>
/// <returns></returns>
public static bool IsBefore(this DateTime date, DateTime other)
return date < other;
/// <summary>
/// 判断是否比指定时间晚
/// </summary>
/// <param name="date"></param>
/// <param name="other"></param>
/// <returns></returns>
public static bool IsAfter(this DateTime date, DateTime other)
return date > other;
/// <summary>
/// 给定日期所在月份共有多少天
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
public static int GetCountDaysOfMonth(this DateTime date)
return date.GetMonthEnd().Day;
/// <summary>
/// 当前日期与给定日期是否是同一天
/// </summary>
/// <param name="date">当前日期</param>
/// <param name="dateToCompare">给定日期</param>
/// <returns></returns>
public static bool IsDateEqual(this DateTime date, DateTime dateToCompare)
return date.Date == dateToCompare.Date;
/// <summary>
/// 是否是周未
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
public static bool IsWeekend(this DateTime date)
return date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
/// <summary>
/// 是否是工作日
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
public static bool IsWeekDay(this DateTime date)
return !date.IsWeekend();
/// <summary>
/// 判断是否为今天
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
public static bool IsToday(this DateTime date)
return date.Date == DateTime.Now.Date;
/// <summary>
/// 判定公历闰年遵循的一般规律为:四年一闰,百年不闰,四百年再闰。
/// 公历闰年的精确计算方法:(按一回归年365天5小时48分45.5秒)
/// 普通年能被4整除而不能被100整除的为闰年。 (如2004年就是闰年,1900年不是闰年)
/// 世纪年能被400整除而不能被3200整除的为闰年。 (如2000年是闰年,3200年不是闰年)
/// 对于数值很大的年份能整除3200,但同时又能整除172800则又是闰年。(如172800年是闰年,86400年不是闰年)
/// 公元前闰年规则如下:
/// 非整百年:年数除4余数为1是闰年,即公元前1、5、9……年;
/// 整百年:年数除400余数为1是闰年,年数除3200余数为1,不是闰年,年数除172800余1又为闰年,即公元前401、801……年。
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static bool IsLeap(this DateTime dateTime)
var year = dateTime.Year;
if ((year % 400 == 0 && year % 3200 != 0)
|| (year % 4 == 0 && year % 100 != 0)
|| (year % 3200 == 0 && year % 172800 == 0))
return true;
else
return false;
/// <summary>
/// 获取当前年天数
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static int GetDaysByYear(this DateTime dateTime)
return (new DateTime(dateTime.Year + 1, 1, 1) - new DateTime(dateTime.Year, 1, 1)).Days;
/// <summary>
/// 获取当前年天数
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static int GetWeekCountByYear(this DateTime dateTime)
//找到今年的第一天是周几
int firstWeekend = Convert.ToInt32(DateTime.Parse(dateTime.Year + "-1-1").DayOfWeek);
//获取第一周的差额,如果是周日,则firstWeekend为0,第一周也就是从周天开始的。
int weekDay = firstWeekend == 0 ? 1 : (7 - firstWeekend + 1);
//获取今天是一年当中的第几天
int currentDay = dateTime.DayOfYear;
//(今天 减去 第一周周末)/7 等于 距第一周有多少周 再加上第一周的1 就是今天是今年的第几周了
// 刚好考虑了惟一的特殊情况就是,今天刚好在第一周内,那么距第一周就是0 再加上第一周的1 最后还是1
int current_week = Convert.ToInt32(Math.Ceiling((currentDay - weekDay) / 7.0)) + 1;
return current_week;
取消另一个类 C# 中的任务
【中文标题】取消另一个类 C# 中的任务【英文标题】:Cancel task in another class C# 【发布时间】:2021-03-08 05:19:44 【问题描述】:我对 C# 中的 cancelTokenSource 有问题
public class Building
public CancellationTokenSource BuildTokenSource;
public void StartBuilt()
BuildTokenSource = new CancellationTokenSource();
buildingService.buildTask = Task.Run(async () =>
await clock.Delay(BUILT_TIME);
, BuildTokenSource.Token);
public void CancelBuilt()
if (BuildTokenSource != null)
BuildTokenSource.Cancel();
在另一个类中想要检测任务是否像这样取消但它不起作用。从未触发过的 catch 异常
public async Task<Building> GetBuildingOfUserTask()
double remainingTime = unitService.GetRemainingTime();
if (remainingTime <= 2000 && remainingTime > 0.0)
Building building = GetBuilding();
CancellationToken cancellation = building.BuildTokenSource.Token;
try
await buildTask;
catch (OperationCanceledException) when (cancellation.IsCancellationRequested)
return GetBuildingOfUser();
return GetBuildingOfUser();
有人知道为什么这不起作用,在这种情况下有解决方案吗?
【问题讨论】:
“它不起作用” 什么不起作用?编译器错误?例外?行为与预期不同? 任务没有取消。永远不会触发 catch 异常 相关:Using CancellationToken for timeout in Task.Run does not work 【参考方案1】:clock.Delay(BUILT_TIME)
是否有接受CancellationToken
的重载?如果是这样,请使用它。
问题是如果代码在您取消时已经在等待clock.Delay(BUILT_TIME)
,clock.Delay
将不知道它需要抛出异常。
【讨论】:
【参考方案2】:我没有看到任何地方调用CancelBuilt()
+ 你必须调用BuildTokenSource.Token.ThrowIfCancellationRequested()
才能引发OperationCanceledException
异常
token.Cancel()
应该在使用 cancelationToken 的异步方法之外调用。同样消费异步方法必须调用(通常在每一步)Token.ThrowIfCancellationRequested();
【讨论】:
【参考方案3】:我相信使用调解器 (Mediator design pattern) 会更合适。这实际上是一个 pub-sub 模型,它将在取消时发布一个事件并通知所有订阅者。
第一个类将中介实例作为引用(只读字段、属性)来发布取消事件,另一个类应该有相同的实例作为引用,以便在事件实际发生时得到通知。您应该注意的另一点是,当包含“GetBuildingOfUserTask”方法的类的实例被销毁时应该取消订阅。
你怎么看?
【讨论】:
【参考方案4】:我同意HadascokJ的回答,我想带来更多的光明。
您有一个主要任务从 Task buildingService.buildTask
开始,它的从属任务从 await clock.Delay(BUILT_TIME);
开始
第一个任务管理CancellationToken
,但从属的不是。为了更好地使用Task Task.Delay(int millisecondsDelay, CancellationToken cancellationToken);
替换您的clock.Delay(BUILT_TIME)
,当然还要提供CancelationToken
。您会看到,在这种情况下,从属任务将被取消。同时调用void CancellationToken.CancelAfter(int millisecondsDelay)
由于您没有为从属任务提供CancellationToken
,因此主任务已启动,主任务及其从属任务都不会被取消。
另一方面,要在从属任务执行时取消,向从属任务提供一些逻辑来管理CancelationToken
到其相应的方法中,并在必要时调用CancelationToken.ThrowIfCancellationRequested()
,这会抛出OperationCanceledException
.
至少,尝试将长任务分成几个小任务。
我用来管理异步。任务,必须按顺序运行到能够观察这些TaskStatus
的任务队列中。为了解决这个问题,如果你需要,我在 github 上有一个实现。我叫它FifoTaskQueue
【讨论】:
以上是关于C#中的时间类的主要内容,如果未能解决你的问题,请参考以下文章