You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

481 lines
17 KiB

  1. using Apewer.Internals;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. namespace Apewer.Internals
  6. {
  7. /// <summary>时钟。</summary>
  8. internal struct ClockValue
  9. {
  10. #region 值。
  11. //private int _hashcode = 0;
  12. private int _year, _month, _day, _hour, _minute, _second, _milli;
  13. /// <summary>年:1 ~ 9999,若超出范围,则设置为最大值。</summary>
  14. public int Year
  15. {
  16. get { return _year; }
  17. set { _year = NumberHelper.RestrictValue(value, 1, 9999); }
  18. }
  19. /// <summary>月:1 ~ 12,若超出范围,则设置为最大值。</summary>
  20. public int Month
  21. {
  22. get { return _month; }
  23. set { _month = NumberHelper.RestrictValue(value, 1, 12); }
  24. }
  25. /// <summary>日:1 ~ 31,若超出范围,则设置为最大值。</summary>
  26. public int Day
  27. {
  28. get { return _day; }
  29. set { _day = NumberHelper.RestrictValue(value, 1, ClockHelper.MonthDays(Year, Month)); }
  30. }
  31. /// <summary>时:0 ~ 23,若超出范围,则设置为最大值。</summary>
  32. public int Hour
  33. {
  34. get { return _hour; }
  35. set { _hour = NumberHelper.RestrictValue(value, 0, 59); }
  36. }
  37. /// <summary>分:0 ~ 59,若超出范围,则设置为最大值。</summary>
  38. public int Minute
  39. {
  40. get { return _minute; }
  41. set { _minute = NumberHelper.RestrictValue(value, 0, 59); }
  42. }
  43. /// <summary>秒:0 ~ 59,若超出范围,则设置为最大值。</summary>
  44. public int Second
  45. {
  46. get { return _second; }
  47. set { _second = NumberHelper.RestrictValue(value, 0, 59); }
  48. }
  49. /// <summary>毫秒:0 ~ 999,若超出范围,则设置为最大值。</summary>
  50. public int Millisecond
  51. {
  52. get { return _milli; }
  53. set { _milli = NumberHelper.RestrictValue(value, 0, 999); }
  54. }
  55. #endregion
  56. #region 运算。
  57. /// <summary>获取哈希代码。</summary>
  58. public override int GetHashCode()
  59. {
  60. return Compact.GetHashCode();
  61. }
  62. /// <summary>判断值相等。</summary>
  63. public override bool Equals(object obj)
  64. {
  65. if (obj == null) return Equals(Create(0, 0, 0, 0, 0, 0, 0));
  66. try
  67. {
  68. if (obj.GetType().Equals(typeof(ClockValue)))
  69. {
  70. return Compare(this, (ClockValue)obj) == 0;
  71. }
  72. }
  73. catch { }
  74. return false;
  75. }
  76. public static bool operator ==(ClockValue argLeft, ClockValue argRight)
  77. {
  78. if (argLeft.Year != argRight.Year) return false;
  79. if (argLeft.Month != argRight.Month) return false;
  80. if (argLeft.Day != argRight.Day) return false;
  81. if (argLeft.Hour != argRight.Hour) return false;
  82. if (argLeft.Minute != argRight.Minute) return false;
  83. if (argLeft.Second != argRight.Second) return false;
  84. if (argLeft.Millisecond != argRight.Millisecond) return false;
  85. return true;
  86. }
  87. public static bool operator !=(ClockValue argLeft, ClockValue argRight)
  88. {
  89. if (argLeft.Year != argRight.Year) return true;
  90. if (argLeft.Month != argRight.Month) return true;
  91. if (argLeft.Day != argRight.Day) return true;
  92. if (argLeft.Hour != argRight.Hour) return true;
  93. if (argLeft.Minute != argRight.Minute) return true;
  94. if (argLeft.Second != argRight.Second) return true;
  95. if (argLeft.Millisecond != argRight.Millisecond) return true;
  96. return false;
  97. }
  98. /// <summary>获取时间戳,默认基于零值。</summary>
  99. public TimeSpan Subtract()
  100. {
  101. return Subtract(true);
  102. }
  103. /// <summary>获取时间戳,若不为零值,则使用 1970-01-01 00:00:00.000 作为减数。</summary>
  104. public TimeSpan Subtract(bool argZero)
  105. {
  106. return ToDateTime().Subtract(argZero ? Zero.ToDateTime() : Create(1970, 1, 1, 0, 0, 0, 0).ToDateTime());
  107. }
  108. /// <summary>减少时间。</summary>
  109. public TimeSpan Subtract(ClockValue argClock)
  110. {
  111. var span = ToDateTime().Subtract(argClock.ToDateTime());
  112. return span;
  113. }
  114. /// <summary>减少时间。</summary>
  115. public ClockValue Subtract(TimeSpan argSpan)
  116. {
  117. var span = (argSpan == null) ? new TimeSpan(0) : argSpan;
  118. var dt = ToDateTime().Add(span);
  119. return Create(dt);
  120. }
  121. private static int Compare(ClockValue argLeft, ClockValue argRight)
  122. {
  123. if ((argLeft == null) && (argRight == null)) return 0;
  124. if ((argLeft == null) && (argRight != null)) return -1;
  125. if ((argLeft != null) && (argRight == null)) return 1;
  126. if (argLeft.Year < argRight.Year) return -1;
  127. if (argLeft.Month < argRight.Month) return -1;
  128. if (argLeft.Day < argRight.Day) return -1;
  129. if (argLeft.Hour < argRight.Hour) return -1;
  130. if (argLeft.Minute < argRight.Minute) return -1;
  131. if (argLeft.Second < argRight.Second) return -1;
  132. if (argLeft.Millisecond < argRight.Millisecond) return -1;
  133. if (argLeft.Millisecond == argRight.Millisecond) return 0;
  134. return 1;
  135. }
  136. /// <summary>比较 Clock 对象值。</summary>
  137. public static bool operator >(ClockValue argLeft, ClockValue argRight)
  138. {
  139. return Compare(argLeft, argRight) == 1;
  140. }
  141. /// <summary>比较 Clock 对象值。</summary>
  142. public static bool operator <(ClockValue argLeft, ClockValue argRight)
  143. {
  144. return Compare(argLeft, argRight) == -1;
  145. }
  146. #endregion
  147. #region 输入。
  148. /// <summary>使用零值创建对象。</summary>
  149. public static ClockValue Zero
  150. {
  151. get
  152. {
  153. var clock = new ClockValue();
  154. clock._year = 0;
  155. clock._month = 0;
  156. clock._day = 0;
  157. clock._hour = 0;
  158. clock._minute = 0;
  159. clock._second = 0;
  160. clock._milli = 0;
  161. return clock;
  162. }
  163. }
  164. /// <summary>使用当前本地时间创建对象。</summary>
  165. public static ClockValue Current
  166. {
  167. get { return Create(DateTime.Now); }
  168. }
  169. /// <summary>使用当前本地时间创建对象。</summary>
  170. public static ClockValue LocalNow
  171. {
  172. get { return Create(DateTime.Now); }
  173. }
  174. /// <summary>使用当前 UTC 时间创建对象。</summary>
  175. public static ClockValue UtcNow
  176. {
  177. get { return Create(DateTime.UtcNow); }
  178. }
  179. /// <summary>由指定时间创建对象。</summary>
  180. public static ClockValue Create(int argYear, int argMonth, int argDay, int argHour, int argMinute, int argSecond, int argMillisecond)
  181. {
  182. var clock = new ClockValue();
  183. clock.Year = argYear;
  184. clock.Month = argMonth;
  185. clock.Day = argDay;
  186. clock.Hour = argHour;
  187. clock.Minute = argMinute;
  188. clock.Second = argSecond;
  189. clock.Millisecond = argMillisecond;
  190. return clock;
  191. }
  192. /// <summary>由指定时间创建对象。</summary>
  193. public static ClockValue Create(int argYear, int argMonth, int argDay, int argHour, int argMinute, int argSecond)
  194. {
  195. return Create(argYear, argMonth, argDay, argHour, argMinute, argSecond, 0);
  196. }
  197. /// <summary>由指定时间创建对象。</summary>
  198. public static ClockValue Create(int argYear, int argMonth, int argDay)
  199. {
  200. return Create(argYear, argMonth, argDay, 0, 0, 0, 0);
  201. }
  202. /// <summary>由指定时间创建对象。</summary>
  203. public static ClockValue Create(string argText, bool argLucid)
  204. {
  205. var clock = new ClockValue();
  206. if (string.IsNullOrEmpty(argText)) return clock;
  207. if (argLucid)
  208. {
  209. if (argText.Length >= 10)
  210. {
  211. clock.Year = TextConverter.GetInt32(argText.Substring(0, 2));
  212. clock.Month = TextConverter.GetInt32(argText.Substring(5, 2));
  213. clock.Day = TextConverter.GetInt32(argText.Substring(8, 2));
  214. }
  215. if (argText.Length >= 19)
  216. {
  217. clock.Hour = TextConverter.GetInt32(argText.Substring(11, 2));
  218. clock.Minute = TextConverter.GetInt32(argText.Substring(14, 2));
  219. clock.Second = TextConverter.GetInt32(argText.Substring(17, 2));
  220. }
  221. if (argText.Length >= 23)
  222. {
  223. clock.Millisecond = TextConverter.GetInt32(argText.Substring(20, 3));
  224. }
  225. }
  226. else
  227. {
  228. if (argText.Length >= 8)
  229. {
  230. clock.Year = TextConverter.GetInt32(argText.Substring(0, 2));
  231. clock.Month = TextConverter.GetInt32(argText.Substring(4, 2));
  232. clock.Day = TextConverter.GetInt32(argText.Substring(6, 2));
  233. }
  234. if (argText.Length >= 14)
  235. {
  236. clock.Hour = TextConverter.GetInt32(argText.Substring(8, 2));
  237. clock.Minute = TextConverter.GetInt32(argText.Substring(10, 2));
  238. clock.Second = TextConverter.GetInt32(argText.Substring(12, 2));
  239. }
  240. if (argText.Length >= 17)
  241. {
  242. clock.Millisecond = TextConverter.GetInt32(argText.Substring(14, 3));
  243. }
  244. }
  245. return clock;
  246. }
  247. /// <summary>由指定 DateTime 创建对象。</summary>
  248. public static ClockValue Create(DateTime argDateTime)
  249. {
  250. var dt = argDateTime;
  251. if (dt == null) dt = new DateTime(0, 0, 0, 0, 0, 0, 0);
  252. return Create(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Millisecond);
  253. }
  254. /// <summary>由毫秒时间戳创建对象。</summary>
  255. public static ClockValue Create(long argMillisecondStamp)
  256. {
  257. var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
  258. var datetime = origin.AddMilliseconds(Convert.ToDouble(argMillisecondStamp));
  259. return Create(datetime);
  260. }
  261. #endregion
  262. #region 输出。
  263. /// <summary>表示当前时钟的文本,显示为易于阅读的格式。</summary>
  264. public string Lucid
  265. {
  266. get { return ToString(true); }
  267. }
  268. /// <summary>表示当前时钟的文本,显示为易于阅读的格式。</summary>
  269. public string LucidDate
  270. {
  271. get { return ToString(true).Substring(0, 10); }
  272. }
  273. /// <summary>表示当前时钟的文本,显示为易于阅读的格式。</summary>
  274. public string LucidTime
  275. {
  276. get { return ToString(true).Substring(11); }
  277. }
  278. /// <summary>表示当前时钟的文本,显示为连续的数字。</summary>
  279. public string Compact
  280. {
  281. get { return ToString(false); }
  282. }
  283. /// <summary>获取以毫秒为单位的时间戳,以 1970-01-01 00:00:00.000 为原点。</summary>
  284. public long Stamp
  285. {
  286. get
  287. {
  288. return ClockHelper.Stamp(ToDateTime(), true);
  289. }
  290. }
  291. /// <summary>生成 DateTime 对象。</summary>
  292. public static DateTime ToDateTime(object argDateTime)
  293. {
  294. try { var dt = (DateTime)argDateTime; return dt; }
  295. catch { return Zero.ToDateTime(); }
  296. }
  297. /// <summary>生成 DateTime 对象。</summary>
  298. public static DateTime ToDateTime(string argDateTime)
  299. {
  300. if (string.IsNullOrEmpty(argDateTime))
  301. {
  302. try { var dt = DateTime.Parse(argDateTime); return dt; }
  303. catch { }
  304. }
  305. return Zero.ToDateTime();
  306. }
  307. /// <summary>生成 DateTime 对象。</summary>
  308. public DateTime ToDateTime()
  309. {
  310. try
  311. {
  312. var year = NumberHelper.RestrictValue(Year, 1, 9999);
  313. var month = NumberHelper.RestrictValue(Month, 1, 12);
  314. var days = ClockHelper.MonthDays(year, month);
  315. var day = NumberHelper.RestrictValue(Day, 1, days);
  316. var hour = NumberHelper.RestrictValue(Hour, 0, 23);
  317. var minute = NumberHelper.RestrictValue(Minute, 0, 59);
  318. var second = NumberHelper.RestrictValue(Second, 0, 59);
  319. var milli = NumberHelper.RestrictValue(Millisecond, 0, 999);
  320. var dt = new DateTime(year, month, day, hour, minute, second, milli);
  321. return dt;
  322. }
  323. catch { return new DateTime(); }
  324. }
  325. public byte[] ToBinary()
  326. {
  327. var bs = new byte[9];
  328. bs[0] = (byte)(Year / 256);
  329. bs[1] = (byte)(Year % 256);
  330. bs[2] = (byte)(Day / 256);
  331. bs[3] = (byte)(Month / 256);
  332. bs[4] = (byte)(Hour / 256);
  333. bs[5] = (byte)(Minute / 256);
  334. bs[6] = (byte)(Second / 256);
  335. bs[7] = (byte)(Millisecond / 256);
  336. bs[8] = (byte)(Millisecond % 256);
  337. return bs;
  338. }
  339. /// <summary>生成文本。</summary>
  340. public string ToString(bool argLucid)
  341. {
  342. if (argLucid)
  343. {
  344. var result = new TextBuilder();
  345. result.Append(TextModifier.PreZero(Year.ToString(), 4));
  346. result.Append("-");
  347. result.Append(TextModifier.PreZero(Month.ToString(), 2));
  348. result.Append("-");
  349. result.Append(TextModifier.PreZero(Day.ToString(), 2));
  350. result.Append(" ");
  351. result.Append(TextModifier.PreZero(Hour.ToString(), 2));
  352. result.Append(":");
  353. result.Append(TextModifier.PreZero(Minute.ToString(), 2));
  354. result.Append(":");
  355. result.Append(TextModifier.PreZero(Second.ToString(), 2));
  356. result.Append(".");
  357. result.Append(TextModifier.PreZero(Millisecond.ToString(), 3));
  358. return result.Value;
  359. }
  360. else
  361. {
  362. string result = "";
  363. result += TextModifier.PreZero(Year.ToString(), 4);
  364. result += TextModifier.PreZero(Month.ToString(), 2);
  365. result += TextModifier.PreZero(Day.ToString(), 2);
  366. result += TextModifier.PreZero(Hour.ToString(), 2);
  367. result += TextModifier.PreZero(Minute.ToString(), 2);
  368. result += TextModifier.PreZero(Second.ToString(), 2);
  369. result += TextModifier.PreZero(Millisecond.ToString(), 3);
  370. return result;
  371. }
  372. }
  373. /// <summary>生成 Lucid 风格的文本。</summary>
  374. public override string ToString()
  375. {
  376. return ToString(true);
  377. }
  378. #endregion
  379. #region 封装。
  380. /// <summary>表示当前时钟的字节数组。</summary>
  381. public static byte[] ToBinary(ClockValue argClock)
  382. {
  383. var bs = new byte[9];
  384. bs[0] = (byte)(argClock.Year / 256);
  385. bs[1] = (byte)(argClock.Year % 256);
  386. bs[2] = (byte)(argClock.Day / 256);
  387. bs[3] = (byte)(argClock.Month / 256);
  388. bs[4] = (byte)(argClock.Hour / 256);
  389. bs[5] = (byte)(argClock.Minute / 256);
  390. bs[6] = (byte)(argClock.Second / 256);
  391. bs[7] = (byte)(argClock.Millisecond / 256);
  392. bs[8] = (byte)(argClock.Millisecond % 256);
  393. return bs;
  394. }
  395. /// <summary>由指定字节数组创建对象。</summary>
  396. public static ClockValue FromBinary(byte[] argBytes)
  397. {
  398. var bs = argBytes;
  399. if (bs != null)
  400. {
  401. var clock = new ClockValue();
  402. if (argBytes.Length >= 4)
  403. {
  404. clock.Year = bs[0] * 256 + bs[1];
  405. clock.Month = bs[2];
  406. clock.Day = bs[3];
  407. }
  408. if (argBytes.Length >= 7)
  409. {
  410. clock.Hour = bs[4];
  411. clock.Minute = bs[5];
  412. clock.Millisecond = bs[6] * 256 + bs[7];
  413. }
  414. return clock;
  415. }
  416. else
  417. {
  418. return Create(0, 0, 0, 0, 0, 0, 0);
  419. }
  420. }
  421. #endregion
  422. }
  423. }