在很多应用中,我们会用mktime函数进行时间准换操作,但这里面有一个夏令时的操作问题

我们的最终目的是把字符串格式的时间转换为内部使用的“日历时间”,即到UTC 1970年1月1日零时的秒数。这里就存在夏令时的问题。比如俄罗斯时间2008年10月26日2:30由于夏令时的跳变会经过两次,这两次所代表的“日历时间”明显不同。如果仍按照上面的程序 ,由mktime()函数来决定这个时间是否处于夏令时(它会根据当前时区自动判断,在没有发生时间重叠的情况下处理是正确的)就会有问题。 这时我们不能使用ttm.tm_isdst = -1了,而是明确使用ttm_tm_isdst = 1来告知mktime()现在处于夏令时,明确使用ttm.tm_isdst = 0来告知未处于夏令时。
结论:使用字符串时间表示时一定要有标记表示这个时间是否处于夏令时,推荐在时间字符串后面添加DST或者加上时区。否则,无法正确处理夏令时情况。如果时间字符串表示的是UTC时间,则无需上述处理过程。

mktime各种情况测试一下

在支持不支持夏令时时区,夏令时区间,非夏令时区间,切入夏令时丢失小时时,切出夏令时重复小时时。。tm_isdst 的不同作用

mktime是用于生成指定的本地时刻的,多数情况下我们都会把tm_isdst设置为-1,这样子可以把指定时刻是否为夏令时交由系统判断.不过实际应用中发现,对于切出夏令时时出现的重复小时,一个小时处于夏令时,一个小时不处于夏令时,因为我们没有指定是否处于夏令时,这时得到的结果便不稳定,可能是处于夏令时的小时,也可能是处于非夏令时的小时.

下面是测试结果:
tm中tm_isdst分别为0,1,-1对mktime结果影响.
tm_isdst = -1(由系统判断)
对于切入夏令时丢失的小时前的小时,生成时间为指定时间.
对于切入夏令时丢失的小时,生成时间为指定小时后面一个小时(不受前面mk结果影响)
对于切入夏令时丢失的小时后的小时,生成时间为指定时间.

对于切出夏令时重复的小时前的小时,生成时间为指定时间.
对于切出夏令时重复的小时,生成时间受前面mk结果影响,倘若前次mk时间结果处于夏令时,则结果为处于夏令时的那个小时;倘若前次mk时间结果不处于夏令时,则结果为不处于夏令时的那个小时;
对于切出夏令时重复的小时后的小时,生成时间为指定时间.

tm_isdst = 0(指定为非夏令时)
对于切入夏令时丢失的小时前的小时,生成时间为指定时间.
对于切入夏令时丢失的小时,生成时间为指定小时后面一个小时(不受前面mk结果影响)
对于切入夏令时丢失的小时后的小时,生成时间为指定时间后面一个小时.

对于切出夏令时重复的小时前的小时,生成时间为指定时间后面一个小时.
对于切出夏令时重复的小时,生成时间为不处于夏令时的那个小时;
对于切出夏令时重复的小时后的小时,生成时间为指定时间.

tm_isdst = 1(指定为夏令时)
对于切入夏令时丢失的小时前的小时,生成时间为指定时间前面一个小时.
对于切入夏令时丢失的小时,生成时间为指定小时后面一个小时(不受前面mk结果影响)
对于切入夏令时丢失的小时后的小时,生成时间为指定时间.

对于切出夏令时重复的小时前的小时,生成时间为指定时间.
对于切出夏令时重复的小时,生成时间为处于夏令时的那个小时;
对于切出夏令时重复的小时后的小时,生成时间为指定时间前面一个小时.

倘若mktime传入时间因为夏令时存在两个,那mktime会认为该时间可能处于夏令时也可能处于非夏令时。是否处于夏令时由mktime生成的上一个时间决定,倘若上一个时间处于夏令时则生成的该重复时间是处于夏令时的,否则生成的该重复时间是处于非夏令时的。程序内部的原因是它在mktime中用一个静态变量保存夏令时状态,下次生成时间是优先以保存的状态来生成时间。

倘若mktime一个不存在的夏令时(出现夏令时切换时丢失的那个小时)会直接生成丢失小时的下一个小时。这个结果是确定的稳定的。

long time zone = 0; _VALIDATE_RETURN( ( tb != NULL ), EINVAL, ( ( __ time 64_t )( -1 ) ) ) * First, make sure tm _year is reasonably close to being in range. if ( (( tm p tm 1 = tb-> tm _year) < _BASE_YEAR - 1) || ( tm p tm 1 > _MAX_YEAR64 + 1) ) goto err_ mk time ; * 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) ) { tm p tm 1 += (tb-> tm _mon / 12); if ( (tb-> tm _mon %= 12) < 0 ) { tb-> tm _mon += 12; tm p tm 1--; * Make sure year count is still in range. if ( ( tm p tm 1 < _BASE_YEAR - 1) || ( tm p tm 1 > _MAX_YEAR64 + 1) ) goto err_ mk time ; /***** HERE: tm p tm 1 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. tm p tm 2 = _days[tb-> tm _mon]; if ( _IS_LEAP_YEAR( tm p tm 1) && (tb-> tm _mon > 1) ) tm p tm 2++; * 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 tm p tm 1. tm p tm 3 = ( tm p tm 1 - _BASE_YEAR) * 365 + _ELAPSED_LEAP_YEARS( tm p tm 1); * elapsed days to current month (still no possible overflow) tm p tm 3 += tm p tm 2; * elapsed days to current date. tm p tm 1 = tm p tm 3 + ( tm p tm 2 = (__ time 64_t)(tb-> tm _mday)); /***** HERE: tm p tm 1 holds number of elapsed days *****/ * Calculate elapsed hours since base date tm p tm 2 = tm p tm 1 * 24; tm p tm 1 = tm p tm 2 + ( tm p tm 3 = (__ time 64_t)tb-> tm _hour); /***** HERE: tm p tm 1 holds number of elapsed hours *****/ * Calculate elapsed minutes since base date tm p tm 2 = tm p tm 1 * 60; tm p tm 1 = tm p tm 2 + ( tm p tm 3 = (__ time 64_t)tb-> tm _min); /***** HERE: tm p tm 1 holds number of elapsed minutes *****/ * Calculate elapsed seconds since base date tm p tm 2 = tm p tm 1 * 60; tm p tm 1 = tm p tm 2 + ( tm p tm 3 = (__ time 64_t)tb-> tm _sec); /***** HERE: tm p tm 1 holds number of elapsed seconds *****/ if ( ultflag ) { * Adjust for time zone. No need to check for overflow since * local time () will check its arg value __tzset(); _ERRCHECK(_get_ dst bias(& dst bias;)); _ERRCHECK(_get_ time zone(& time zone;)); tm p tm 1 += time zone; * Convert this second count back into a time block structure. * If local time returns NULL, return an error. if ( _local time 64_s(&tbtemp;, & tm p tm 1;) != 0 ) goto err_ mk time ; * Now must compensate for DST . The ANSI rules are to use the * passed-in tm _is dst flag if it is non-negative. Otherwise, * compute if DST applies. Recall that tbtemp has the time without * DST compensation, but has set tm _is dst correctly. if ( (tb-> tm _is dst > 0) || ((tb-> tm _is dst < 0) && (tbtemp. tm _is dst > 0)) ) { tm p tm 1 += dst bias; if ( _local time 64_s(&tbtemp;, & tm p tm 1;) != 0 ) goto err_ mk time ; else { if ( _gm time 64_s(&tbtemp;, & tm p tm 1;) != 0) goto err_ mk time ; /***** HERE: tm p tm 1 holds number of elapsed seconds, adjusted *****/ /***** for local time if requested *****/ *tb = tbtemp; return tm p tm 1; err_ mk time : * All errors come to here errno = EINVAL; return (__ time 64_t)(-1); 连接:http://www.educity.cn/wenda/248940.h tm l mk time 中的 tm _is dst 不对 tm 结构体中的 tm _is dst 赋值,在不同机器上会出现 tm _is dst 默认值不同  也就是说最终, mk time 算出来的时候会有一个小时的差别。 #include #include int main(void) { tm mask Time tm ; tm _is dst mk time () 将 struct tm 描述的 时间 转换成 时间 戳, tm _is dst 只是传入的 时间 是否是 DST ( 夏令时 ), tm _is dst 含有: >0: 是 DST =0: 不是 DST 同事测的传入 1 和 0 的i性能对比: 1: 1w 次耗时 2s 0: 1w 次耗时 0.02s         我们的最终目的是把字符串格式的 时间 转换为内部使用的“日历 时间 ”,即到UTC 1970年1月1日零时的秒数。这里就存在 夏令时 问题 。比如俄罗斯 时间 2008年10月26日2:30由于 夏令时 的跳变会经过两次,这两次所代表的“日历 时间 ”明显不同。如果仍按照上面的程序,由 mk time () 函数 来决定这个 时间 是否处于 夏令时 (它会根据当前时区自动判断,在没有发生 时间 重叠的情况下处理是正确的)就会有... 1.python中的 时间 操作 python中 time 、date time 两个模块均可进行 时间 操作;二者均可以获取 时间 、转换 时间 time 模块特有进行进程阻塞,date time 模块特有计算 时间 差; 时间 戳:指以1970年1月1日 00:00:00 UTC+00:00为基准(记为0),当前时刻距离基准的 时间 间隔; 时间 戳只表示 时间 间隔,与时区无关;python中 时间 戳是浮点数,表示距离基准的秒数,Java中 时间 戳是整数,表示距离基准的毫秒数,二者相差1000倍; 一 时间 获取 time 直接获取的是 时间 戳,dat #include < time .h> time _t time ( time _t * ) ; // time _t 是long类型 //返回从1970年1月1日0时0分0秒,到现在的的秒数 #include < time .h> time _t t; time _t time (&t);//返回从1970年1月1日0时0分0秒,... 1. 函数 说明 1.1描述 ​ time _t mk time (struct tm * time ptr) 把 time ptr 所指向的结构转换为自 1970 年 1 月 1 日以来持续 时间 的秒数,发生错误时返回-1。 1.2.声明 ​ time _t mk time (struct tm * time ptr) 1.3.参数 struct tm int tm _sec; /* 秒 – 取值[0,59] */    int tm _min; /* 分 - 取值[0,59] */    夏令制(Daylight Saving Time , DST ),如果想知道当前的 时间 是否是 夏令时 ,可以借助于 time 模块的local time 函数 来完成。先看下local time ()里面的具体项: &gt;&gt;&gt; time .local time () time .struct_ time ( tm _year=2018, tm _mon=7, tm _mday=28, tm _hour=17, tm _min... int tm _sec; /* 秒–取值区间为[0,59] */    int tm _min; /* 分 - 取值区间为[0,59] */    int tm _hour; /* 时 - 取值区间为[0,23] */    int tm _mday; /* 一个月中的日期 - 取值区间为[1,31] */   int tm _mon; /