翼度科技»论坛 编程开发 .net 查看内容

给C#新增一个时间类型: YearMonth

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
在.Net Framework中,我们常用的时间类型是DateTime。直到.Net6微软加入了两个新的时间类型:DateOnly和TimeOnly,才弥补了之前的不足。DateOnly:表示仅日期。比如:某人的生日,我只关心日期,就适合用DateOnly。
TimeOnly:表示仅时间。比如:每天定时执行某个任务,我只关心时间,就适合用TimeOnly。
由此可见,DateOnly和TimeOnly都有相应的应用场景。可小编在实际项目中遇到了这样的业务场景:需要每月给客户生成月账单。这里我所关心的是某个月份,于是我首先想到用DateOnly表示(不考虑字符串)。
  1. var date = new DateOnly(2023, 2, 1);    // 代表2023年2月1日
复制代码
虽然DateOnly可用,但从字面理解和表现形式上还是略显尴尬。 DateOnly真正表达的是某一天并不是某个月, 在代码层面也容易混淆,所以并不符合小编的心理期望。经过一番纠结和思考,小编决定自己动手创建一个表示年/月的时间类型:YearMonth。
  1. var ym = new YearMonth(2023, 2);  // 代表2023年2月
复制代码
 YearMonth的源码如下:
  1.   1  /// <summary>
  2.   2  /// 表示年/月的时间类型
  3.   3  /// </summary>
  4.   4  [JsonConverter(typeof(YearMonthJsonConverter))]
  5.   5  public readonly struct YearMonth
  6.   6  {
  7.   7      public int Year { get; }
  8.   8
  9.   9      public int Month { get; }
  10. 10
  11. 11      public YearMonth(int year, int month)
  12. 12      {
  13. 13          Year = year;
  14. 14          Month = month;
  15. 15      }
  16. 16         
  17. 17      public YearMonth AddMonths(int value)
  18. 18      {
  19. 19          var date = new DateOnly(Year, Month, 1);
  20. 20          return FromDateOnly(date.AddMonths(value));
  21. 21      }
  22. 22
  23. 24      public YearMonth AddYears(int value)
  24. 25      {
  25. 26          var date = new DateOnly(Year, Month, 1);
  26. 27          return FromDateOnly(date.AddYears(value));
  27. 28      }
  28. 29
  29. 30      public DateOnly FirstDay()
  30. 31      {
  31. 32          return new DateOnly(Year, Month, 1);
  32. 33      }
  33. 34
  34. 35      public DateOnly LastDay()
  35. 36      {
  36. 37          var nextMonth = AddMonths(1);
  37. 38          var date = new DateOnly(nextMonth.Year, nextMonth.Month, 1);
  38. 39          return date.AddDays(-1);
  39. 40      }
  40. 41
  41. 42      public int DaysInMonth()
  42. 43      {
  43. 44          return DateTime.DaysInMonth(Year, Month);
  44. 45      }
  45. 46
  46. 47      public static YearMonth Current
  47. 48      {
  48. 49          get { return FromDateTime(DateTime.Now); }
  49. 50      }
  50. 51
  51. 52      public static YearMonth UtcCurrent
  52. 53      {
  53. 54          get { return FromDateTime(DateTime.UtcNow); }
  54. 55      }
  55. 56
  56. 57      public static YearMonth FromDateOnly(DateOnly dateOnly)
  57. 58      {
  58. 59          return new YearMonth(dateOnly.Year, dateOnly.Month);
  59. 60      }
  60. 61
  61. 62      public static YearMonth FromDateTime(DateTime dateTime)
  62. 63      {
  63. 64          return new YearMonth(dateTime.Year, dateTime.Month);
  64. 65      }
  65. 66         
  66. 67      public static YearMonth FromString(string s)
  67. 68      {
  68. 69          if (DateTime.TryParse(s, out var date))
  69. 70          {
  70. 71              return FromDateTime(date);
  71. 72          }
  72. 73          throw new ArgumentException("format is error", nameof(s));
  73. 74      }
  74. 75
  75. 76      public override string ToString()
  76. 77      {
  77. 78          return $"{Year.ToString().PadLeft(4, '0')}-{Month.ToString().PadLeft(2, '0')}";
  78. 79      }
  79. 80
  80. 81      public static bool operator ==(YearMonth left, YearMonth right)
  81. 82      {
  82. 83          return left.Year == right.Year && left.Month == right.Month;
  83. 84      }
  84. 85
  85. 86      public static bool operator !=(YearMonth left, YearMonth right)
  86. 87      {
  87. 88          return !(left.Year == right.Year && left.Month == right.Month);
  88. 89      }
  89. 90
  90. 91      public static bool operator >=(YearMonth left, YearMonth right)
  91. 92      {
  92. 93          return (left.Year > right.Year) || (left.Year == right.Year && left.Month >= right.Month);
  93. 94      }
  94. 95
  95. 96      public static bool operator <=(YearMonth left, YearMonth right)
  96. 97      {
  97. 98          return (left.Year < right.Year) || (left.Year == right.Year && left.Month <= right.Month);
  98. 99      }
  99. 100
  100. 101      public static bool operator >(YearMonth left, YearMonth right)
  101. 102      {
  102. 103          return (left.Year > right.Year) || (left.Year == right.Year && left.Month > right.Month);
  103. 104      }
  104. 105
  105. 106      public static bool operator <(YearMonth left, YearMonth right)
  106. 107      {
  107. 108          return (left.Year < right.Year) || (left.Year == right.Year && left.Month < right.Month);
  108. 109      }
  109. 110               
  110. 111      public override bool Equals(object obj)
  111. 112      {
  112. 113          return base.Equals(obj);
  113. 114      }
  114. 115
  115. 116      public override int GetHashCode()
  116. 117      {
  117. 118          return base.GetHashCode();
  118. 119      }      
  119. 120 }
复制代码
  至此,上面的YearMonth时间类型已经满足小编的开发需要,当然也可以根据需求继续扩展其它功能。

 
 
本文已同步至作者的微信公众号:玩转DotNet
感谢点赞并关注


来源:https://www.cnblogs.com/fengjq/archive/2023/07/25/17578772.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具