C语言字符串转换成日期

[cpp]  view plain  copy
  1. /***************************************************************************** 
  2.  * 版权所有(C) 2006, ZTE Corp. WiMAX 
  3.  *---------------------------------------------------------------------------- 
  4.  * 模 块 名 : BSPCommon 
  5.  * 文件名称 : str2time.c 
  6.  * 文件标识 : {[N/A]} 
  7.  * 内容摘要 : 将字符串转换为时间 
  8.  * 注意事项 :  
  9.  * 作    者 : 田瑞忠 
  10.  * 创建日期 : 2008-12-27 
  11.  * 当前版本 : Ver1.0 
  12.  *---------------------------------------------------------------------------- 
  13.  * 变更记录 : 
  14.  * 
  15.  * $记录1 
  16.  * 变 更 单: $0000000(N/A) 
  17.  * 责 任 人: 田瑞忠 
  18.  * 修改日戳: 2008-12-27 10:54:17 
  19.  * 变更说明: 创建文件 
  20.  * 
  21.  *---------------------------------------------------------------------------- 
  22.  */  
  23.    
  24. /* 本文件需要引入的外部定义只有 struct tm 这个结构, 它的定义如下: 
  25.  *  struct tm 
  26.  *      { 
  27.  *      int tm_sec;     // seconds after the minute - [0, 59]  
  28.  *      int tm_min;     // minutes after the hour   - [0, 59]  
  29.  *      int tm_hour;    // hours after midnight     - [0, 23]  
  30.  *      int tm_mday;    // day of the month         - [1, 31]  
  31.  *      int tm_mon;     // months since January     - [0, 11]  
  32.  *      int tm_year;    // years since 1900  
  33.  *      int tm_wday;    // days since Sunday        - [0, 6]   
  34.  *      int tm_yday;    // days since January 1     - [0, 365] 
  35.  *      int tm_isdst;   // Daylight Saving Time flag  
  36.  *      }; 
  37.  * 
  38.  * 在上面这个结构中, 只有年月日时分秒6个必要的元素, 其它的数字可以计算得到. 
  39.  * 因为结构定义年从1900年开始, 而转换后的统一秒数只能达到136年, 所以目前能够识别 
  40.  * 的年限范围是在1900~2036年之间.  
  41.  * 本文件提供的字符串转日期目前只支持常见的中英文格式, 比如年月日, 时分秒,  
  42.  * 通常人能够直观读出的日期读数, 本文应该都可以识别, 比如: 
  43.  *  sep 3, 1995, 20:30      -> 1995-09-03 20:30:00 
  44.  *  3sep97                  -> 1997-09-03 00:00:00 
  45.  *  oct 4,03                -> 2003-10-04 00:00:00 
  46.  *  mon dec 29, 2008        -> 2008-12-29 00:00:00 
  47.  *  2011 nov 11, 11:11:11   -> 2011-11-11 11:11:11 
  48.  *  10:00am, 2008/9/1       -> 2008-09-01 10:00:00 
  49.  *  10/01/1976 3:01:05pm    -> 1976-10-01 15:01:05 
  50.  * 但产生歧议的日期, 比如 01/02/03, 本文将按照月份优先, 日期其次,  
  51.  * 最后是年份的格式将被解读成 2003年1月2日. 
  52.  * 
  53.  * 本文亦可识别一连串的数字组成的日期格式, 但月日时分秒必须使用两位十进制数表示. 
  54.  * 
  55.  * 若您还有其它不明事项, 可以运行strtotimeTest()函数进行检查. 在移植到PC机运行时 
  56.  * 只要改名为main()函数即可编译运行(请包含stdio.h头文件). 作者@2008-12-29 
  57.  * 
  58.  */  
  59.    
  60. #include <time.h>  
  61.   
  62. #define TOKEN_INIT      0  
  63. #define TOKEN_VAL       1  
  64. #define TOKEN_SEC       2  
  65. #define TOKEN_MIN       3  
  66. #define TOKEN_HOUR      4  
  67. #define TOKEN_HALFDAY   5  
  68. #define TOKEN_DAY       6  
  69. #define TOKEN_MONTH     7  
  70. #define TOKEN_YEAR      8  
  71. #define TOKEN_WEEKDAY   9  
  72.   
  73. #define STEP_INIT       0  
  74. #define STEP_DATE       1  
  75. #define STEP_TIME       2  
  76. #define STEP_OVER       3  
  77.   
  78. #define FLAG_SEC        0x0001  
  79. #define FLAG_MIN        0x0002  
  80. #define FLAG_HOUR       0x0004  
  81. #define FLAG_HALFDAY    0x0008  
  82. #define FLAG_DAY        0x0010  
  83. #define FLAG_MONTH      0x0020  
  84. #define FLAG_YEAR       0x0040  
  85. #define FLAG_TIME       0x0100  
  86. #define FLAG_DATE       0x0200  
  87. #define FLAG_ALPHA      0x1000  
  88.   
  89. static char s_cWeekDay[]    = "MonTueWedThuFriSatSun";  
  90. static char s_cWeekDayU[]   = "MONTUEWEDTHUFRISATSUN";  
  91. static char s_cWeekDayL[]   = "montuewedthufrisatsun";  
  92. static char s_cMonth[]      = "JanFebMarAprMayJunJulAugSepOctNovDec";  
  93. static char s_cMonthU[]     = "JANFEBMARAPRMAYJUNJULAUTSEPOCTNOVDEC";  
  94. static char s_cMonthL[]     = "janfebmaraprmayjunjulaugsepoctnovdec";  
  95. static int  s_iMonthFix[]   = {2, 0, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2};  
  96.   
  97. #define IsTimeDelim(a)  ((a) == ':')  
  98. #define IsDateDelim(a)  (isspace(a) || (a) == ',' || (a) == '.' || \  
  99.                          (a) == '-' || (a) == '/' || (a) == '\\')  
  100. #define LeapYear(year)  (((year) % 400 == 0) || \  
  101.                             (((year) % 100 != 0) && ((year) % 4 == 0)))  
  102.   
  103. /*****************************************************************************  
  104.  *  函数名称   : nextTimeToken(*) 
  105.  *  功能描述   : 找到下一个时间标记 
  106.  *  读全局变量 : 无 
  107.  *  写全局变量 : 无 
  108.  *  输入参数   : timeStr    - 时间日期字符串 
  109.  *  输出参数   : pVal       - 标记可以转换的年月日及时间的读数值 
  110.                  pFlag      - 类型标记, 标明解析的是数字, 还是有量纲的值 
  111.  *  返 回 值   : 解析过的字符长度, 失败时返回0 
  112.  *  其它说明   : 内部函数, 要求入参指针必须非空 
  113.  *--------------------------------------------------------------------------- 
  114.  * 历史记录(变更单, 责任人@修改日期, 操作说明) 
  115.  *  $0000000(N/A), 田瑞忠@2008-12-27 16:14:59 创建 
  116.  *---------------------------------------------------------------------------- 
  117.  */  
  118. static int nextTimeToken(char *timeStr, int *pVal, int *pFlag)  
  119. {  
  120.     char    *pChar = timeStr, *pCharEnd;  
  121.     int     iFlags = 0, iTemp;  
  122.   
  123.     *pFlag = TOKEN_INIT;  
  124.   
  125.     /* 跳过分隔符 */  
  126.     while (IsTimeDelim(*pChar) || IsDateDelim(*pChar))      
  127.     {  
  128.         pChar++;  
  129.     }  
  130.   
  131.     /* 是数值串, 直接返回数值 */  
  132.     if (isdigit(*pChar))  
  133.     {  
  134.         for (*pVal = 0, pCharEnd = pChar; isdigit(*pCharEnd); pCharEnd++)  
  135.         {  
  136.             *pVal = *pVal * 10 + (*pCharEnd - '0');  
  137.         }  
  138.   
  139.         /* 英文字母序号, 被指定为day */  
  140.         if (*(pCharEnd - 1) == '1' && strncmp(pCharEnd, "st", 2) == 0)  
  141.         {  
  142.             *pFlag = TOKEN_DAY, pCharEnd += 2;  
  143.         }  
  144.         else if (*(pCharEnd - 1) == '2' && strncmp(pCharEnd, "nd", 2) == 0)  
  145.         {  
  146.             *pFlag = TOKEN_DAY, pCharEnd += 2;  
  147.         }  
  148.         else if (*(pCharEnd - 1) == '3' && strncmp(pCharEnd, "rd", 2) == 0)  
  149.         {  
  150.             *pFlag = TOKEN_DAY, pCharEnd += 2;  
  151.         }  
  152.         else if (strncmp(pCharEnd, "th", 2) == 0)  
  153.         {  
  154.             *pFlag = TOKEN_DAY, pCharEnd += 2;  
  155.         }  
  156.           
  157.         if (*pFlag == TOKEN_DAY)  
  158.         {  
  159.             return pCharEnd - timeStr;  
  160.         }  
  161.   
  162. #if 1   /* 为中文服务, 可忽略 */  
  163.         /* 跳过空格, 以检查单位识别符 */  
  164.         while (isspace(*pChar))  
  165.         {  
  166.             pChar++;  
  167.         }  
  168.         /* 汉字量纲, 被特许为可识别的日期标识 */  
  169.         if (strncmp(pCharEnd, "年", 2) == 0)  
  170.         {  
  171.             *pFlag = TOKEN_YEAR, pCharEnd += 2;  
  172.         }  
  173.         else if (strncmp(pCharEnd, "月", 2) == 0)  
  174.         {  
  175.             *pFlag = TOKEN_MONTH, pCharEnd += 2;  
  176.         }  
  177.         else if (strncmp(pCharEnd, "日", 2) == 0)  
  178.         {  
  179.             *pFlag = TOKEN_DAY, pCharEnd += 2;  
  180.         }  
  181.         else if (strncmp(pCharEnd, "时", 2) == 0)  
  182.         {  
  183.             *pFlag = TOKEN_HOUR, pCharEnd += 2;  
  184.         }  
  185.         else if (strncmp(pCharEnd, "分", 2) == 0)  
  186.         {  
  187.             *pFlag = TOKEN_MIN, pCharEnd += 2;  
  188.         }  
  189.         else if (strncmp(pCharEnd, "秒", 2) == 0)  
  190.         {  
  191.             *pFlag = TOKEN_SEC, pCharEnd += 2;  
  192.         }  
  193.         else  
  194. #endif  
  195.         {  
  196.             *pFlag= TOKEN_VAL;  
  197.         }  
  198.         return pCharEnd - timeStr;  
  199.   
  200.     } /* (isdigit(*pChar)) */  
  201.       
  202.     /* 不是数值且不是字母(其它标点, 不可显示字符), 一般不被支持, 返回0 */  
  203.     if (!isalpha(*pChar))  
  204.     {  
  205.         if (*pChar >= 0)  
  206.         {  
  207.             return 0;  
  208.         }  
  209.         /* 非ASCII字符集, 比如是中文"星期一"之类, 跳过 */  
  210.         pCharEnd = pChar;  
  211.         while (*pCharEnd != ' ' && *pCharEnd != ',' && *pCharEnd != EOS)  
  212.         {  
  213.             pCharEnd++;  
  214.         }  
  215.         return pCharEnd - timeStr;  
  216.     } /* (!isdigit(*pChar) && !isalpha(*pChar)) */  
  217.           
  218.     /* 是字母, 检查是不是月份 */  
  219.     for (iTemp = 0; iTemp < 12; iTemp++)  
  220.     {  
  221.         if (strncmp(pChar, s_cMonth + iTemp * 3, 3) == 0)  
  222.         {  
  223.             *pVal = iTemp + 1;  
  224.             break;  
  225.         }  
  226.         else if (strncmp(pChar, s_cMonthL + iTemp * 3, 3) == 0)  
  227.         {  
  228.             *pVal = iTemp + 1;  
  229.             break;  
  230.         }  
  231.         else if (strncmp(pChar, s_cMonthU + iTemp * 3, 3) == 0)  
  232.         {  
  233.             *pVal = iTemp + 1;  
  234.             break;  
  235.         }  
  236.     } /* 月份字母检查 */  
  237.   
  238.     /* 找到月份字母, 跳过尾部字母 */  
  239.     if (iTemp < 12)  
  240.     {  
  241.         pCharEnd = pChar + 3;  
  242.         while (isalpha(*pCharEnd))  
  243.         {  
  244.             pCharEnd++;  
  245.         }  
  246.         *pFlag = TOKEN_MONTH;  
  247.         return pCharEnd - timeStr;  
  248.     }  
  249.       
  250.     /* 未找到月份字母, 则检查星期字母 */  
  251.     for (iTemp = 0; iTemp < 7; iTemp++)  
  252.     {  
  253.         if (strncmp(pChar, s_cWeekDay + iTemp * 3, 3) == 0)  
  254.         {  
  255.             *pVal = iTemp;  
  256.             break;  
  257.         }  
  258.         else if (strncmp(pChar, s_cWeekDayL + iTemp * 3, 3) == 0)  
  259.         {  
  260.             *pVal = iTemp;  
  261.             break;  
  262.         }  
  263.         else if (strncmp(pChar, s_cWeekDayU + iTemp * 3, 3) == 0)  
  264.         {  
  265.             *pVal = iTemp;  
  266.             break;  
  267.         }  
  268.     } /* 星期字母检查 */  
  269.   
  270.     /* 找到星期字母 */  
  271.     if (iTemp < 7)  
  272.     {  
  273.         pCharEnd = pChar + 3;  
  274.         while (isalpha(*pCharEnd))  
  275.         {  
  276.             pCharEnd++;  
  277.         }  
  278.         *pFlag = TOKEN_WEEKDAY;  
  279.         return pCharEnd - timeStr;  
  280.     }  
  281.       
  282.     /* 午前午后标志检查 */  
  283.     if (strncmp(pChar, "am", 2) == 0 || strncmp(pChar, "AM", 2) == 0)  
  284.     {  
  285.         pCharEnd = pChar + 2;  
  286.         if (!isalpha(*pCharEnd))  
  287.         {  
  288.             *pFlag = TOKEN_HALFDAY;  
  289.             *pVal  = 0;  
  290.             return pCharEnd - timeStr;  
  291.         }  
  292.     }  
  293.     if (strncmp(pChar, "pm", 2) == 0 || strncmp(pChar, "PM", 2) == 0)  
  294.     {  
  295.         pCharEnd = pChar + 2;  
  296.         if (!isalpha(*pCharEnd))  
  297.         {  
  298.             *pFlag = TOKEN_HALFDAY;  
  299.             *pVal  = 1;  
  300.             return pCharEnd - timeStr;  
  301.         }  
  302.     }  
  303.       
  304.     return 0;  
  305.   
  306. /* nextTimeToken() */  
  307.   
  308. /*****************************************************************************  
  309.  *  函数名称   : digit2time(*) 
  310.  *  功能描述   : 将日期数字转换为时间结构, 必须按年月日时分秒排列, 否则看不懂 
  311.  *  读全局变量 : 无 
  312.  *  写全局变量 : 无 
  313.  *  输入参数   : timeStr    - 时间日期字符串 
  314.                  iLen       - 时间日期字符串长度 
  315.  *  输出参数   : ptTime     - 日期时间结构 
  316.  *  返 回 值   : 年月日时分秒有效的标志 
  317.  *  其它说明   : 歧义和冲突处理, 按排列的优先顺序进行 
  318.  *--------------------------------------------------------------------------- 
  319.  * 历史记录(变更单, 责任人@修改日期, 操作说明) 
  320.  *  $0000000(N/A), 田瑞忠@2008-12-28 10:47:31 创建 
  321.  *---------------------------------------------------------------------------- 
  322.  */  
  323. static int digit2time(char *timeStr, int iLen, struct tm *ptTime)  
  324. {  
  325.     char    *pChar = timeStr;  
  326.   
  327.     memset(ptTime, 0, sizeof(*ptTime));  
  328.   
  329.     if (iLen < 6 || iLen % 2 != 0)  
  330.     {  
  331.         return 0;  
  332.     }  
  333.   
  334.     /* 允许的日期时间格式(按常用频度排列): 5 + 4 + 3 + 2 + 1 = 15  
  335.         纪年月日时分秒  - YYYYMMDDHHmmss 
  336.         年月日时分秒    - YYMMDDHHmmss 
  337.         纪年月日时分    - YYYYMMDDHHmm 
  338.         月日时分秒      - MMDDHHmmss 
  339.         年月日时分      - YYMMDDHHmm 
  340.         纪年月日时      - YYYYMMDDHH 
  341.         月日时分        - MMDDHHmm 
  342.         纪年月日        - YYYYMMDD 
  343.         日时分秒        - DDHHmmss 
  344.         年月日时        - YYMMDDHH 
  345.         年月日          - YYMMDD 
  346.         纪年月          - YYYYMM 
  347.         时分秒          - HHmmss 
  348.         日时分          - DDHHmm 
  349.         月日时          - MMDDHH 
  350.     */  
  351.   
  352.     /* 超长格式, 只有: YYYYMMDDHHmmss */  
  353.     if (iLen >= 14)  
  354.     {  
  355.         ptTime->tm_year = (pChar[0] - '0') * 1000 + (pChar[1] - '0') * 100 +   
  356.             (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  357.         ptTime->tm_mon  = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  358.         ptTime->tm_mday = (pChar[6] - '0') * 10 + (pChar[7] - '0');  
  359.         ptTime->tm_hour = (pChar[8] - '0') * 10 + (pChar[9] - '0');  
  360.         ptTime->tm_min  = (pChar[10] - '0') * 10 + (pChar[11] - '0');  
  361.         ptTime->tm_sec  = (pChar[12] - '0') * 10 + (pChar[13] - '0');  
  362.         if (ptTime->tm_year >= 1900 && ptTime->tm_year < 2036 &&  
  363.             ptTime->tm_mon < 13 &&   
  364.             ptTime->tm_mday <= 29 + s_iMonthFix[ptTime->tm_mon - 1] &&  
  365.             ptTime->tm_hour < 24 && ptTime->tm_min < 60 && ptTime->tm_sec < 60)  
  366.         {  
  367.             return FLAG_SEC | FLAG_MIN | FLAG_HOUR |   
  368.                 FLAG_DAY | FLAG_MONTH | FLAG_YEAR;  
  369.         }  
  370.     }  
  371.     /* 次长格式, 有: YYYYMMDDHHmm, YYMMDDHHmmss */  
  372.     else if (iLen == 12)  
  373.     {  
  374.         /* YYYYMMDDHHmm */  
  375.         ptTime->tm_year = (pChar[0] - '0') * 1000 + (pChar[1] - '0') * 100 +   
  376.             (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  377.         ptTime->tm_mon  = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  378.         ptTime->tm_mday = (pChar[6] - '0') * 10 + (pChar[7] - '0');  
  379.         ptTime->tm_hour = (pChar[8] - '0') * 10 + (pChar[9] - '0');  
  380.         ptTime->tm_min  = (pChar[10] - '0') * 10 + (pChar[11] - '0');  
  381.         if (ptTime->tm_year >= 1900 && ptTime->tm_year < 2036 &&  
  382.             ptTime->tm_mon < 13 &&   
  383.             ptTime->tm_mday <= 29 + s_iMonthFix[ptTime->tm_mon - 1] &&  
  384.             ptTime->tm_hour < 24 && ptTime->tm_min < 60)  
  385.         {  
  386.             return FLAG_MIN | FLAG_HOUR | FLAG_DAY | FLAG_MONTH | FLAG_YEAR;  
  387.         }  
  388.         /* YYMMDDHHmmss */  
  389.         ptTime->tm_year = (pChar[0] - '0') * 10 + (pChar[1] - '0');  
  390.         ptTime->tm_year+= (ptTime->tm_year >= 70) ? 1900 : 2000;  
  391.         ptTime->tm_mon  = (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  392.         ptTime->tm_mday = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  393.         ptTime->tm_hour = (pChar[6] - '0') * 10 + (pChar[7] - '0');  
  394.         ptTime->tm_min  = (pChar[8] - '0') * 10 + (pChar[9] - '0');  
  395.         ptTime->tm_sec  = (pChar[10] - '0') * 10 + (pChar[11] - '0');  
  396.         if (ptTime->tm_year >= 1900 && ptTime->tm_year < 2036 &&  
  397.             ptTime->tm_mon < 13 &&   
  398.             ptTime->tm_mday <= 29 + s_iMonthFix[ptTime->tm_mon - 1] &&  
  399.             ptTime->tm_hour < 24 && ptTime->tm_min < 60 && ptTime->tm_sec < 60)  
  400.         {  
  401.             return FLAG_SEC | FLAG_MIN | FLAG_HOUR |   
  402.                 FLAG_DAY | FLAG_MONTH | FLAG_YEAR;  
  403.         }  
  404.     } /* (iLen == 12) */  
  405.     /* 10字节, 有: MMDDHHmmss, YYMMDDHHmm, YYYYMMDDHH */  
  406.     else if (iLen == 10)  
  407.     {  
  408.         /* MMDDHHmmss */  
  409.         ptTime->tm_mon  = (pChar[0] - '0') * 10 + (pChar[1] - '0');  
  410.         ptTime->tm_mday = (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  411.         ptTime->tm_hour = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  412.         ptTime->tm_min  = (pChar[6] - '0') * 10 + (pChar[7] - '0');  
  413.         ptTime->tm_sec  = (pChar[8] - '0') * 10 + (pChar[9] - '0');  
  414.         if (ptTime->tm_mon < 13 &&   
  415.             ptTime->tm_mday <= 29 + s_iMonthFix[ptTime->tm_mon - 1] &&  
  416.             ptTime->tm_hour < 24 && ptTime->tm_min < 60 && ptTime->tm_sec < 60)  
  417.         {  
  418.             return FLAG_SEC | FLAG_MIN | FLAG_HOUR | FLAG_DAY | FLAG_MONTH;  
  419.         }  
  420.         /* YYMMDDHHmm */  
  421.         ptTime->tm_year = (pChar[0] - '0') * 10 + (pChar[1] - '0');  
  422.         ptTime->tm_year+= (ptTime->tm_year >= 70) ? 1900 : 2000;  
  423.         ptTime->tm_mon  = (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  424.         ptTime->tm_mday = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  425.         ptTime->tm_hour = (pChar[6] - '0') * 10 + (pChar[7] - '0');  
  426.         ptTime->tm_min  = (pChar[8] - '0') * 10 + (pChar[9] - '0');  
  427.         if (ptTime->tm_year >= 1900 && ptTime->tm_year < 2036 &&  
  428.             ptTime->tm_mon < 13 &&   
  429.             ptTime->tm_mday <= 29 + s_iMonthFix[ptTime->tm_mon - 1] &&  
  430.             ptTime->tm_hour < 24 && ptTime->tm_min < 60)  
  431.         {  
  432.             return FLAG_MIN | FLAG_HOUR | FLAG_DAY | FLAG_MONTH | FLAG_YEAR;  
  433.         }  
  434.         /* YYYYMMDDHH */  
  435.         ptTime->tm_year = (pChar[0] - '0') * 1000 + (pChar[1] - '0') * 100 +   
  436.             (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  437.         ptTime->tm_mon  = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  438.         ptTime->tm_mday = (pChar[6] - '0') * 10 + (pChar[7] - '0');  
  439.         ptTime->tm_hour = (pChar[8] - '0') * 10 + (pChar[9] - '0');  
  440.         if (ptTime->tm_hour < 24 &&   
  441.             ptTime->tm_year >= 1900 && ptTime->tm_year < 2036 &&  
  442.             ptTime->tm_mon < 13 &&   
  443.             ptTime->tm_mday <= 29 + s_iMonthFix[ptTime->tm_mon - 1])  
  444.         {  
  445.             return FLAG_HOUR | FLAG_DAY | FLAG_MONTH | FLAG_YEAR;  
  446.         }  
  447.     } /* (iLen == 10) */  
  448.     /* 8字节, 有: MMDDHHmm, YYYYMMDD, DDHHmmss, YYMMDDHH */  
  449.     else if (iLen == 8)  
  450.     {  
  451.         /* MMDDHHmm */  
  452.         ptTime->tm_mon  = (pChar[0] - '0') * 10 + (pChar[1] - '0');  
  453.         ptTime->tm_mday = (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  454.         ptTime->tm_hour = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  455.         ptTime->tm_min  = (pChar[6] - '0') * 10 + (pChar[7] - '0');  
  456.         if (ptTime->tm_mon < 13 &&   
  457.             ptTime->tm_mday <= 29 + s_iMonthFix[ptTime->tm_mon - 1] &&  
  458.             ptTime->tm_hour < 24 && ptTime->tm_min < 60)  
  459.         {  
  460.             return FLAG_MIN | FLAG_HOUR | FLAG_DAY | FLAG_MONTH;  
  461.         }  
  462.         /* YYYYMMDD */  
  463.         ptTime->tm_year = (pChar[0] - '0') * 1000 + (pChar[1] - '0') * 100 +   
  464.             (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  465.         ptTime->tm_mon  = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  466.         ptTime->tm_mday = (pChar[6] - '0') * 10 + (pChar[7] - '0');  
  467.         if (ptTime->tm_year >= 1900 && ptTime->tm_year < 2036 &&  
  468.             ptTime->tm_mon < 13 &&   
  469.             ptTime->tm_mday <= 29 + s_iMonthFix[ptTime->tm_mon - 1])  
  470.         {  
  471.             return FLAG_DAY | FLAG_MONTH | FLAG_YEAR;  
  472.         }  
  473.         /* DDHHmmss */  
  474.         ptTime->tm_mday = (pChar[0] - '0') * 10 + (pChar[1] - '0');  
  475.         ptTime->tm_hour = (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  476.         ptTime->tm_min  = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  477.         ptTime->tm_sec  = (pChar[6] - '0') * 10 + (pChar[7] - '0');  
  478.         if (ptTime->tm_mday <= 31 && ptTime->tm_hour < 24 &&   
  479.             ptTime->tm_min < 60 && ptTime->tm_sec < 60)  
  480.         {  
  481.             return FLAG_SEC | FLAG_MIN | FLAG_HOUR | FLAG_DAY;  
  482.         }  
  483.         /* YYMMDDHH */  
  484.         ptTime->tm_year = (pChar[0] - '0') * 10 + (pChar[1] - '0');  
  485.         ptTime->tm_year+= (ptTime->tm_year >= 70) ? 1900 : 2000;  
  486.         ptTime->tm_mon  = (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  487.         ptTime->tm_mday = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  488.         ptTime->tm_hour = (pChar[6] - '0') * 10 + (pChar[7] - '0');  
  489.         if (ptTime->tm_hour < 24 &&   
  490.             ptTime->tm_year >= 1900 && ptTime->tm_year < 2036 &&  
  491.             ptTime->tm_mon < 13 &&   
  492.             ptTime->tm_mday <= 29 + s_iMonthFix[ptTime->tm_mon - 1])  
  493.         {  
  494.             return FLAG_HOUR | FLAG_DAY | FLAG_MONTH | FLAG_YEAR;  
  495.         }  
  496.     } /* (iLen == 8) */  
  497.     else  
  498.     {  
  499.         /* YYMMDD */  
  500.         ptTime->tm_year = (pChar[0] - '0') * 10 + (pChar[1] - '0');  
  501.         ptTime->tm_year+= (ptTime->tm_year >= 70) ? 1900 : 2000;  
  502.         ptTime->tm_mon  = (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  503.         ptTime->tm_mday = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  504.         if (ptTime->tm_year >= 1900 && ptTime->tm_year < 2036 &&  
  505.             ptTime->tm_mon < 13 &&   
  506.             ptTime->tm_mday <= 29 + s_iMonthFix[ptTime->tm_mon - 1])  
  507.         {  
  508.             return FLAG_DAY | FLAG_MONTH | FLAG_YEAR;  
  509.         }  
  510.         /* YYYYMM */  
  511.         ptTime->tm_year = (pChar[0] - '0') * 1000 + (pChar[1] - '0') * 100 +   
  512.             (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  513.         ptTime->tm_mon  = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  514.         if (ptTime->tm_year >= 1900 && ptTime->tm_year < 2036 &&   
  515.             ptTime->tm_mon < 13)  
  516.         {  
  517.             return FLAG_MONTH | FLAG_YEAR;  
  518.         }  
  519.         /* HHmmss */  
  520.         ptTime->tm_hour = (pChar[0] - '0') * 10 + (pChar[1] - '0');  
  521.         ptTime->tm_min  = (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  522.         ptTime->tm_sec  = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  523.         if (ptTime->tm_hour < 24 && ptTime->tm_min < 60 && ptTime->tm_sec < 60)  
  524.         {  
  525.             return FLAG_SEC | FLAG_MIN | FLAG_HOUR;  
  526.         }  
  527.         /* DDHHmm */  
  528.         ptTime->tm_mday = (pChar[0] - '0') * 10 + (pChar[1] - '0');  
  529.         ptTime->tm_hour = (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  530.         ptTime->tm_min  = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  531.         if (ptTime->tm_mday <= 31 && ptTime->tm_hour < 24 && ptTime->tm_min < 60)  
  532.         {  
  533.             return FLAG_MIN | FLAG_HOUR | FLAG_DAY;  
  534.         }  
  535.         /* MMDDHH */  
  536.         ptTime->tm_mon  = (pChar[0] - '0') * 10 + (pChar[1] - '0');  
  537.         ptTime->tm_mday = (pChar[2] - '0') * 10 + (pChar[3] - '0');  
  538.         ptTime->tm_hour = (pChar[4] - '0') * 10 + (pChar[5] - '0');  
  539.         if (ptTime->tm_mon < 13 &&   
  540.             ptTime->tm_mday <= 29 + s_iMonthFix[ptTime->tm_mon - 1] &&   
  541.             ptTime->tm_hour < 24)  
  542.         {  
  543.             return FLAG_HOUR | FLAG_DAY | FLAG_MONTH;  
  544.         }  
  545.     } /* (iLen == 6) */  
  546.   
  547.     return 0;  
  548. /* digit2time() */  
  549.   
  550. /*****************************************************************************  
  551.  *  函数名称   : strtotime(*) 
  552.  *  功能描述   : 将日期及(或)时间字符串转换为时间结构, 例: Dec 19 2008, 13:35:40 
  553.  *  读全局变量 : 无 
  554.  *  写全局变量 : 无 
  555.  *  输入参数   : timeStr    - 时间日期字符串 
  556.  *  输出参数   : ptTime     - 日期时间结构 
  557.  *  返 回 值   : 年月日时分秒有效的标志 
  558.  *  其它说明   : 时分秒之间必须使用冒号":"分隔, 并且必然是此顺序 
  559.  *--------------------------------------------------------------------------- 
  560.  * 历史记录(变更单, 责任人@修改日期, 操作说明) 
  561.  *  $0000000(N/A), 田瑞忠@2008-12-27 16:14:59 创建 
  562.  *---------------------------------------------------------------------------- 
  563.  */  
  564. static int strtotime(char *timeStr, struct tm *ptTime)  
  565. {  
  566.     int     iFlags, iVal, iLen, iStep, iDateTimeFlag;  
  567.     int     iYear, iMonth, iDay, iHour, iMinute, iSecond;  
  568.     char    *pChar = timeStr, *pCharEnd = timeStr, tempStr[8];  
  569.   
  570.     iDateTimeFlag = iYear = iMonth = iDay = iHour = iMinute = iSecond = 0;  
  571.     memset(ptTime, 0, sizeof(*ptTime));  
  572.   
  573.     /* 跳过前导空格 */  
  574.     while (*pChar == ' ' || *pChar == '\t')      
  575.     {  
  576.         pChar++;  
  577.     }  
  578.   
  579.     /* 不存在可解析的中间字符串 */  
  580.     if ((iLen = nextTimeToken(pChar, &iVal, &iFlags)) <= 0)  
  581.     {  
  582.         return iDateTimeFlag;  
  583.     }  
  584.   
  585.     /* 数值串且长度大于等于6, 则为全数字型日期时间, 如20081229080306  
  586.      * 需要重新解析 */  
  587.     if (iFlags == TOKEN_VAL && iLen >= 6 && iLen % 2 == 0)  
  588.     {  
  589.         iDateTimeFlag = digit2time(pChar, iLen, ptTime);  
  590.         if (iDateTimeFlag == 0)  
  591.         {  
  592.             memset(ptTime, 0, sizeof(*ptTime));  
  593.         }  
  594.         /* 由于进行了值尝试, 当不适用时, 要清除尝试值 */  
  595.         ptTime->tm_year =  
  596.                 (iDateTimeFlag & FLAG_YEAR) ? ptTime->tm_year - 1900 : 0;  
  597.   
  598.         ptTime->tm_mon  =  
  599.                 (iDateTimeFlag & FLAG_MONTH) ? ptTime->tm_mon - 1 : 0;  
  600.   
  601.         if ((iDateTimeFlag & FLAG_DAY) == 0)  
  602.         {  
  603.             ptTime->tm_mday = 1;  
  604.         }  
  605.         if ((iDateTimeFlag & FLAG_HOUR) == 0)  
  606.         {  
  607.             ptTime->tm_hour = 0;  
  608.         }  
  609.         if ((iDateTimeFlag & FLAG_MIN) == 0)  
  610.         {  
  611.             ptTime->tm_min = 0;  
  612.         }  
  613.         if ((iDateTimeFlag & FLAG_SEC) == 0)  
  614.         {  
  615.             ptTime->tm_sec = 0;  
  616.         }  
  617.         if (!iDateTimeFlag)  
  618.         {  
  619.             goto strToTimeErrOut;  
  620.         }  
  621.         return iDateTimeFlag;  
  622.     }  
  623.   
  624.     /* 否则各字段之间必然有分隔符(或数字英文分隔, 比如 22sep92) */  
  625.     for (iStep = STEP_INIT; *pChar != EOS && iLen > 0;  
  626.         pChar += iLen, iLen = nextTimeToken(pChar, &iVal, &iFlags))  
  627.     {  
  628.         /* 强格式年份, 直接填充到年份信息中 */  
  629.         if (iFlags == TOKEN_YEAR)  
  630.         {  
  631.             if ((iDateTimeFlag & FLAG_YEAR) == 0)  
  632.             {  
  633.                 iYear = iVal, iDateTimeFlag |= FLAG_YEAR;  
  634.             }  
  635.             else  
  636.             {  
  637.                 goto strToTimeErrOut;  
  638.             }  
  639.             iStep = STEP_DATE, iDateTimeFlag |= FLAG_DATE;  
  640.             continue;  
  641.         }  
  642.         /* 强格式月份, 直接填充到月份信息中(否则需要试探比较) */  
  643.         else if (iFlags == TOKEN_MONTH)  
  644.         {  
  645.             if ((iDateTimeFlag & FLAG_MONTH) == 0)  
  646.             {  
  647.                 iMonth = iVal, iDateTimeFlag |= FLAG_ALPHA | FLAG_MONTH;  
  648.             }  
  649.             /* 有月份信息但非字母指定, 说明是试探, 则将其移走(值必居于1~12) */  
  650.             else if ((iDateTimeFlag & FLAG_ALPHA) == 0)  
  651.             {  
  652.                 if ((iDateTimeFlag & FLAG_DAY) == 0)  
  653.                 {  
  654.                     iDay = iMonth, iDateTimeFlag |= FLAG_DAY;  
  655.                 }  
  656.                 else if ((iDateTimeFlag & FLAG_YEAR) == 0) /* 2001 ~ 2012年 */  
  657.                 {  
  658.                     iYear = iMonth, iDateTimeFlag |= FLAG_YEAR;  
  659.                 }  
  660.                 else  
  661.                 {  
  662.                     goto strToTimeErrOut;  
  663.                 }  
  664.                 iMonth = iVal, iDateTimeFlag |= FLAG_ALPHA;  
  665.             }  
  666.             else  
  667.             {  
  668.                 goto strToTimeErrOut;  
  669.             }  
  670.             iStep = STEP_DATE, iDateTimeFlag |= FLAG_DATE;  
  671.             continue;  
  672.         } /* (iFlags == TOKEN_MONTH) */  
  673.         /* 强格式日期, 直接填充到日期信息中 */  
  674.         else if (iFlags == TOKEN_DAY)  
  675.         {  
  676.             if ((iDateTimeFlag & FLAG_DAY) == 0)  
  677.             {  
  678.                 iDay = iVal, iDateTimeFlag |= FLAG_DAY;  
  679.             }  
  680.             else  
  681.             {  
  682.                 goto strToTimeErrOut;  
  683.             }  
  684.             iStep = STEP_DATE, iDateTimeFlag |= FLAG_DATE;  
  685.             continue;  
  686.         }  
  687.         /* 半日信息(上午, 下午, 必然在时间后, 不然不予认可) */  
  688.         else if (iFlags == TOKEN_HALFDAY)  
  689.         {  
  690.             if ((iDateTimeFlag & FLAG_HALFDAY) == 0 &&  
  691.                 iHour + iVal * 12 < 24)  
  692.             {  
  693.                 iHour += iVal * 12, iDateTimeFlag |= FLAG_HALFDAY;  
  694.             }  
  695.             else  
  696.             {  
  697.                 goto strToTimeErrOut;  
  698.             }  
  699.             iStep = STEP_TIME, iDateTimeFlag |= FLAG_TIME;  
  700.             continue;  
  701.         }  
  702.         /* 强格式小时, 直接填充到小时信息中 */  
  703.         else if (iFlags == TOKEN_HOUR)  
  704.         {  
  705.             if ((iDateTimeFlag & FLAG_HOUR) == 0 && iVal < 24)  
  706.             {  
  707.                 iHour = iVal, iDateTimeFlag |= FLAG_HOUR;  
  708.             }  
  709.             else  
  710.             {  
  711.                 goto strToTimeErrOut;  
  712.             }  
  713.             iStep = STEP_TIME, iDateTimeFlag |= FLAG_TIME;  
  714.             continue;  
  715.         }  
  716.         /* 强格式分钟, 直接填充到分钟信息中 */  
  717.         else if (iFlags == TOKEN_MIN)  
  718.         {  
  719.             if ((iDateTimeFlag & FLAG_MIN) == 0 && iVal < 60)  
  720.             {  
  721.                 iMinute = iVal, iDateTimeFlag |= FLAG_MIN;  
  722.             }  
  723.             else  
  724.             {  
  725.                 goto strToTimeErrOut;  
  726.             }  
  727.             iStep = STEP_TIME, iDateTimeFlag |= FLAG_TIME;  
  728.             continue;  
  729.         }  
  730.         /* 强格式秒, 直接填充到秒信息中 */  
  731.         else if (iFlags == TOKEN_SEC)  
  732.         {  
  733.             if ((iDateTimeFlag & FLAG_SEC) == 0 && iVal < 60)  
  734.             {  
  735.                 iSecond = iVal, iDateTimeFlag |= FLAG_SEC;  
  736.             }  
  737.             else  
  738.             {  
  739.                 goto strToTimeErrOut;  
  740.             }  
  741.             iStep = STEP_TIME, iDateTimeFlag |= FLAG_TIME;  
  742.             continue;  
  743.         }  
  744.   
  745.         /* 不是数值, 跳过 */  
  746.         if (iFlags != TOKEN_VAL)  
  747.         {  
  748.             continue;  
  749.         }  
  750.   
  751.         /* 标记尾碰到时间分隔符, 则直接进入时间信息处理区 */  
  752.         if (IsTimeDelim(pChar[iLen]))  
  753.         {  
  754.             if ((iDateTimeFlag & FLAG_TIME) == 0)  
  755.             {  
  756.                 iStep = STEP_TIME, iDateTimeFlag |= FLAG_TIME;  
  757.             }  
  758.             /* 如果时间信息已获取, 且在处理日期状态, 则跳过 */  
  759.             else if (iStep == STEP_DATE)  
  760.             {  
  761.                 iStep = STEP_OVER;  
  762.             }  
  763.         }  
  764.         /* 时间信息处理区, 但没有碰到时间分隔符, 则要切换处理区 */  
  765.         else if (iStep == STEP_TIME)  
  766.         {  
  767.             if (IsTimeDelim(pChar[0]))  
  768.             {  
  769.                 /* 最后一个字段, 状态保持 */;  
  770.             }  
  771.             else if ((iDateTimeFlag & FLAG_DATE) == 0)  
  772.             {  
  773.                 iStep = STEP_DATE, iDateTimeFlag |= FLAG_DATE;  
  774.             }  
  775.             /* 如果日期信息已获取, 且在处理时间状态, 则跳过 */  
  776.             else  
  777.             {  
  778.                 iStep = STEP_OVER;  
  779.             }  
  780.         }  
  781.         /* 默认情况下都是处理日期 */  
  782.         else  
  783.         {  
  784.             iStep = STEP_DATE;  
  785.         }  
  786.   
  787.         /* 处理时间: 时分秒, 逐次检查(秒可能被省略) */  
  788.         if (iStep == STEP_TIME)  
  789.         {  
  790.             if ((iDateTimeFlag & FLAG_HOUR) == 0)  
  791.             {  
  792.                 if (iVal >= 0 && iVal <= 23)  
  793.                 {  
  794.                     iHour = iVal, iDateTimeFlag |= FLAG_HOUR;  
  795.                 }  
  796.                 else  
  797.                 {  
  798.                     goto strToTimeErrOut;  
  799.                 }  
  800.             }  
  801.             else if ((iDateTimeFlag & FLAG_MIN) == 0)  
  802.             {  
  803.                 if (iVal >= 0 && iVal <= 59)  
  804.                 {  
  805.                     iMinute = iVal, iDateTimeFlag |= FLAG_MIN;  
  806.                 }  
  807.                 else  
  808.                 {  
  809.                     goto strToTimeErrOut;  
  810.                 }  
  811.             }  
  812.             else if ((iDateTimeFlag & FLAG_SEC) == 0)  
  813.             {  
  814.                 if (iVal >= 0 && iVal <= 59)  
  815.                 {  
  816.                     iSecond = iVal, iDateTimeFlag |= FLAG_SEC;  
  817.                 }  
  818.                 else  
  819.                 {  
  820.                     goto strToTimeErrOut;  
  821.                 }  
  822.             }  
  823.             else /* 多余的时间数据, 则认为字符串不合法 */  
  824.             {  
  825.                 goto strToTimeErrOut;  
  826.             }  
  827.   
  828.             continue;  
  829.   
  830.         } /* if (iStep == STEP_TIME) */  
  831.   
  832.         /* 日期处理, 日期格式只有三种: 月日年, 日月年, 年月日, 03oct01?  
  833.          * 歧议日期一律按"月日年"顺序处理, 上例是01年10月3日而不是03年10月1日 */  
  834.           
  835.         /* 四位数字年份, 毫无疑问直接填充 */  
  836.         if (iVal >= 1900 && iVal <= 2036)  
  837.         {  
  838.             if ((iDateTimeFlag & FLAG_YEAR) == 0)  
  839.             {  
  840.                 iYear = iVal, iDateTimeFlag |= FLAG_YEAR;  
  841.             }  
  842.             else  
  843.             {  
  844.                 goto strToTimeErrOut;  
  845.             }  
  846.         }  
  847.         /* 两位数字无争议年份, 填充 */  
  848.         else if (iVal == 0 || (iVal >= 70 && iVal <= 99))  
  849.         {  
  850.             if ((iDateTimeFlag & FLAG_YEAR) == 0)  
  851.             {  
  852.                 iYear = iVal, iDateTimeFlag |= FLAG_YEAR;  
  853.             }  
  854.             else  
  855.             {  
  856.                 goto strToTimeErrOut;  
  857.             }  
  858.         }  
  859.         else if (iVal <= 12)    /* 小于12的数字, 年月日都可以 */  
  860.         {  
  861.             /* 写入月份读数时要检测日期读数冲突 */  
  862.             if ((iDateTimeFlag & FLAG_MONTH) == 0)  
  863.             {  
  864.                 if ((iDateTimeFlag & FLAG_DAY) == 0 ||  
  865.                     iDay <= 29 + s_iMonthFix[iVal - 1])  
  866.                 {  
  867.                     iMonth = iVal, iDateTimeFlag |= FLAG_MONTH;  
  868.                 }  
  869.                 else if ((iDateTimeFlag & FLAG_YEAR) == 0)  
  870.                 {  
  871.                     iYear = iVal, iDateTimeFlag |= FLAG_YEAR;  
  872.                 }  
  873.                 else  
  874.                 {  
  875.                     goto strToTimeErrOut;  
  876.                 }  
  877.             }  
  878.             else if ((iDateTimeFlag & FLAG_DAY) == 0)  
  879.             {  
  880.                 iDay = iVal, iDateTimeFlag |= FLAG_DAY;  
  881.             }  
  882.             else if ((iDateTimeFlag & FLAG_YEAR) == 0)  
  883.             {  
  884.                 iYear = iVal, iDateTimeFlag |= FLAG_YEAR;  
  885.             }  
  886.             else  
  887.             {  
  888.                 goto strToTimeErrOut;  
  889.             }  
  890.         }  
  891.         else if (iVal <= 31 /* && iVal > 12 */)  
  892.         {  
  893.             /* 写入日期读数时要检测月份读数冲突 */  
  894.             if ((iDateTimeFlag & FLAG_DAY) == 0)  
  895.             {  
  896.                 if ((iDateTimeFlag & FLAG_MONTH) == 0 ||  
  897.                     iVal <= 29 + s_iMonthFix[iMonth - 1])  
  898.                 {  
  899.                     iDay = iVal, iDateTimeFlag |= FLAG_DAY;  
  900.                 }  
  901.                 else if ((iDateTimeFlag & FLAG_YEAR) == 0)  
  902.                 {  
  903.                     iYear = iVal, iDateTimeFlag |= FLAG_YEAR;  
  904.                 }  
  905.                 else  
  906.                 {  
  907.                     goto strToTimeErrOut;  
  908.                 }  
  909.             }  
  910.             else if ((iDateTimeFlag & FLAG_YEAR) == 0)  
  911.             {  
  912.                 iYear = iVal, iDateTimeFlag |= FLAG_YEAR;  
  913.             }  
  914.             else  
  915.             {  
  916.                 goto strToTimeErrOut;  
  917.             }  
  918.         }  
  919.         else if (iVal > 31 && iVal <= 36)  
  920.         {  
  921.             if ((iDateTimeFlag & FLAG_YEAR) == 0)  
  922.             {  
  923.                 iYear = iVal, iDateTimeFlag |= FLAG_YEAR;  
  924.             }  
  925.             else  
  926.             {  
  927.                 goto strToTimeErrOut;  
  928.             }  
  929.         }  
  930.         else /* 不合法的读数 */  
  931.         {  
  932.             goto strToTimeErrOut;  
  933.         }  
  934.               
  935.     } /* while (*pChar != EOS && iLen > 0) */  
  936.   
  937.     /* 对于存在歧议的日期及时间, 目前的默认顺序是: 月份, 日期, 年份 
  938.      * 使用这个规则的原因在于, 月份的限制最严格(1~12), 其次日期(1~31), 年份任意, 
  939.      * 按这个顺序填入日期读数, 可以避免冲突数据的搬移操作,  
  940.      * 要改变这个默认规则, 只需在下面检查是否存在歧议, 然后修改顺序即可 */  
  941.   
  942.     /* 年份读数转换为内部表示 */  
  943.     if (iDateTimeFlag & FLAG_YEAR)  
  944.     {  
  945.         if (iYear > 2036)  
  946.         {  
  947.             goto strToTimeErrOut;  
  948.         }  
  949.         else if (iYear >= 1900)  
  950.         {  
  951.             ptTime->tm_year = iYear - 1900;  
  952.         }  
  953.         else if (iYear >= 0 && iYear < 36)  
  954.         {  
  955.             ptTime->tm_year = iYear + 100;  
  956.         }  
  957.         else if (iYear >= 70 && iYear <= 99)  
  958.         {  
  959.             ptTime->tm_year = iYear;  
  960.         }  
  961.         else  
  962.         {  
  963.             goto strToTimeErrOut;  
  964.     }  
  965.     } /* (iDateTimeFlag & FLAG_YEAR) */  
  966.   
  967.     /* 月份读数也要转换为内部表示(0~11) */  
  968.     if (iDateTimeFlag & FLAG_MONTH)  
  969.     {  
  970.         if (iMonth < 1 || iMonth > 12)  
  971.         {  
  972.             goto strToTimeErrOut;  
  973.         }  
  974.         ptTime->tm_mon  = iMonth - 1;  
  975.     }  
  976.   
  977.     /* 日期, 要查看是否满足条件 */  
  978.     if (iDateTimeFlag & FLAG_DAY)  
  979.     {  
  980.         if ((iDay > 29 + s_iMonthFix[ptTime->tm_mon]) ||  
  981.             (ptTime->tm_mon == 1 && !LeapYear(iYear) && iDay > 28))  
  982.         {  
  983.             goto strToTimeErrOut;  
  984.         }  
  985.     ptTime->tm_mday = iDay;  
  986.     }  
  987.     else  
  988.     {  
  989.         ptTime->tm_mday = 1;  
  990.     }  
  991.       
  992.     /* 时间值在赋值时都是合法的 */  
  993.     ptTime->tm_hour = iHour;  
  994.     ptTime->tm_min  = iMinute;  
  995.     ptTime->tm_sec  = iSecond;  
  996.       
  997.     return iDateTimeFlag;  
  998.   
  999. strToTimeErrOut:  
  1000.     memset(ptTime, 0, sizeof(*ptTime));  
  1001.     ptTime->tm_mday = 1;  
  1002.     printf("Unrecognized date and/or time string:\n%s\n", timeStr);  
  1003.     return 0;  
  1004. /* strtotime() */  
  1005.   
  1006. /*****************************************************************************  
  1007.  *  函数名称   : strtotimeTest(*) 
  1008.  *  功能描述   : 字符串转换为日期时间函数测试, 可以反复验证转换函数的正确性  
  1009.  *  读全局变量 : 无 
  1010.  *  写全局变量 : 无 
  1011.  *  输入参数   : 等待用户输入 
  1012.  *  输出参数   : 无 
  1013.  *  返 回 值   : OK 
  1014.  *  其它说明   : 修改为main()函数后可在PC上调试 
  1015.  *--------------------------------------------------------------------------- 
  1016.  * 历史记录(变更单, 责任人@修改日期, 操作说明) 
  1017.  *  $0000000(N/A), 田瑞忠@2008-12-28 20:42:26 
  1018.  *---------------------------------------------------------------------------- 
  1019.  */  
  1020. int strtotimeTest(void)  
  1021. {  
  1022.     char    charbuf[80];  
  1023.     struct tm timeStru;  
  1024.     int     iret;  
  1025.   
  1026.     while (1)  
  1027.     {  
  1028.         printf("Input string to be converted, 'q' for quit:\n");  
  1029.         gets(charbuf);  
  1030.         if (charbuf[0] == 'q')  
  1031.         {  
  1032.             break;  
  1033.         }  
  1034.         iret = strtotime(charbuf, &timeStru);  
  1035.         printf("conver result %d: %04d-%02d-%02d, %02d:%02d:%02d\n", iret,  
  1036.             timeStru.tm_year + 1900, timeStru.tm_mon + 1, timeStru.tm_mday,  
  1037.             timeStru.tm_hour, timeStru.tm_min, timeStru.tm_sec);  
  1038.     }  
  1039.   
  1040.     return iret;  
  1041.   
  1042. /* strtotimeTest() */  


 

 

mktime(将时间结构数据转换成经过的秒数)  
相关函数  time,asctime,gmtime,localtime

表头文件  #include<time.h>

定义函数  time_t mktime(strcut tm * timeptr);

函数说明  mktime()用来将参数timeptr所指的tm结构数据转换成从公元1970年1月1日0时0分0 秒算起至今的UTC时间所经过的秒数。

返回值  返回经过的秒数。

将两个数都mktime,然后求差

猜你喜欢

转载自blog.csdn.net/qq_26422355/article/details/54629167