DateTimeManager.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. /*******************************************************************************
  2. * Copyright(c) 2012 dongke All rights reserved. / Confidential
  3. * 类的信息:
  4. * 1.程序名称:DateTimeManager.cs
  5. * 2.功能描述:提供跟DateTime相关的功能,例如:字符转日期,日期转字符等
  6. * 编辑履历:
  7. * 作者 日期 版本 修改内容
  8. * 欧阳涛 2012/06/07 1.00 新建
  9. *******************************************************************************/
  10. using System;
  11. using System.Text.RegularExpressions;
  12. namespace Dongke.IBOSS.PRD.Basics.Library
  13. {
  14. /// <summary>
  15. /// 提供跟DateTime相关的功能,例如:字符转日期,日期转字符等
  16. /// </summary>
  17. public class DateTimeManager
  18. {
  19. #region 常量定义
  20. /// <summary>
  21. /// 日期格式的字符串格式数组<br/>
  22. /// <br/>
  23. /// 格式<br/>
  24. ///  ・YYYY:年(公历、4位数字)<br/>
  25. ///  ・YY :年(公历、4位数字)<br/>
  26. ///  ・MMM:月(JAN/FEB/MAR/APR/MAY/JUN/JUL/AUG/SEP/OCT/NOV/DEC)<br/>
  27. ///  ・MM :月(2位数字)<br/>
  28. ///  ・M :月(可变位数数字)<br/>
  29. ///  ・DD:日(2位数字)<br/>
  30. ///  ・D :日(可变位数数字)<br/>
  31. /// <br/>
  32. ///  ・[ ] :空字符串<br/>
  33. ///  ・[/] :区分字符串(分隔符)<br/>
  34. /// </summary>
  35. private static string[] FORMAT_LIST_FOR_DATE = new string[]
  36. {
  37. "YYYY_/_MM_/_DD",
  38. "YYYY_/_MM_/_D",
  39. "YYYY_/_M_/_DD",
  40. "YYYY_/_M_/_D",
  41. "YY_/_MM_/_DD",
  42. "YY_/_MM_/_D",
  43. "YY_/_M_/_DD",
  44. "YY_/_M_/_D",
  45. "MM_/_DD",
  46. "MM_/_D",
  47. "M_/_DD",
  48. "M_/_D",
  49. "YYYY_MM_DD",
  50. "YY_MM_DD",
  51. "MM_DD",
  52. "DD_/_MMM_/_YYYY",
  53. "DD_/_MMM_/_YY",
  54. "DD_/_MMM",
  55. "DD_MMM_YYYY",
  56. "DD_MMM_YY",
  57. "DD_MMM",
  58. "YYYY_/_MM"
  59. };
  60. /// <summary>
  61. /// 时间格式的字符串格式数组<br/>
  62. /// <br/>
  63. /// 格式<br/>
  64. ///  ・hh :小时(2位数字)<br/>
  65. ///  ・h :小时(可变位数数字)<br/>
  66. ///  ・mm :分钟(2位数字)<br/>
  67. ///  ・m :分钟(可变位数数字)<br/>
  68. ///  ・ss :秒(2位数字)<br/>
  69. ///  ・s :秒(可变位数数字)<br/>
  70. /// <br/>
  71. ///  ・[ ] :空字符串<br/>
  72. ///  ・[/] :区分字符串(分隔符)<br/>
  73. /// </summary>
  74. private static string[] FORMAT_LIST_FOR_TIME = new string[]
  75. {
  76. "hh_mm",
  77. "h_mm",
  78. "hh_/_mm",
  79. "hh_/_m",
  80. "h_/_mm",
  81. "h_/_m",
  82. "hh_/_mm_/_ss",
  83. "hh_/_mm_/_s",
  84. "hh_/_m_/_ss",
  85. "hh_/_m_/_s",
  86. "h_/_mm_/_ss",
  87. "h_/_mm_/_s",
  88. "h_/_m_/_ss",
  89. "h_/_m_/_s"
  90. };
  91. /// <summary>
  92. /// 日期和时间的字符串数组
  93. /// </summary>
  94. private static string[][] FORMAT_LIST = new string[][]
  95. {
  96. FORMAT_LIST_FOR_DATE,
  97. FORMAT_LIST_FOR_TIME
  98. };
  99. /// <summary>
  100. /// 英文月的数组
  101. /// </summary>
  102. private static string[] EMONTH_LIST = new string[]
  103. {
  104. "January",
  105. "Febuary",
  106. "March",
  107. "April",
  108. "May",
  109. "June",
  110. "July",
  111. "August",
  112. "September",
  113. "October",
  114. "November",
  115. "December",
  116. };
  117. /// <summary>
  118. /// 英文星期数组
  119. /// </summary>
  120. private static string[] EWDAY_LIST = new string[]
  121. {
  122. "Sunday",
  123. "Monday",
  124. "Tuesday",
  125. "Wednesday",
  126. "Thursday",
  127. "Friday",
  128. "Saturday",
  129. };
  130. /// <summary>
  131. /// 中文星期数组
  132. /// </summary>
  133. private static string[] CWDAY_LIST = new string[]
  134. {
  135. "星期一",
  136. "星期二",
  137. "星期三",
  138. "星期四",
  139. "星期五",
  140. "星期六",
  141. "星期日",
  142. };
  143. #endregion
  144. #region 枚举
  145. /// <summary>
  146. /// 日期的种类
  147. /// </summary>
  148. private enum DateItemType
  149. {
  150. /// <summary>
  151. /// 年
  152. /// </summary>
  153. Year,
  154. /// <summary>
  155. /// 月
  156. /// </summary>
  157. Month,
  158. /// <summary>
  159. /// 日
  160. /// </summary>
  161. Day,
  162. /// <summary>
  163. /// 星期
  164. /// </summary>
  165. DayOfWeek,
  166. /// <summary>
  167. /// 小时
  168. /// </summary>
  169. Hour,
  170. /// <summary>
  171. /// 分钟
  172. /// </summary>
  173. Minute,
  174. /// <summary>
  175. /// 秒
  176. /// </summary>
  177. Second,
  178. /// <summary>
  179. /// 毫秒
  180. /// </summary>
  181. Millisecond
  182. }
  183. #endregion
  184. #region 公开方法/函数
  185. #region DateTime
  186. /// <summary>
  187. /// 取得当月第一天
  188. /// </summary>
  189. /// <param name="date"></param>
  190. /// <returns></returns>
  191. public static DateTime GetFirstDateInMonth(DateTime date)
  192. {
  193. return date.AddDays(1 - date.Day);
  194. }
  195. /// <summary>
  196. /// 取得该月的最后一天
  197. /// </summary>
  198. /// <param name="date"></param>
  199. /// <returns></returns>
  200. public static DateTime GetLastDateInMonth(DateTime date)
  201. {
  202. DateTime firstDate = GetFirstDateInMonth(date);
  203. return firstDate.AddMonths(1).AddDays(-1);
  204. }
  205. /// <summary>
  206. /// 取得本周的第一天的日期
  207. /// </summary>
  208. /// <param name="date">日期</param>
  209. /// <param name="firstDayOfWeek">星期的第一天是星期几,周一或者周日</param>
  210. /// <returns></returns>
  211. public static DateTime GetFirstDateInWeek(DateTime date, DayOfWeek firstDayOfWeek)
  212. {
  213. int diffNum = ((int)(date.DayOfWeek - firstDayOfWeek) + 7) % 7;
  214. return date.AddDays(-1 * diffNum);
  215. }
  216. /// <summary>
  217. /// 取得本周的最后一天的日期
  218. /// </summary>
  219. /// <param name="date">日期</param>
  220. /// <param name="firstDayOfWeek">星期的第一天是星期几,周一或者周日</param>
  221. /// <returns></returns>
  222. public static DateTime GetLastDateInWeek(DateTime date, DayOfWeek firstDayOfWeek)
  223. {
  224. int diffNum = ((int)(date.DayOfWeek - firstDayOfWeek) + 7) % 7;
  225. return date.AddDays(7 - diffNum - 1);
  226. }
  227. /// <summary>
  228. /// 取得本年中的周数
  229. /// </summary>
  230. /// <param name="date">日期</param>
  231. /// <param name="firstDayOfWeek">星期的第一天是星期几,周一或者周日</param>
  232. /// <returns></returns>
  233. public static int GetWeekNumberInYear(DateTime date, DayOfWeek firstDayOfWeek)
  234. {
  235. return (GetLastDateInWeek(date, firstDayOfWeek).DayOfYear - 1) / 7 + 1;
  236. }
  237. #endregion
  238. #region 字符串转换成日期
  239. /// <summary>
  240. /// 字符串转换成日期
  241. /// </summary>
  242. /// <param name="dateTimeString">需要转换成日期的字符串</param>
  243. /// <param name="dateTime">返回转换后的日期</param>
  244. /// <returns>
  245. /// True:转换成功
  246. /// False:转换错误
  247. /// </returns>
  248. public static bool ConvertDateTime(string dateTimeString, out DateTime dateTime)
  249. {
  250. return ConvertDateTime(dateTimeString, null, out dateTime);
  251. }
  252. /// <summary>
  253. /// 字符串转换成日期
  254. /// </summary>
  255. /// <param name="dateTimeString"></param>
  256. /// <param name="parseList"></param>
  257. /// <param name="dateTime">返回转换后的日期,转换失败的情况下,返回DateTime.MinValue</param>
  258. /// <returns>
  259. /// True:转换成功
  260. /// False:转换错误
  261. /// </returns>
  262. public static bool ConvertDateTime(string dateTimeString, string[] parseList, out DateTime dateTime)
  263. {
  264. if (string.IsNullOrEmpty(dateTimeString))
  265. {
  266. dateTime = DateTime.MinValue;
  267. return false;
  268. }
  269. string parseFormat = GetDateTimeParseFormat(dateTimeString, parseList);
  270. if (string.IsNullOrEmpty(parseFormat))
  271. {
  272. dateTime = DateTime.MinValue;
  273. return false;
  274. }
  275. dateTimeString = ConvertDelimiter(dateTimeString);
  276. string yearStr, month, day, hour, minute, second;
  277. yearStr = ExtractSubstring(dateTimeString, parseFormat, string.Empty, "YYYY", "YY");
  278. if (yearStr.Length == 2)
  279. {
  280. // 西历的年是2位的情况,需要自动补充完整
  281. string paramYearUnderStr = yearStr;
  282. int nParamYearUnder = int.Parse(paramYearUnderStr);
  283. // 现在系统的时间
  284. string curYearStr;
  285. curYearStr = DateTime.Today.Year.ToString();
  286. int curYearUpper = int.Parse(curYearStr.Substring(0, 2));
  287. int curYearUnder = int.Parse(curYearStr.Substring(2, 2));
  288. int border = curYearUnder - 50;
  289. int year1, year2;
  290. if (border < 0)
  291. {
  292. // 当前西历是上半年的情况
  293. border = curYearUnder + 50;
  294. year1 = curYearUpper;
  295. year2 = curYearUpper - 1;
  296. }
  297. else
  298. {
  299. // 当前西历是是下半年的情况
  300. year1 = curYearUpper + 1;
  301. year2 = curYearUpper;
  302. }
  303. string tmpStr;
  304. tmpStr = ((nParamYearUnder <= border) ? year1 : year2).ToString();
  305. tmpStr += paramYearUnderStr;
  306. yearStr = tmpStr;
  307. }
  308. // 月
  309. month = ExtractSubstring(dateTimeString, parseFormat, "1", "MMM", "MM", "M");
  310. if (month.Length == 3)
  311. {
  312. // [JAN/FEB/...]的情况
  313. month = ConvertValue(EMONTH_LIST, month);
  314. }
  315. // 日
  316. day = ExtractSubstring(dateTimeString, parseFormat, "1", "DD", "D");
  317. // 小时
  318. hour = ExtractSubstring(dateTimeString, parseFormat, "0", "hh", "h");
  319. // 分钟
  320. minute = ExtractSubstring(dateTimeString, parseFormat, "0", "mm", "m");
  321. // 秒
  322. second = ExtractSubstring(dateTimeString, parseFormat, "0", "ss", "s");
  323. bool isFindYear = true;
  324. if (string.IsNullOrEmpty(yearStr))
  325. {
  326. // 是不是能够找到年度
  327. isFindYear = false;
  328. // 用当前年度设定
  329. yearStr = DateTime.Today.Year.ToString();
  330. }
  331. try
  332. {
  333. // 向日期类型进行转换
  334. DateTime tmp = DateTime.MinValue;
  335. if (DateTime.TryParse(string.Format("{0}/{1}/{2} {3}:{4}:{5}", yearStr, month, day, hour, minute, second), out tmp))
  336. {
  337. dateTime = tmp;
  338. }
  339. else
  340. {
  341. dateTime = DateTime.MinValue;
  342. return false;
  343. }
  344. }
  345. catch (Exception)
  346. {
  347. dateTime = DateTime.MinValue;
  348. return false;
  349. }
  350. if (isFindYear == false)
  351. {
  352. if (dateTime < DateTime.Today)
  353. {
  354. dateTime = dateTime.AddYears(1);
  355. }
  356. }
  357. return true;
  358. }
  359. #endregion
  360. #region 日期转换成字符串
  361. public static string ConvertString(DateTime source, string format)
  362. {
  363. string result = format;
  364. // 日期·时间的变量初始化
  365. string year = string.Format("{0:0000}", source.Year);
  366. string month = string.Format("{0:00}", source.Month);
  367. string day = string.Format("{0:00}", source.Day);
  368. string hour = string.Format("{0:00}", source.Hour);
  369. string minute = string.Format("{0:00}", source.Minute);
  370. string second = string.Format("{0:00}", source.Second);
  371. // 向指定格式的数据进行转换
  372. result.Replace("YYYY", year);
  373. result.Replace("YY", year.Substring(2, 2));
  374. result.Replace("MMM", EMONTH_LIST[int.Parse(TrimLeftZero(month)) - 1].Substring(0, 3).ToUpper());
  375. result.Replace("MM", month);
  376. result.Replace("M", TrimLeftZero(month));
  377. result.Replace("DD", day);
  378. result.Replace("D", TrimLeftZero(day));
  379. result.Replace("hh", hour);
  380. result.Replace("h", TrimLeftZero(hour));
  381. result.Replace("mm", minute);
  382. result.Replace("m", TrimLeftZero(minute));
  383. result.Replace("ss", second);
  384. result.Replace("s", TrimLeftZero(second));
  385. result.Replace("ddd", EWDAY_LIST[(source.DayOfWeek - DayOfWeek.Sunday) - 1].Substring(0, 3).ToUpper());
  386. result.Replace("dd", EWDAY_LIST[(source.DayOfWeek - DayOfWeek.Sunday) - 1].Substring(0, 2).ToUpper());
  387. result.Replace("jjj", CWDAY_LIST[(source.DayOfWeek - DayOfWeek.Sunday) - 1]);
  388. result.Replace("j", CWDAY_LIST[(source.DayOfWeek - DayOfWeek.Sunday) - 1].Substring(0, 1));
  389. return result;
  390. }
  391. #endregion
  392. #region 年龄·月龄计算
  393. /// <summary>
  394. /// 计算年龄
  395. /// </summary>
  396. /// <param name="birthDate">生日</param>
  397. /// <param name="baseDate">计算日期</param>
  398. /// <returns></returns>
  399. public static int CalcAge(DateTime birthDate, DateTime baseDate)
  400. {
  401. // 基本年龄
  402. int age = baseDate.Year - birthDate.Year;
  403. // 当年的生日
  404. DateTime thisYearBirthDate = birthDate.AddYears(age);
  405. // 生日前判断
  406. if (baseDate < thisYearBirthDate)
  407. {
  408. age--;
  409. }
  410. return age;
  411. }
  412. /// <summary>
  413. /// 计算月龄
  414. /// </summary>
  415. /// <param name="birthDate">生日</param>
  416. /// <param name="baseDate">计算日期</param>
  417. /// <returns></returns>
  418. public static int CalcAgeMonth(DateTime birthDate, DateTime baseDate)
  419. {
  420. // 基本月龄
  421. int ageMonth = (baseDate.Year - birthDate.Year) * 12
  422. + (baseDate.Month - birthDate.Month);
  423. // 生日前判断
  424. if (baseDate.Day < birthDate.Day)
  425. {
  426. ageMonth--;
  427. }
  428. return ageMonth;
  429. }
  430. #endregion
  431. #endregion
  432. #region 私有函数/方法
  433. /// <summary>
  434. /// 指定的字符串按照规定的格式要求转换成日期格式
  435. /// </summary>
  436. /// <param name="dateTime"></param>
  437. /// <param name="formatList"></param>
  438. /// <returns></returns>
  439. private static string GetDateTimeParseFormat(string dateTime, string[] formatList)
  440. {
  441. dateTime = ConvertDelimiter(dateTime);
  442. if (formatList == null)
  443. {
  444. System.Collections.Generic.List<string> list =
  445. new System.Collections.Generic.List<string>();
  446. foreach (string format in FORMAT_LIST_FOR_DATE)
  447. {
  448. list.Add(format);
  449. }
  450. foreach (string format in FORMAT_LIST_FOR_TIME)
  451. {
  452. list.Add(format);
  453. }
  454. foreach (string formatDate in FORMAT_LIST_FOR_DATE)
  455. {
  456. foreach (string formatTime in FORMAT_LIST_FOR_TIME)
  457. {
  458. list.Add(string.Format("{0}_ _{1}", formatDate, formatTime));
  459. }
  460. }
  461. formatList = list.ToArray();
  462. }
  463. int start, end, checkNum;
  464. bool isMatch;
  465. string formatTemp, item, type;
  466. string parseFormat = null;
  467. for (int i = 0; i < formatList.Length; i++)
  468. {
  469. formatTemp = formatList[i];
  470. formatTemp = formatTemp.Replace("_", string.Empty);
  471. if (formatTemp.Length != dateTime.Length)
  472. {
  473. continue;
  474. }
  475. formatTemp = formatList[i];
  476. start = end = checkNum = 0;
  477. isMatch = true;
  478. while (0 <= end)
  479. {
  480. end = formatTemp.IndexOf("_", end);
  481. if (0 <= end)
  482. {
  483. item = dateTime.Substring(start - checkNum, end - start);
  484. type = formatTemp.Substring(start, end - start);
  485. }
  486. else
  487. {
  488. item = dateTime.Substring(start - checkNum);
  489. type = formatTemp.Substring(start);
  490. }
  491. if (!CheckItem(item, type))
  492. {
  493. isMatch = false;
  494. break;
  495. }
  496. if (end < 0)
  497. {
  498. break;
  499. }
  500. checkNum++;
  501. start = ++end;
  502. }
  503. if (isMatch)
  504. {
  505. parseFormat = formatTemp;
  506. break;
  507. }
  508. }
  509. if (string.IsNullOrEmpty(parseFormat))
  510. {
  511. // 不可识别的情况
  512. return null;
  513. }
  514. else
  515. {
  516. // 取得显示的格式
  517. return parseFormat.Replace("_", string.Empty);
  518. }
  519. }
  520. /// <summary>
  521. /// 分隔符替换
  522. /// </summary>
  523. /// <param name="dateTime"></param>
  524. /// <returns></returns>
  525. private static string ConvertDelimiter(string dateTime)
  526. {
  527. return Regex.Replace(dateTime, "[^A-Za-z0-9_ ]", "/");
  528. }
  529. /// <summary>
  530. ///
  531. /// </summary>
  532. /// <param name="list"></param>
  533. /// <param name="value"></param>
  534. /// <returns></returns>
  535. private static string ConvertValue(string[] list, string value)
  536. {
  537. if (string.IsNullOrEmpty(value))
  538. {
  539. return null;
  540. }
  541. int length = value.Length;
  542. for (int i = 0; i < list.Length; i++)
  543. {
  544. if (value.Equals(list[i].Substring(0, length),
  545. StringComparison.InvariantCultureIgnoreCase))
  546. {
  547. return string.Format("{0:00}", i + 1);
  548. }
  549. }
  550. return null;
  551. }
  552. /// <summary>
  553. /// 字符串的值是不是该种类的检查
  554. /// </summary>
  555. /// <param name="item"></param>
  556. /// <param name="type"></param>
  557. /// <returns></returns>
  558. private static bool CheckItem(string item, string type)
  559. {
  560. if ("/".CompareTo(type) == 0)
  561. {
  562. // 有日期分隔符的情况
  563. if ("/".CompareTo(item) == 0)
  564. {
  565. return true;
  566. }
  567. else
  568. {
  569. return false;
  570. }
  571. }
  572. else if (" ".CompareTo(type) == 0)
  573. {
  574. // 空字符串的情况
  575. if (" ".CompareTo(item) == 0)
  576. {
  577. return true;
  578. }
  579. else
  580. {
  581. return false;
  582. }
  583. }
  584. else if ("MMM".CompareTo(type) == 0)
  585. {
  586. // [JAN/FEB/...]格式的情况
  587. return !string.IsNullOrEmpty(ConvertValue(EMONTH_LIST, item));
  588. }
  589. else
  590. {
  591. // 月份是通常数字的情况
  592. if (type.Length != item.Length)
  593. {
  594. return false;
  595. }
  596. int result;
  597. return int.TryParse(item, out result);
  598. }
  599. }
  600. /// <summary>
  601. /// 提取该字符串
  602. /// </summary>
  603. /// <param name="dateTimeString"></param>
  604. /// <param name="parseFormat"></param>
  605. /// <param name="defaultValue"></param>
  606. /// <param name="findList"></param>
  607. /// <returns></returns>
  608. private static string ExtractSubstring(string dateTimeString, string parseFormat,
  609. string defaultValue, params string[] findList)
  610. {
  611. int index;
  612. foreach (string find in findList)
  613. {
  614. if ((index = parseFormat.IndexOf(find)) != -1)
  615. {
  616. return dateTimeString.Substring(index, find.Length);
  617. }
  618. }
  619. return defaultValue;
  620. }
  621. /// <summary>
  622. /// 左边用零补齐
  623. /// </summary>
  624. /// <param name="value"></param>
  625. /// <returns></returns>
  626. private static string TrimLeftZero(string value)
  627. {
  628. if (string.IsNullOrEmpty(value))
  629. {
  630. return value;
  631. }
  632. return value.TrimStart(new char[] { '0' });
  633. }
  634. #endregion
  635. }
  636. }