user-0 提问: localtime mktime 高效的实现

回复:
user: user-1
content: 楼上的为什么总是这个回复

user: user-2
content: 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。 Linux或Unix下用GDB调试。  GDB常用命令 调用gdb编译需要在cc后面加 -g参数再加-o； [root@redhat home]#gdb 调试文件：启动gdb (gdb) l ：（字母l）从第一行开始列出源码 (gdb) break n :在第n行处设置断点 (gdb) break func：在函数func()的入口处设置断点 (gdb) info break： 查看断点信息 (gdb) r：运行程序 (gdb) n：单步执行 (gdb) c：继续运行 (gdb) p 变量 ：打印变量的值 (gdb) bt：查看函数堆栈 (gdb) finish：退出函数 (gdb) shell 命令行：执行shell命令行 (gdb) set args 参数:指定运行时的参数 (gdb) show args：查看设置好的参数 (gdb) show paths:查看程序运行路径；            set environment varname [=value] 设置环境变量。如：set env USER=hchen；             show environment [varname] 查看环境变量； (gdb) cd 相当于shell的cd; (gdb)pwd ：显示当前所在目录 (gdb)info program： 来查看程序的是否在运行，进程号，被暂停的原因。 (gdb)clear 行号n：清除第n行的断点 (gdb)delete 断点号n：删除第n个断点 (gdb)disable 断点号n：暂停第n个断点 (gdb)enable 断点号n：开启第n个断点 (gdb)step：单步调试如果有函数调用，则进入函数；与命令n不同，n是不进入调用的函数的 list ：简记为 l ，其作用就是列出程序的源代码，默认每次显示10行。 list 行号：将显示当前文件以“行号”为中心的前后10行代码，如：list 12 list 函数名：将显示“函数名”所在函数的源代码，如：list main list ：不带参数，将接着上一次 list 命令的，输出下边的内容。 注意 ：如果运行list 命令得到类似如下的打印，那是因为在编译程序时没有加入 -g 选项： (gdb) list 1       ../sysdeps/i386/elf/start.S: No such file or directory.         in ../sysdeps/i386/elf/start.S run：简记为 r ，其作用是运行程序，当遇到断点后，程序会在断点处停止运行，等待用户输入下一步的命令。 回车：重复上一条命令。 set args：设置运行程序时的命令行参数，如：set args 33 55 show args：显示命令行参数 continue：简讯为 c ，其作用是继续运行被断点中断的程序。 break：为程序设置断点。 break 行号：在当前文件的“行号”处设置断点，如：break  33 break 函数名：在用户定义的函数“函数名”处设置断点，如：break cb_button info breakpoints：显示当前程序的断点设置情况 disable breakpoints Num：关闭断点“Num”，使其无效，其中“Num”为 info breakpoints 中显示的对应值 enable breakpoints Num：打开断点“Num”，使其重新生效 step：简记为 s ，单步跟踪程序，当遇到函数调用时，则进入此函数体（一般只进入用户自定义函数）。 next：简记为 n，单步跟踪程序，当遇到函数调用时，也不进入此函数体；此命令同 step 的主要区别是，step 遇到用户自定义的函数，将步进到函数中去运行，而 next 则直接调用函数，不会进入到函数体内。 until：当你厌倦了在一个循环体内单步跟踪时，这个命令可以运行程序直到退出循环体。 finish： 运行程序，直到当前函数完成返回，并打印函数返回时的堆栈地址和返回值及参数值等信息。 stepi或nexti：单步跟踪一些机器指令。 print 表达式：简记为 p ，其中“表达式”可以是任何当前正在被测试程序的有效表达式，比如当前正在调试C语言的程序，那么“表达式”可以是任何C语言的有效表达式，包括数字，变量甚至是函数调用。 print a：将显示整数 a 的值 print ++a：将把 a 中的值加1,并显示出来 print name：将显示字符串 name 的值 print gdb_test(22)：将以整数22作为参数调用 gdb_test() 函数 print gdb_test(a)：将以变量 a 作为参数调用 gdb_test() 函数 bt：显示当前程序的函数调用堆栈。 display 表达式：在单步运行时将非常有用，使用display命令设置一个表达式后，它将在每次单步进行指令后，紧接着输出被设置的表达式及值。如： display a watch 表达式：设置一个监视点，一旦被监视的“表达式”的值改变，gdb将强行终止正在被调试的程序。如： watch a kill：将强行终止当前正在调试的程序 help 命令：help 命令将显示“命令”的常用帮助信息 call 函数(参数)：调用“函数”，并传递“参数”，如：call  gdb_test(55) layout：用于分割窗口，可以一边查看代码，一边测试： layout src：显示源代码窗口 layout asm：显示反汇编窗口 layout regs：显示源代码/反汇编和CPU寄存器窗口 layout split：显示源代码和反汇编窗口 Ctrl + L：刷新窗口 quit：简记为 q ，退出gdb 当然，gdb的功能远不止这些，包括多进程/多线程/信号/远程调试等功能在这里均没有提及，有需要的读者可以参考其它信息 本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/pizi0475/archive/2011/03/08/6232749.aspx

user: user-0
content: 引用 2 楼 zhao4zhong1 的回复:参考localtime和mktime的源代码。 C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\localtim.c /*** *localtim.c - Convert __time32_t value to time structure * *       Copyright (c) Microsoft Corporation. All rights reserved. * *Purpose: *       Converts time stored as a __time32_t value to a structure of type *       struct tm expressed as local time. * *******************************************************************************/  #include <cruntime.h> #include <limits.h> #include <time.h> #include <stddef.h> #include <memory.h> #include <ctime.h> #include <internal.h>   /*** *struct tm *_localtime32_s(ptm, ptime) - convert __time32_t value to tm structure * *Purpose: *       Convert a value in 32-bit internal (__time32_t) format to a tm struct *       containing the corresponding local time. * * NOTES: *       (1) gmtime must be called before _isindst to ensure that the tb time *           structure is initialized. *       (2) gmtime and localtime use a single statically allocated buffer. *           Each call to one of these routines destroys the contents of the *           previous call. *       (3) __time32_t is a 32-bit long integer representing the number of seconds *           since 00:00:00, 01-01-70 (UTC) (i.e., the Posix/Unix Epoch. Only *           non-negative values are supported. *       (4) It is assumed that the maximum adjustment for local time is *           less than three days (include Daylight Savings Time adjustment). *           This only a concern in Posix where the specification of the TZ *           environment restricts the combined offset for time zone and *           Daylight Savings Time to 2 * (24:59:59), just under 50 hours. * *Entry: *       __time32_t *ptime - pointer to a long time value * *Exit: *       errno_t = 0 success *                 tm members filled-in *       errno_t = non zero *                 tm members initialized to -1 if ptm != NULL * *Exceptions: *       See items (3) and (4) in the NOTES above. If these assumptions are *       violated, behavior is undefined. * *******************************************************************************/  errno_t __cdecl _localtime32_s (         struct tm *ptm,         const __time32_t *ptime         ) {         __time32_t ltime;         errno_t e = 0;         int daylight = 0;         long dstbias = 0;         long timezone = 0;          _VALIDATE_RETURN_ERRCODE( ( ptm != NULL ), EINVAL )         memset( ptm, 0xff, sizeof( struct tm ) );          _VALIDATE_RETURN_ERRCODE( ( ptime != NULL ), EINVAL )          /*          * Check for illegal __time32_t value          */         _VALIDATE_RETURN_ERRCODE_NOEXC( ( *ptime >= 0 ), EINVAL )          __tzset();          _ERRCHECK(_get_daylight(&daylight));         _ERRCHECK(_get_dstbias(&dstbias));         _ERRCHECK(_get_timezone(&timezone));           if ( (*ptime > 3 * _DAY_SEC) && (*ptime < LONG_MAX - 3 * _DAY_SEC) ) {                 /*                  * The date does not fall within the first three, or last                  * three, representable days of the Epoch. Therefore, there                  * is no possibility of overflowing or underflowing the                  * __time32_t representation as we compensate for timezone and                  * Daylight Savings Time.                  */                  ltime = *ptime - timezone;                 e = _gmtime32_s( ptm, <ime );                 if ( e != 0 )                 {                     return e;                 }                  /*                  * Check and adjust for Daylight Saving Time.                  */                 if ( daylight && _isindst( ptm ) ) {                         ltime -= dstbias;                         e = _gmtime32_s( ptm, <ime );                         if ( e != 0 )                         {                             return e;                         }                         ptm->tm_isdst = 1;                 }         }         else {                 e = _gmtime32_s( ptm, ptime );                 if ( e != 0 )                 {                     return e;                 }                  /*                      * The date falls with the first three, or last three days                  * of the Epoch. It is possible the __time32_t representation                  * would overflow or underflow while compensating for                  * timezone and Daylight Savings Time. Therefore, make the                  * timezone and Daylight Savings Time adjustments directly                  * in the tm structure. The beginning of the Epoch is                  * 00:00:00, 01-01-70 (UTC) and the last representable second                  * in the Epoch is 03:14:07, 01-19-2038 (UTC). This will be                  * used in the calculations below.                  *                  * First, adjust for the timezone.                  */                 if ( daylight && _isindst(ptm) ) {                         ltime = (__time32_t)ptm->tm_sec - (timezone + dstbias);                         ptm->tm_isdst = 1;                 }                 else                         ltime = (__time32_t)ptm->tm_sec - timezone;                 ptm->tm_sec = (int)(ltime % 60);                 if ( ptm->tm_sec < 0 ) {                         ptm->tm_sec += 60;                         ltime -= 60;                 }                  ltime = (__time32_t)ptm->tm_min + ltime/60;                 ptm->tm_min = (int)(ltime % 60);                 if ( ptm->tm_min < 0 ) {                         ptm->tm_min += 60;                         ltime -= 60;                 }                  ltime = (__time32_t)ptm->tm_hour + ltime/60;                 ptm->tm_hour = (int)(ltime % 24);                 if ( ptm->tm_hour < 0 ) {                         ptm->tm_hour += 24;                         ltime -=24;                 }                  ltime /= 24;                  if ( ltime > 0 ) {                         /*                          * There is no possibility of overflowing the tm_mday                          * and tm_yday fields since the date can be no later                          * than January 19.                          */                         ptm->tm_wday = (ptm->tm_wday + (int)ltime) % 7;                         ptm->tm_mday += (int)ltime;                         ptm->tm_yday += (int)ltime;                 }                 else if ( ltime < 0 ) {                         /*                          * It is possible to underflow the tm_mday and tm_yday                          * fields. If this happens, then adjusted date must                          * lie in December 1969.                          */                         ptm->tm_wday = (ptm->tm_wday + 7 + (int)ltime) % 7;                         if ( (ptm->tm_mday += (int)ltime) <= 0 ) {                                 ptm->tm_mday += 31;                                 // according to assumption 4 above, timezone can                                 // cause the date to underflow the epoch by                                 // more than a day                                 ptm->tm_yday = ptm->tm_yday + (int)ltime + 365;                                 ptm->tm_mon = 11;                                 ptm->tm_year--;                         }                         else {                                 ptm->tm_yday += (int)ltime;                         }                 }           }           return 0; }   /*** *struct tm *_localtime32(ptime) - convert __time32_t value to tm structure * *Purpose: *       Convert a value in 32-bit internal (__time32_t) format to a tm struct *       containing the corresponding local time. * * NOTES: *       (1) gmtime must be called before _isindst to ensure that the tb time *           structure is initialized. *       (2) gmtime and localtime use a single statically allocated buffer. *           Each call to one of these routines destroys the contents of the *           previous call. *       (3) It is assumed that __time32_t is a 32-bit long integer representing *           the number of seconds since 00:00:00, 01-01-70 (UTC) (i.e., the *           Posix/Unix Epoch. Only non-negative values are supported. *       (4) It is assumed that the maximum adjustment for local time is *           less than three days (include Daylight Savings Time adjustment). *           This only a concern in Posix where the specification of the TZ *           environment restricts the combined offset for time zone and *           Daylight Savings Time to 2 * (24:59:59), just under 50 hours. * *Entry: *       __time32_t *ptime - pointer to a long time value * *Exit: *       If *ptime is non-negative, returns a pointer to the tm structure. *       Otherwise, returns NULL. * *Exceptions: *       See items (3) and (4) in the NOTES above. If these assumptions are *       violated, behavior is undefined. * *******************************************************************************/  struct tm * __cdecl _localtime32 (         const __time32_t *ptime         ) {         errno_t e;         struct tm *ptm = __getgmtimebuf();         if ( ptm == NULL )         {             return NULL;         }          e = _localtime32_s( ptm, ptime );         if ( e != 0 )         {             return NULL;         }         return ptm; }  我也知道linux 内核也有但是看不懂~~

user: user-2
content: 参考localtime和mktime的源代码。 C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\localtim.c /*** *localtim.c - Convert __time32_t value to time structure * *       Copyright (c) Microsoft Corporation. All rights reserved. * *Purpose: *       Converts time stored as a __time32_t value to a structure of type *       struct tm expressed as local time. * *******************************************************************************/  #include <cruntime.h> #include <limits.h> #include <time.h> #include <stddef.h> #include <memory.h> #include <ctime.h> #include <internal.h>   /*** *struct tm *_localtime32_s(ptm, ptime) - convert __time32_t value to tm structure * *Purpose: *       Convert a value in 32-bit internal (__time32_t) format to a tm struct *       containing the corresponding local time. * * NOTES: *       (1) gmtime must be called before _isindst to ensure that the tb time *           structure is initialized. *       (2) gmtime and localtime use a single statically allocated buffer. *           Each call to one of these routines destroys the contents of the *           previous call. *       (3) __time32_t is a 32-bit long integer representing the number of seconds *           since 00:00:00, 01-01-70 (UTC) (i.e., the Posix/Unix Epoch. Only *           non-negative values are supported. *       (4) It is assumed that the maximum adjustment for local time is *           less than three days (include Daylight Savings Time adjustment). *           This only a concern in Posix where the specification of the TZ *           environment restricts the combined offset for time zone and *           Daylight Savings Time to 2 * (24:59:59), just under 50 hours. * *Entry: *       __time32_t *ptime - pointer to a long time value * *Exit: *       errno_t = 0 success *                 tm members filled-in *       errno_t = non zero *                 tm members initialized to -1 if ptm != NULL * *Exceptions: *       See items (3) and (4) in the NOTES above. If these assumptions are *       violated, behavior is undefined. * *******************************************************************************/  errno_t __cdecl _localtime32_s (         struct tm *ptm,         const __time32_t *ptime         ) {         __time32_t ltime;         errno_t e = 0;         int daylight = 0;         long dstbias = 0;         long timezone = 0;          _VALIDATE_RETURN_ERRCODE( ( ptm != NULL ), EINVAL )         memset( ptm, 0xff, sizeof( struct tm ) );          _VALIDATE_RETURN_ERRCODE( ( ptime != NULL ), EINVAL )          /*          * Check for illegal __time32_t value          */         _VALIDATE_RETURN_ERRCODE_NOEXC( ( *ptime >= 0 ), EINVAL )          __tzset();          _ERRCHECK(_get_daylight(&daylight));         _ERRCHECK(_get_dstbias(&dstbias));         _ERRCHECK(_get_timezone(&timezone));           if ( (*ptime > 3 * _DAY_SEC) && (*ptime < LONG_MAX - 3 * _DAY_SEC) ) {                 /*                  * The date does not fall within the first three, or last                  * three, representable days of the Epoch. Therefore, there                  * is no possibility of overflowing or underflowing the                  * __time32_t representation as we compensate for timezone and                  * Daylight Savings Time.                  */                  ltime = *ptime - timezone;                 e = _gmtime32_s( ptm, <ime );                 if ( e != 0 )                 {                     return e;                 }                  /*                  * Check and adjust for Daylight Saving Time.                  */                 if ( daylight && _isindst( ptm ) ) {                         ltime -= dstbias;                         e = _gmtime32_s( ptm, <ime );                         if ( e != 0 )                         {                             return e;                         }                         ptm->tm_isdst = 1;                 }         }         else {                 e = _gmtime32_s( ptm, ptime );                 if ( e != 0 )                 {                     return e;                 }                  /*                      * The date falls with the first three, or last three days                  * of the Epoch. It is possible the __time32_t representation                  * would overflow or underflow while compensating for                  * timezone and Daylight Savings Time. Therefore, make the                  * timezone and Daylight Savings Time adjustments directly                  * in the tm structure. The beginning of the Epoch is                  * 00:00:00, 01-01-70 (UTC) and the last representable second                  * in the Epoch is 03:14:07, 01-19-2038 (UTC). This will be                  * used in the calculations below.                  *                  * First, adjust for the timezone.                  */                 if ( daylight && _isindst(ptm) ) {                         ltime = (__time32_t)ptm->tm_sec - (timezone + dstbias);                         ptm->tm_isdst = 1;                 }                 else                         ltime = (__time32_t)ptm->tm_sec - timezone;                 ptm->tm_sec = (int)(ltime % 60);                 if ( ptm->tm_sec < 0 ) {                         ptm->tm_sec += 60;                         ltime -= 60;                 }                  ltime = (__time32_t)ptm->tm_min + ltime/60;                 ptm->tm_min = (int)(ltime % 60);                 if ( ptm->tm_min < 0 ) {                         ptm->tm_min += 60;                         ltime -= 60;                 }                  ltime = (__time32_t)ptm->tm_hour + ltime/60;                 ptm->tm_hour = (int)(ltime % 24);                 if ( ptm->tm_hour < 0 ) {                         ptm->tm_hour += 24;                         ltime -=24;                 }                  ltime /= 24;                  if ( ltime > 0 ) {                         /*                          * There is no possibility of overflowing the tm_mday                          * and tm_yday fields since the date can be no later                          * than January 19.                          */                         ptm->tm_wday = (ptm->tm_wday + (int)ltime) % 7;                         ptm->tm_mday += (int)ltime;                         ptm->tm_yday += (int)ltime;                 }                 else if ( ltime < 0 ) {                         /*                          * It is possible to underflow the tm_mday and tm_yday                          * fields. If this happens, then adjusted date must                          * lie in December 1969.                          */                         ptm->tm_wday = (ptm->tm_wday + 7 + (int)ltime) % 7;                         if ( (ptm->tm_mday += (int)ltime) <= 0 ) {                                 ptm->tm_mday += 31;                                 // according to assumption 4 above, timezone can                                 // cause the date to underflow the epoch by                                 // more than a day                                 ptm->tm_yday = ptm->tm_yday + (int)ltime + 365;                                 ptm->tm_mon = 11;                                 ptm->tm_year--;                         }                         else {                                 ptm->tm_yday += (int)ltime;                         }                 }           }           return 0; }   /*** *struct tm *_localtime32(ptime) - convert __time32_t value to tm structure * *Purpose: *       Convert a value in 32-bit internal (__time32_t) format to a tm struct *       containing the corresponding local time. * * NOTES: *       (1) gmtime must be called before _isindst to ensure that the tb time *           structure is initialized. *       (2) gmtime and localtime use a single statically allocated buffer. *           Each call to one of these routines destroys the contents of the *           previous call. *       (3) It is assumed that __time32_t is a 32-bit long integer representing *           the number of seconds since 00:00:00, 01-01-70 (UTC) (i.e., the *           Posix/Unix Epoch. Only non-negative values are supported. *       (4) It is assumed that the maximum adjustment for local time is *           less than three days (include Daylight Savings Time adjustment). *           This only a concern in Posix where the specification of the TZ *           environment restricts the combined offset for time zone and *           Daylight Savings Time to 2 * (24:59:59), just under 50 hours. * *Entry: *       __time32_t *ptime - pointer to a long time value * *Exit: *       If *ptime is non-negative, returns a pointer to the tm structure. *       Otherwise, returns NULL. * *Exceptions: *       See items (3) and (4) in the NOTES above. If these assumptions are *       violated, behavior is undefined. * *******************************************************************************/  struct tm * __cdecl _localtime32 (         const __time32_t *ptime         ) {         errno_t e;         struct tm *ptm = __getgmtimebuf();         if ( ptm == NULL )         {             return NULL;         }          e = _localtime32_s( ptm, ptime );         if ( e != 0 )         {             return NULL;         }         return ptm; }

user: user-2
content: C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\mktime.c /*** *mktime.c - Convert struct tm value to __time32_t value. * *       Copyright (c) Microsoft Corporation. All rights reserved. * *Purpose: *       Defines _mktime32() and _mkgmtime32(), routines to converts a time value *       in a tm structure (possibly incomplete) into a __time32_t value, then *       update (all) the structure fields with "normalized" values. * *******************************************************************************/  #include <cruntime.h> #include <stddef.h> #include <ctime.h> #include <time.h> #include <internal.h>  /*  * ChkAdd evaluates to TRUE if dest = src1 + src2 has overflowed  */ #define ChkAdd(dest, src1, src2)   ( ((src1 >= 0L) && (src2 >= 0L) \     && (dest < 0L)) || ((src1 < 0L) && (src2 < 0L) && (dest >= 0L)) )  /*  * ChkMul evaluates to TRUE if dest = src1 * src2 has overflowed  */ #define ChkMul(dest, src1, src2)   ( src1 ? (dest/src1 != src2) : 0 )   /*  * Core function for both _mktime32() and _mkgmtime32()  */ static __time32_t __cdecl _make__time32_t( struct tm *, int);   /*** *__time32_t _mktime32(tb) - Normalize user time block structure * *Purpose: *       _mktime32 converts a time structure, passed in as an argument, into a *       calendar time value in internal format (__time32_t). It also completes *       and updates the fields the of the passed in structure with 'normalized' *       values. There are three practical uses for this routine: * *       (1) Convert broken-down time to internal time format (__time32_t). *       (2) To have _mktime32 fill in the tm_wday, tm_yday, or tm_isdst fields. *       (3) To pass in a time structure with 'out of range' values for some *           fields and have _mktime32 "normalize" them (e.g., pass in 1/35/87 and *           get back 2/4/87). *Entry: *       struct tm *tb - pointer to a tm time structure to convert and *                       normalize * *Exit: *       If successful, _mktime32 returns the specified calender time encoded as *       a __time32_t value. Otherwise, (__time32_t)(-1) is returned to indicate an *       error. * *Exceptions: *       None. * *******************************************************************************/  _CRTIMP __time32_t __cdecl _mktime32 (         struct tm *tb         ) {         return( _make__time32_t(tb, 1) ); }   /*** *__time32_t _mkgmtime32(tb) - Convert broken down UTC time to __time32_t * *Purpose: *       Convert a tm structure, passed in as an argument, containing a UTC *       time value to internal format (__time32_t). It also completes and updates *       the fields the of the passed in structure with 'normalized' values.  *Entry: *       struct tm *tb - pointer to a tm time structure to convert and *                       normalize * *Exit: *       If successful, _mkgmtime returns the calender time encoded as __time32_t *       Otherwise, (__time32_t)(-1) is returned to indicate an error. * *Exceptions: *       None. * *******************************************************************************/  _CRTIMP __time32_t __cdecl _mkgmtime32 (         struct tm *tb         ) {         return( _make__time32_t(tb, 0) ); }   /*** *static __time32_t _make__time32_t(tb, ultflag) - * *Purpose: *       Converts a struct tm value to a __time32_t value, then updates the struct *       tm value. Either local time or UTC is supported, based on ultflag. *       This is the routine that actually does the work for both _mktime32() and *       _mkgmtime32(). * *Entry: *       struct tm *tb - pointer to a tm time structure to convert and *                       normalize *       int ultflag   - use local time flag. the tb structure is assumed *                       to represent a local date/time if ultflag > 0. *                       otherwise, UTC is assumed. * *Exit: *       If successful, _mktime32 returns the specified calender time encoded as *       a __time32_t value. Otherwise, (__time32_t)(-1) is returned to *       indicate an error. * *Exceptions: *       None. * *******************************************************************************/  static __time32_t __cdecl _make__time32_t (         struct tm *tb,         int ultflag         ) {         __time32_t tmptm1, tmptm2, tmptm3;         struct tm tbtemp;         long dstbias = 0;         long timezone = 0;          _VALIDATE_RETURN( ( tb != NULL ), EINVAL, ( ( __time32_t )( -1 ) ) )          /*          * First, make sure tm_year is reasonably close to being in range.          */         if ( ((tmptm1 = tb->tm_year) < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR           + 1) )             goto err_mktime;           /*          * Adjust month value so it is in the range 0 - 11.  This is because          * we don't know how many days are in months 12, 13, 14, etc.          */          if ( (tb->tm_mon < 0) || (tb->tm_mon > 11) ) {              /*              * no danger of overflow because the range check above.              */             tmptm1 += (tb->tm_mon / 12);              if ( (tb->tm_mon %= 12) < 0 ) {                 tb->tm_mon += 12;                 tmptm1--;             }              /*              * Make sure year count is still in range.              */             if ( (tmptm1 < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR + 1) )                 goto err_mktime;         }          /***** HERE: tmptm1 holds number of elapsed years *****/          /*          * Calculate days elapsed minus one, in the given year, to the given          * month. Check for leap year and adjust if necessary.          */         tmptm2 = _days[tb->tm_mon];         if ( !(tmptm1 & 3) && (tb->tm_mon > 1) )                 tmptm2++;          /*          * Calculate elapsed days since base date (midnight, 1/1/70, UTC)          *          *          * 365 days for each elapsed year since 1970, plus one more day for          * each elapsed leap year. no danger of overflow because of the range          * check (above) on tmptm1.          */         tmptm3 = (tmptm1 - _BASE_YEAR) * 365L + ((tmptm1 - 1L) >> 2)           - _LEAP_YEAR_ADJUST;          /*          * elapsed days to current month (still no possible overflow)          */         tmptm3 += tmptm2;          /*          * elapsed days to current date. overflow is now possible.          */         tmptm1 = tmptm3 + (tmptm2 = (__time32_t)(tb->tm_mday));         if ( ChkAdd(tmptm1, tmptm3, tmptm2) )             goto err_mktime;          /***** HERE: tmptm1 holds number of elapsed days *****/          /*          * Calculate elapsed hours since base date          */         tmptm2 = tmptm1 * 24L;         if ( ChkMul(tmptm2, tmptm1, 24L) )             goto err_mktime;          tmptm1 = tmptm2 + (tmptm3 = (__time32_t)tb->tm_hour);         if ( ChkAdd(tmptm1, tmptm2, tmptm3) )             goto err_mktime;          /***** HERE: tmptm1 holds number of elapsed hours *****/          /*          * Calculate elapsed minutes since base date          */          tmptm2 = tmptm1 * 60L;         if ( ChkMul(tmptm2, tmptm1, 60L) )             goto err_mktime;          tmptm1 = tmptm2 + (tmptm3 = (__time32_t)tb->tm_min);         if ( ChkAdd(tmptm1, tmptm2, tmptm3) )             goto err_mktime;          /***** HERE: tmptm1 holds number of elapsed minutes *****/          /*          * Calculate elapsed seconds since base date          */          tmptm2 = tmptm1 * 60L;         if ( ChkMul(tmptm2, tmptm1, 60L) )             goto err_mktime;          tmptm1 = tmptm2 + (tmptm3 = (__time32_t)tb->tm_sec);         if ( ChkAdd(tmptm1, tmptm2, tmptm3) )             goto err_mktime;          /***** HERE: tmptm1 holds number of elapsed seconds *****/          if  ( ultflag ) {              /*              * Adjust for timezone. No need to check for overflow since              * localtime() will check its arg value              */              __tzset();              _ERRCHECK(_get_dstbias(&dstbias));             _ERRCHECK(_get_timezone(&timezone));              tmptm1 += timezone;              /*              * Convert this second count back into a time block structure.              * If localtime returns NULL, return an error.              */             if ( _localtime32_s(&tbtemp, &tmptm1) != 0 )                 goto err_mktime;              /*              * Now must compensate for DST. The ANSI rules are to use the              * passed-in tm_isdst flag if it is non-negative. Otherwise,              * compute if DST applies. Recall that tbtemp has the time without              * DST compensation, but has set tm_isdst correctly.              */             if ( (tb->tm_isdst > 0) || ((tb->tm_isdst < 0) &&               (tbtemp.tm_isdst > 0)) ) {                 tmptm1 += dstbias;                 if ( _localtime32_s(&tbtemp, &tmptm1) != 0 )                     goto err_mktime;             }          }         else {             if ( _gmtime32_s(&tbtemp, &tmptm1) != 0 )                 goto err_mktime;         }          /***** HERE: tmptm1 holds number of elapsed seconds, adjusted *****/         /*****       for local time if requested                      *****/          *tb = tbtemp;         return (__time32_t)tmptm1;  err_mktime:         /*          * All errors come to here          */          errno = EINVAL;         return (__time32_t)(-1); }

user: user-0
content: #include "time.h" #include "stdlib.h" #include "stdio.h" #include "math.h" #define BEGIN_YEAR 1970 #define USER_BEGIN_YEAR 1900 #define YEAR_DIFFERENCE (BEGIN_YEAR - USER_BEGIN_YEAR) enum TIME_DEF {         SEC = 1,         MIN = SEC * 60,         HOUR = MIN * 60,         DAY = HOUR * 24,          YEAR = DAY * 365, }; time_t time_difference = 8 * HOUR; #define YEAR_CYCLE_DAY ((365 * 3) + 366) //1461 size_t leap(size_t year) {     if(((year%4) == 0 && (year%100) != 0 )|| (year%400) == 0 ) return 1;     else return 0; }  static time_t mom_day_table[2][12]={                 {31,28,31,30,31,30,31,31,30,31,30,31},                 {31,29,31,30,31,30,31,31,30,31,30,31}, };   tm* localtime(time_t *p) {         if(!p)         {                 return nullptr;         }         time_t t  = *p;         static tm ret;         memset(&ret,0,sizeof(ret));          t += time_difference;          time_t day = t / DAY;         day += 719542;         time_t year_not_cycle_day = day % YEAR_CYCLE_DAY;          ret.tm_year = ((day / YEAR_CYCLE_DAY) * 4);         ret.tm_year += year_not_cycle_day / 365;         ret.tm_year -= BEGIN_YEAR;          year_not_cycle_day %= 365;             size_t switc_table = leap(BEGIN_YEAR + ret.tm_year);          for(size_t i = 0;i < 12; ++i)         {                 if(year_not_cycle_day >= mom_day_table[switc_table][i])                 {                         year_not_cycle_day -= mom_day_table[switc_table][i];                         ret.tm_mon ++;                 }                 else                 {                         break;                 }         }            year_not_cycle_day ++;         ret.tm_mday = year_not_cycle_day;         ret.tm_sec = t % MIN;         ret.tm_min = (t % HOUR) / MIN;         ret.tm_hour = (t % DAY) / HOUR;         ret.tm_wday = t + (3 * DAY);          ret.tm_wday %= (7 * DAY);         ret.tm_wday /= DAY;         ret.tm_year  += YEAR_DIFFERENCE;           return &ret; } time_t mktime(int year,int mon,int day,int hour,int min,int sec) {         static time_t mon_yday[2][12] =         {                 {0,31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},                 {0,31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335},         };          time_t ret = 0;          time_t tool_day = 0;         year += BEGIN_YEAR;         year -= YEAR_DIFFERENCE;         year += mon / 12;         mon %= 12; //1461         tool_day += (year / 4) * YEAR_CYCLE_DAY;         tool_day += (year % 4) * 365;          tool_day -= 719542l;         if(mon > 0) tool_day += mon_yday[leap(year)][mon];         else if(mon < 0) tool_day -= mon_yday[leap(year)][abs(mon)];         tool_day += day - 1;         ret += tool_day * DAY;         ret += hour * HOUR;         ret += min * MIN;         ret += sec * SEC;          return ret - time_difference; } time_t mktime(tm* mk) {         if(!mk)         {                 return 0;         }         return mktime(mk->tm_year,mk->tm_mon,mk->tm_mday,mk->tm_hour,mk->tm_min,mk->tm_sec); }