我们的最终目的是把字符串格式的时间转换为内部使用的“日历时间”,即到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)));

转载于:https://www.cnblogs.com/dongzhiquan/archive/2011/11/05/2237075.html

mktime 夏令时相关推荐

  1. PHP date, strtotime, mktime处理

    今天经过几个工作日(周一-周五)后为哪天. 2016-09-08经过5个工作日为2016-09-14 $currentDate=date('Y-m-d', strtotime("-1 day ...

  2. mktime()函数使用

    原型:time_t mktime(struct tm *) 其中的tm结构体定义如下: struct tm {int tm_sec;/* 秒 - 取值区间为[0,59] */int tm_min; / ...

  3. 《Linux系统调用:gmtime,mktime,asctime》

    一.介绍 #include <time.h>char *asctime(const struct tm *tm);// 将time_t值转换为一个所谓的分解时间 struct tm 结构体 ...

  4. php中mktime函数,php mktime函数怎么用

    mktime()函数是PHP中的一个内置函数,用于返回日期的Unix时间戳.语法为mktime(hour,minute,second,month,day,year,is_dst),该函数在成功时返回整 ...

  5. C语言 mktime() gmtime()实现——亲测正确性

    前言 写此文章是因为有的嵌入式设备编程时不支持<time.h>,所以有些时间转换的函数必须自己实现. 关于<time.h>的使用,可以参考我的另一篇博客C语言常用时间相关函数. ...

  6. 日期与时间函数与夏令时的关系

    测试环境:VMware12 pro+CentOS 7 时间结构介绍: 1. time_t 为从公元1970 年1 月1 日0 时0 分0 秒算起至今的UTC 时间所经过的秒数 2. 结构tm的定义为 ...

  7. Linux中有关时区及夏令时设置(TZ环境变量)

    一.相关内容 Glibc中存储时间转换信息的有:tzname.timezone.daylight三个全局变量,声明在time.h中. Glibc中关于时区设置的函数有:tzset(),声明在time. ...

  8. mktime函数性能分析

    mktime函数性能分析 1月 02, 2019 in Linux环境高级编程 mktime函数性能分析 mktime是一个将break-down时间(struct tm)转化为日历时间(time_t ...

  9. c语言mktime返回值为-1,C语言mktime()

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

  10. mktime函数 php,php mktime函数怎么用

    mktime()函数是PHP中的一个内置函数,用于返回日期的Unix时间戳.语法为mktime(hour,minute,second,month,day,year,is_dst),该函数在成功时返回整 ...

最新文章

  1. Linux文件系统:概览(思维导图)
  2. 屏幕滑动_Appium滑动引导页swipe函数
  3. boost计算随机数和计算crc32简单示例 - jwybobo2007的专栏 - 博客频道 - CSDN.NET
  4. 基于Java的Heritrix爬取网页
  5. ios property 之 strong weak unsafe_unretained
  6. 综合布线(楼栋)需求分析报告
  7. matlab DSP6678,TMS320C6678开发例程使用手册(8)
  8. UWB定位/RSSI定位 三边测量法trilateration C语言代码详解
  9. Google 开源的前端项目
  10. Xcode打包证书,ipa安装启动闪退的相关问题
  11. 只有英语四级和计算机二级,通过英语四级和计算机二级用英语怎么说
  12. “醉牛前端”重新起航!
  13. 55-硅谷课堂1(项目概述+MyBatisPlus使用+搭建项目环境+开发讲师管理接口)
  14. android转发短信到邮箱,Android手机使用Tasker转发短信及来电
  15. java根据经纬度获取地址信息
  16. Android studio sdk下载
  17. upc 6617: Finite Encyclopedia of Integer Sequences(树的先序遍历第n/2个结点)
  18. Android 车机初体验: Auto,Automotive 傻傻分不清楚?| 开发者说·DTalk
  19. NGINX按天生成日志文件的简易配置
  20. 列表4:拼接排序方法实操

热门文章

  1. Dubbo介绍前篇------单一应用框架、垂直应用框架、分布式应用框架、流动计算框架,及RPC的简介
  2. 耐人寻味的 8 幅Java技术图
  3. 如何用一个废旧的笔记本打造一个家庭网络服务器?
  4. 国庆假期程序员是这样给自己粉饰无限的逼格!
  5. CTF-Mayday
  6. centos操作---搭建环境 安装python
  7. 数据库练习(1)——建立数据库
  8. fasthttp中的协程池实现
  9. 何为软件的Alpha、Beta、RC和GA发布版本?
  10. 二十三、常用的标签:见源码