在很多应用中,我们会用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
()里面的具体项:
>>>
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; /