我们的最终目的是把字符串格式的时间转换为内部使用的“日历时间”,即到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一个不存在的夏令时(出现夏令时切换时丢失的那个小时)会直接生成丢失小时的下一个小时。这个结果是确定的稳定的。

暂时解决问题的一个方案:

#include <iostream>
#include <time.h>
#include <arpa/inet.h>
using namespace std;
time_t MakeTime(int iYear, int iMonth, int iMonthDay,
int iHour, int iMinute, int iSecond, int iIsdst)
{
struct tm dTm;
dTm.tm_mon = iMonth - 1;
dTm.tm_mday = iMonthDay ;
dTm.tm_year = iYear - 1900;
dTm.tm_hour = iHour;
dTm.tm_min = iMinute;
dTm.tm_sec = iSecond;
dTm.tm_isdst = iIsdst; time_t ret = mktime(&dTm); // 判断生成的是不是夏令时中的,倘若系统一直不是夏令时,可以省一些性能
if(1 == dTm.tm_isdst)
{
// 调整为非夏令时
dTm.tm_isdst = 0;
time_t tmpRet = mktime(&dTm);
if(iHour == dTm.tm_hour)
{
// 确定为重复时间
ret = tmpRet;
}
}
return ret; } string ToString(time_t tTime)
{
struct tm Tm;
struct tm* pTm;
pTm = localtime_r(&tTime, &Tm);
if(NULL == pTm)
{
}
int iSecond = pTm->tm_sec;
int iMinute = pTm->tm_min;
int iHour = pTm->tm_hour;
int iMonthDay = pTm->tm_mday;
int iMonth = pTm->tm_mon + 1;
int iYear = pTm->tm_year + 1900;
#define MAX_DATETIME_STRING_FORMAT "%04d-%02d-%02d %02d:%02d:%02d %s"
static const int MaxDateTimeStringLength = 23;
char temp[MaxDateTimeStringLength + 1];
snprintf(temp, MaxDateTimeStringLength + 1, MAX_DATETIME_STRING_FORMAT, iYear, iMonth, iMonthDay, iHour, iMinute, iSecond, pTm->tm_zone);
return temp;
} int main()
{
    setenv("TZ","Europe/Moscow",1);
  tzset();
    time_t tt = MakeTime(2011,10,30, 2, 30, 00, -1);

    string tstring = ToString(tt);
cout<<tstring<<endl;
cout<<"Moscow exit UTC time(duplicate hour 2011-10-30 02:30:00):"<<ToString(MakeTime(2011, 10, 30, 2, 30, 00, -1))<<endl; cout<<"Isdst = -1"<<endl;
cout<<"Moscow enter UTC time(before miss hour 2011-03-27 01:30:00):"<<ToString(MakeTime(2011, 3, 27, 1, 30, 00, -1))<<endl;
cout<<"Moscow exit UTC time(duplicate hour 2011-10-30 02:30:00):"<<ToString(MakeTime(2011, 10, 30, 2, 30, 00, -1))<<endl;
cout<<"Moscow enter UTC time(miss hour 2011-03-27 02:30:00):"<<ToString(MakeTime(2011, 3, 27, 2, 30, 00, -1))<<endl;
cout<<"Moscow enter UTC time(miss hour 2011-03-27 03:30:00):"<<ToString(MakeTime(2011, 3, 27, 3, 30, 00, -1))<<endl;
cout<<"Moscow exit UTC time(before duplicate hour 2011-10-30 01:30:00):"<<ToString(MakeTime(2011, 10, 30, 1, 30, 00, -1))<<endl;
cout<<"Moscow exit UTC time(duplicate hour 2011-10-30 02:30:00):"<<ToString(MakeTime(2011, 10, 30, 2, 30, 00, -1))<<endl;
cout<<"Moscow exit UTC time(after duplicate hour 2011-10-30 03:30:00):"<<ToString(MakeTime(2011, 10 ,30, 3, 30, 00, -1))<<endl;
cout<<"Moscow enter UTC time(before miss hour 2011-03-27 01:30:00):"<<ToString(MakeTime(2011, 3, 27, 1, 30, 00, -1))<<endl;
cout<<"Moscow exit UTC time(duplicate hour 2011-10-30 02:30:00):"<<ToString(MakeTime(2011, 10, 30, 2, 30, 00, -1))<<endl; cout<<"Current time :"<<ToString(time(0))<<endl;
cout<<"Isdst = -1"<<endl;
cout<<"Moscow enter UTC time(before miss hour 2011-03-27 01:30:00):"<<ToString(MakeTime(2011, 3, 27, 1, 30, 00, -1))<<endl;
cout<<"Moscow enter UTC time(miss hour 2011-03-27 02:30:00):"<<ToString(MakeTime(2011, 3, 27, 2, 30, 00, -1))<<endl;
cout<<"Moscow enter UTC time(miss hour 2011-03-27 03:30:00):"<<ToString(MakeTime(2011, 3, 27, 3, 30, 00, -1))<<endl;
cout<<"Moscow exit UTC time(before duplicate hour 2011-10-30 01:30:00):"<<ToString(MakeTime(2011, 10, 30, 1, 30, 00, -1))<<endl;
cout<<"Moscow exit UTC time(duplicate hour 2011-10-30 02:30:00):"<<ToString(MakeTime(2011, 10, 30, 2, 30, 00, -1))<<endl;
cout<<"Moscow exit UTC time(after duplicate hour 2011-10-30 03:30:00):"<<ToString(MakeTime(2011, 10 ,30, 3, 30, 00, -1))<<endl; cout<<"Isdst = 1"<<endl;
cout<<"Moscow enter UTC time(before miss hour 2011-03-27 01:30:00):"<<ToString(MakeTime(2011, 3, 27, 1, 30, 00, 1))<<endl;
cout<<"Moscow enter UTC time(miss hour 2011-03-27 02:30:00):"<<ToString(MakeTime(2011, 3, 27, 2, 30, 00, 1))<<endl;
cout<<"Moscow enter UTC time(miss hour 2011-03-27 03:30:00):"<<ToString(MakeTime(2011, 3, 27, 3, 30, 00, 1))<<endl;
cout<<"Moscow exit UTC time(before duplicate hour 2011-10-30 01:30:00):"<<ToString(MakeTime(2011, 10, 30, 1, 30, 00, 1))<<endl;
cout<<"Moscow exit UTC time(duplicate hour 2011-10-30 02:30:00):"<<ToString(MakeTime(2011, 10, 30, 2, 30, 00, 1))<<endl;
cout<<"Moscow exit UTC time(after duplicate hour 2011-10-30 03:30:00):"<<ToString(MakeTime(2011, 10 ,30, 3, 30, 00, 1))<<endl; cout<<"Isdst = 0"<<endl;
cout<<"Moscow enter UTC time(before miss hour 2011-03-27 01:30:00):"<<ToString(MakeTime(2011, 3, 27, 1, 30, 00, 0))<<endl;
cout<<"Moscow enter UTC time(miss hour 2011-03-27 02:30:00):"<<ToString(MakeTime(2011, 3, 27, 2, 30, 00, 0))<<endl;
cout<<"Moscow enter UTC time(miss hour 2011-03-27 03:30:00):"<<ToString(MakeTime(2011, 3, 27, 3, 30, 00, 0))<<endl;
cout<<"Moscow exit UTC time(before duplicate hour 2011-10-30 01:30:00):"<<ToString(MakeTime(2011, 10, 30, 1, 30, 00, 0))<<endl;
cout<<"Moscow exit UTC time(duplicate hour 2011-10-30 02:30:00):"<<ToString(MakeTime(2011, 10, 30, 2, 30, 00, 0))<<endl;
cout<<"Moscow exit UTC time(after duplicate hour 2011-10-30 03:30:00):"<<ToString(MakeTime(2011, 10 ,30, 3, 30, 00, 0))<<endl;
}

MakeTime的测试代码

setenv("TZ","Europe/Moscow",1);
tzset();
// DST = -1

// 切入夏令时丢失的小时前的小时
assert("2011-03-27 01:30:00 MSK" == ToString(MakeTime(2011, 3, 27, 1, 30, 00, -1)));
// 切入夏令时丢失的小时
assert("2011-03-27 03:30:00 MSD" == ToString(MakeTime(2011, 3, 27, 2, 30, 00, -1)));
// 切入夏令时丢失的小时后的小时
assert("2011-03-27 03:30:00 MSD" == ToString(MakeTime(2011, 3, 27, 3, 30, 00, -1)));
// 切入夏令时丢失的小时
assert("2011-03-27 03:30:00 MSD" == ToString(MakeTime(2011, 3, 27, 2, 30, 00, -1))); // 切出夏令时重复的小时前的小时
assert("2011-10-30 01:30:00 MSD" == ToString(MakeTime(2011, 10, 30, 1, 30, 00, -1)));
// 切出夏令时重复的小时
assert("2011-10-30 02:30:00 MSD" == ToString(MakeTime(2011, 10, 30, 2, 30, 00, -1)));
// 切出夏令时重复的小时后的小时
assert("2011-10-30 03:30:00 MSK" == ToString(MakeTime(2011, 10 ,30, 3, 30, 00, -1)));
// 切出夏令时重复的小时
assert("2011-10-30 02:30:00 MSK" == ToString(MakeTime(2011, 10, 30, 2, 30, 00, -1))); // DST = 0 // 切入夏令时丢失的小时前的小时
assert("2011-03-27 01:30:00 MSK" == ToString(MakeTime(2011, 3, 27, 1, 30, 00, 0)));
// 切入夏令时丢失的小时
assert("2011-03-27 03:30:00 MSD" == ToString(MakeTime(2011, 3, 27, 2, 30, 00, 0)));
// 切入夏令时丢失的小时后的小时
assert("2011-03-27 04:30:00 MSD" == ToString(MakeTime(2011, 3, 27, 3, 30, 00, 0)));
// 切入夏令时丢失的小时
assert("2011-03-27 03:30:00 MSD" == ToString(MakeTime(2011, 3, 27, 2, 30, 00, 0))); // 切出夏令时重复的小时前的小时
assert("2011-10-30 02:30:00 MSD" == ToString(MakeTime(2011, 10, 30, 1, 30, 00, 0)));
// 切出夏令时重复的小时
assert("2011-10-30 02:30:00 MSK" == ToString(MakeTime(2011, 10, 30, 2, 30, 00, 0)));
// 切出夏令时重复的小时后的小时
assert("2011-10-30 03:30:00 MSK" == ToString(MakeTime(2011, 10 ,30, 3, 30, 00, 0)));
// 切出夏令时重复的小时
assert("2011-10-30 02:30:00 MSK" == ToString(MakeTime(2011, 10, 30, 2, 30, 00, 0))); // DST = 1 // 切入夏令时丢失的小时前的小时
assert("2011-03-27 00:30:00 MSK" == ToString(MakeTime(2011, 3, 27, 1, 30, 00, 1)));
// 切入夏令时丢失的小时
assert("2011-03-27 01:30:00 MSK" == ToString(MakeTime(2011, 3, 27, 2, 30, 00, 1)));
// 切入夏令时丢失的小时后的小时
assert("2011-03-27 03:30:00 MSD" == ToString(MakeTime(2011, 3, 27, 3, 30, 00, 1)));
// 切入夏令时丢失的小时
assert("2011-03-27 01:30:00 MSK" == ToString(MakeTime(2011, 3, 27, 2, 30, 00, 1))); // 切出夏令时重复的小时前的小时
assert("2011-10-30 01:30:00 MSD" == ToString(MakeTime(2011, 10, 30, 1, 30, 00, 1)));
// 切出夏令时重复的小时
assert("2011-10-30 02:30:00 MSD" == ToString(MakeTime(2011, 10, 30, 2, 30, 00, 1)));
// 切出夏令时重复的小时后的小时
assert("2011-10-30 02:30:00 MSK" == ToString(MakeTime(2011, 10 ,30, 3, 30, 00, 1)));
// 切出夏令时重复的小时
assert("2011-10-30 02:30:00 MSD" == ToString(MakeTime(2011, 10, 30, 2, 30, 00, 1)));

mktime 夏令时的更多相关文章

  1. mktime夏令时处理

    https://www.cnblogs.com/dongzhiquan/archive/2011/11/05/2237075.html 我们的最终目的是把字符串格式的时间转换为内部使用的“日历时间”, ...

  2. mktime性能问题调查

    一.问题提出 会议中有同学提到使用mktime遇到一些问题: 1) 设置tm_isdst后速度很慢 2) 设置TZ环境变量提速极大 所以想调查下具体情况.   mktime真的这么慢?如果是,为什么? ...

  3. C语言mktime()

    最近在调试stm32L151单片机,因为业务需要将从RTC获取的时间转换成时间戳.转换的时候发现获取的时间一直不对.一直被两个问题困扰. 1.从RTC获取出来的月份为什么比实际月份小1? 2.转换得来 ...

  4. c++ mktime()

    今天联系写一个日历的程序,需要算出月份中的第一天是星期几,用到了mktime()这个函数,感觉这个函数挺有用的,分享给大家. 原型:time_t mktime(struct tm *) 其中的tm结构 ...

  5. C语言中mktime函数功能及用法

    今天联系写一个日历的程序,需要算出月份中的第一天是星期几,用到了mktime()这个函数,感觉这个函数挺有用的,分享给大家. 原型:time_t mktime(struct tm *) 其中的tm结构 ...

  6. php date mktime 获取时间上的各种值

    echo date("Ymd",strtotime("now")), "\n"; echo date("Ymd",str ...

  7. Java中的夏令时问题

    因为在用C#做项目的时候被夏令时坑过一回,所以这次将在java中的时区转换信息做一下记录,很简单 SimpleDateFormat inputFormat = new SimpleDateFormat ...

  8. kernel/mktime

    /* *  linux/kernel/mktime.c * *  Copyright (C) 1991, 1992  Linus Torvalds */ #include <linux/mkti ...

  9. 夏令时 DST (Daylight Saving Time) java中的夏令时【转】

    1916年,德国首先实行夏令时,英国因为怕德国会从中得到更大的效益,因此紧跟着也采取了夏令时 1986年至1991年,中华人民共和国在全国范围实行了六年夏令时 サマータイム 夏時間(日本现在没有实行夏 ...

随机推荐

  1. 运用node真机调试移动web项目

    很多时候我们对移动端进行测试的时候,有pc端的测试,也有真机上的测试,pc的测试就不多说了,因为其实基本上大家都懂的.真机测试上也有几种方法,这里就推荐三种: 移动端真机调试方法 chrome真机调试 ...

  2. Java并发编程随笔

    死锁:两个线程互相等待对方释放锁才可以继续运行. 避免死锁的常见方法: 1.避免一个线程同时获取多个锁 2.避免一个线程在锁内同时占用多个资源,尽量保证一个锁只占用一个资源 3.尝试使用定时锁,使用l ...

  3. idea Tomcat部署时没有update classes and resources

    idea 没有update classes and resources         发现为了方便调试页面,想用idea的update classes and resources找不到了,发现需要把 ...

  4. KeyValuePair 和 Dictionary 的关系和区别

    KeyValuePair 和 Dictionary 的关系 1.KeyValuePair      a.KeyValuePair 是一个结构体(struct):     b.KeyValuePair  ...

  5. BufferedStream说明

    BufferedStream并不是将所有内容都存放到内存中,而MemoryStream则是. BufferedStream必须跟其他流如FileStream结合使用,而MemoryStream则不用

  6. 关于创建String对象过程的内存分配

    String是引用数据类型 但是String实际上java给我们提供的是一个类 注意:String 全类被fianl所修饰 所以 String 又叫 字符串常量 String 的值 一旦定义 不可以改 ...

  7. R语言-图形辅助

    1.画底纹格子    grid()函数 > plot(rnorm(100)) > grid() #画底纹格子 > grid(nx=NA, ny=8, #画水平底纹,横坐标无分隔,纵坐 ...

  8. 移动端响应式布局--你不知道的CSS3.0媒体查询,解决rem部分情况下无法适配的场景

    媒体查询作为响应式布局的方法之一,实际项目中用途也很广.但是你真的知道怎么用吗? 例如,下面匹配 iphone6/7/8 屏幕 @media screen and (max-width: 375px) ...

  9. linux下压力测试工具ab的使用

    一.安装 [root@node2 logs]# yum install httpd-tools 已加载插件:fastestmirror Loading mirror speeds from cache ...

  10. 利用Access-Control-Allow-Origin响应头解决跨域请求原理

    传统的跨域请求没有好的解决方案,无非就是jsonp和iframe,随着跨域请求的应用越来越多,W3C提供了跨域请求的标准方案(Cross-Origin Resource Sharing).IE8.Fi ...