新足迹

 找回密码
 注册

精华好帖回顾

· 征文活动-我眼中的澳洲护圣火之旅 (2008-4-25) likespring · 大头家常菜 -- 满族小吃萨其马 (2008-2-3) datou2z
· 我的3次路考的血泪史+教练评价 (2011-10-27) zzjwl · 咱也上个旧房改造 (2010-6-8) bobll_999
Advertisement
Advertisement
查看: 1921|回复: 26

C++:您遇到过类似的问题么? [复制链接]

发表于 2011-7-19 17:35 |显示全部楼层
此文章由 菜地一块 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 菜地一块 所有!转贴必须注明作者、出处和本声明,并保持内容完整
以前曾经在工作中遇到一个实际问题,非常讨厌。到最后虽然是解决了,但感觉非常别扭。直到现在也没有想出来更好的办法。
放在这里看看有没有人一起来探讨一下?

问题很简单:如何将一个GMT时间转换成本地时间?
例如已知以下时间为一个GMT时间:10:46AM 2011/07/18,如何转化成一个本地时间呢?你不可以假设你的程序将会运行在什么地方——它可能工作在任意时区。
最好是能够不使用OS相关的函数。
Advertisement
Advertisement

特殊贡献奖章

发表于 2011-7-19 18:43 |显示全部楼层
此文章由 kr2000 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 kr2000 所有!转贴必须注明作者、出处和本声明,并保持内容完整
先把获取当前地区时间
再把时区设置成伦敦,计算出跟当前时间的差别
把已知的GMT时间转成timestamp,再减掉之前算出的时间差别就得到这个时间在当前环境下的时间

发表于 2011-7-19 18:50 |显示全部楼层
此文章由 rogerk 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 rogerk 所有!转贴必须注明作者、出处和本声明,并保持内容完整
什么操作系统?linux/windows 各有不同的做法,一般都有个函数从GMT转到local time的。

如果你不用系统函数,你就自己把时间转化成一个long (time_t), 从epoch以来的秒数,然后自己加加减减,另外还别忘了夏令时什么的。。。

发表于 2011-7-19 19:43 |显示全部楼层
此文章由 菜地一块 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 菜地一块 所有!转贴必须注明作者、出处和本声明,并保持内容完整
有兴趣的同学可以动手试试,写一个函数,输入是GMT时间,输出是本地时间。
没有那么容易哦。
C++自己有标准函数库,可以处理时间的,为什么在LINUX和WINDOWS一定要有不同的做法呢?

发表于 2011-7-19 20:18 |显示全部楼层
此文章由 jerryclark 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 jerryclark 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 菜地一块 于 2011-7-19 18:43 发表
有兴趣的同学可以动手试试,写一个函数,输入是GMT时间,输出是本地时间。
没有那么容易哦。
C++自己有标准函数库,可以处理时间的,为什么在LINUX和WINDOWS一定要有不同的做法呢?

因为是不同的操作系统,系统函数完全不一样。
所以Java也好,.Net也好,都不是编译到底层的,这样编译出来的东西能够跨平台用。底层由Runtime来执行。

发表于 2011-7-19 20:41 |显示全部楼层
此文章由 菜地一块 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 菜地一块 所有!转贴必须注明作者、出处和本声明,并保持内容完整
LS的同学,我只是说一个可以把GMT时间变成本地时间的C++函数而已。
你的意思是这也需要写两次代码么?
Advertisement
Advertisement

发表于 2011-7-19 22:43 |显示全部楼层
此文章由 findcaiyzh 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 findcaiyzh 所有!转贴必须注明作者、出处和本声明,并保持内容完整
还是.net 好啊。。。。。

发表于 2011-7-20 00:22 |显示全部楼层
此文章由 kylenix 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 kylenix 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 findcaiyzh 于 2011-7-19 21:43 发表
还是.net 好啊。。。。。

.net只不过是库函数帮你做好了,下层还是一样的c/c++吧。
我想主要问题是要知道时差,而这需要调用系统函数,来得到当前的时区,而不同的os这个系统函数不同。不知理解对否?

发表于 2011-7-20 00:25 |显示全部楼层
此文章由 cppbug 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 cppbug 所有!转贴必须注明作者、出处和本声明,并保持内容完整
大概想了下,用C标准库,步骤大致如下:
1. 通过time()函数得到当前calendar time,然后通过gmtime和localtime函数获取GMT与本地的小时与分钟差:hh:mm。这里需要用前者减后者。
2. 定义一个struct tm 结构体 t,填入具体要转换的GMT时间。
3. 然后设定GMT 时区, putenv("TZ=GMT+0"); tzset();
4.通过mktime获取时间片timestamp:timestamp = mktime(&t);
5. 设定当前时区:putenv(“GMT+hh:mm”);tzset(); //hh:mm的值看第一步
6. 输出GMT时间与转换后时间:
printf("UTC  : %s", asctime(gmtime(&timestamp)));
                printf("Local: %s", asctime(localtime(&timestamp)));

2012年度奖章获得者 2011年度奖章获得者

发表于 2011-7-20 12:44 |显示全部楼层

回复 菜地一块 1# 帖子

此文章由 交易人生 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 交易人生 所有!转贴必须注明作者、出处和本声明,并保持内容完整
这个如果没有system call是不可能的,尤其是要适应在任何一个时区的函数。

发表于 2011-7-20 17:11 |显示全部楼层
此文章由 菜地一块 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 菜地一块 所有!转贴必须注明作者、出处和本声明,并保持内容完整
这里可能有些人并不是C++程序员,所以可能没有明白什么意思,我也不知道这样一个简单的函数,怎么跟操作系统相关性都扯上关系了。
下面是把一个本地时间 EST 2011年7月20日 15:30分转成GMT时间的例子。
你觉得这段代码在WINDOWS,LINUX,UNIX,SOLARIS,或者一切支持C++的环境里,会有什么问题么?
#include <time.h>
#include <iostream>
using namespace std;
int main()
{
        //EST 2011-07-20 15:30:00
        tm tmLocal;
        tmLocal.tm_year = 2011 - 1900;
        tmLocal.tm_mon = 7 - 1;
        tmLocal.tm_mday = 20;
        tmLocal.tm_hour = 15;
        tmLocal.tm_min = 30;
        tmLocal.tm_sec = 0;
        tmLocal.tm_isdst = -1;// Leave it to C run-time library
       
        // Convert tm to time_t and correct values of uninitialized fields int time1
        time_t time_tLocal = mktime( &tmLocal );

        // Convert localtime to GMT
        tm* ptmGMT = gmtime( &time_tLocal );

        const char* szLocal = asctime( &tmLocal );
        cout << szLocal << endl;

        const char* szGMT = asctime( ptmGMT );
        cout << szGMT << endl;

        // What about changing GMT to local?
        //...
        return 0;
}
在我的机器上打印结果将是:
Wed Jul 20 15:30:00 2011

Wed Jul 20 05:30:00 2011
没有问题,因为悉尼的时间是GMT+8。

可以看到,将一个本地时间转化成GMT时间是相当容易的,
        // Convert localtime to GMT
        tm* ptmGMT = gmtime( &time_tLocal );
其实只有一行代码。
那么,反过去呢?您有好的办法么?这个问题的奇怪之处就在于时间的相互转化应当是一个非常容易的操作才对,因为它是一个相对来讲经常会遇到的问题。

楼上的CPPBUG和KR2000的思路大致就是我以前用的老方法了,虽然你们并没有写出实际的代码出来,但我想如果真的要你们去做,相信花费一定时间调试之后,你们一定也能把它弄出来。
Advertisement
Advertisement

2012年度奖章获得者 2011年度奖章获得者

发表于 2011-7-20 19:46 |显示全部楼层

回复 菜地一块 11# 帖子

此文章由 交易人生 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 交易人生 所有!转贴必须注明作者、出处和本声明,并保持内容完整
你不做os level 的调用,你的run time lib也做了。比如这句: tmLocal.tm_isdst = -1;// Leave it to C run-time library

任何时间函数如何判断day light saving?要不然在这里明确地给出,要不然留给系统,这种东西总有os dependency. c++跨平台总有难度,曾经搞过跨平台,用stl,不同公司的run time都有差距。

这点Java强。
0  to 1

发表于 2011-7-20 19:57 |显示全部楼层
此文章由 菜地一块 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 菜地一块 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 交易人生 于 2011-7-20 18:46 发表
你不做os level 的调用,你的run time lib也做了。比如这句: tmLocal.tm_isdst = -1;// Leave it to C run-time library

任何时间函数如何判断day light saving?要不然在这里明确地给出,要不然留给系统,这种东西总有os dependency. c++跨平台总有 ...

呵呵,您想说什么呀? 只要写C/C++代码,肯定要调LIBRARY的呀。
好吧,那就说在WINDOWS下吧,您打算怎么做呀?
有兴趣的话不妨来露一手呗;-)

[ 本帖最后由 菜地一块 于 2011-7-20 19:04 编辑 ]

发表于 2011-7-20 20:35 |显示全部楼层
此文章由 cppbug 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 cppbug 所有!转贴必须注明作者、出处和本声明,并保持内容完整
Lz说的os调用应该说的是指programmer直接调用系统api,比如win32 api。
这种是跨平台很困难,但是用c/c++标准库跨平台是没问题的

发表于 2011-7-20 21:14 |显示全部楼层
此文章由 菜地一块 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 菜地一块 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 cppbug 于 2011-7-20 19:35 发表
Lz说的os调用应该说的是指programmer直接调用系统api,比如win32 api。
这种是跨平台很困难,但是用c/c++标准库跨平台是没问题的

是的cppbug。因为如果不说那句话的话,在WINDOWS中是可以使用诸如windows api,MFC以及其他一些方法来完成这项工作的。那样虽然也能做到,但就失去了我探讨这个问题的本意了。
因为我当时遇到的问题本来就是必须同时在WINDOWS/Linux/UNIX环境下跑的程序。
如果您确实知道一些跨平台的C++库的话,也可以使用。我们使用的是ACE。

那句话本来就是随便加的,结果反而变成喧宾夺主了。
类似iostream, string, vector, map等等这些C++标准库,我认为在跨平台方面是没有什么问题的。
让我们回到问题本身吧 ;-)
头像被屏蔽

禁止发言

发表于 2011-7-21 11:45 |显示全部楼层
此文章由 netstat 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 netstat 所有!转贴必须注明作者、出处和本声明,并保持内容完整
别折腾了,用
#ifdef __unix__

#elif defined _WIN32


#endif
Advertisement
Advertisement

退役斑竹

发表于 2011-7-21 13:42 |显示全部楼层
此文章由 大饼 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 大饼 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 netstat 于 2011-7-21 10:45 发表
别折腾了,用
#ifdef __unix__

#elif defined _WIN32


#endif

顶ls的
专攻电子电路

发表于 2011-7-21 13:53 |显示全部楼层
此文章由 kylenix 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 kylenix 所有!转贴必须注明作者、出处和本声明,并保持内容完整
说白了,lz就是说c++的标准库(其实是c的库time.h)里面没有提供一个gmtime的反函数,所以要自己写,所以很麻烦。

发表于 2011-7-21 14:15 |显示全部楼层
此文章由 菜地一块 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 菜地一块 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 kylenix 于 2011-7-21 12:53 发表
说白了,lz就是说c++的标准库(其实是c的库time.h)里面没有提供一个gmtime的反函数,所以要自己写,所以很麻烦。

呵呵,是啊,不过这只是我个人的一些见解,也许有好方法,只是我不知道而已。这么简单的功能,难道真的要自己写么?我觉得很诡异啊。
如果单纯是为了解决问题,我就没必要发帖了,已经解决的问题了。

发表于 2011-7-21 15:00 |显示全部楼层
此文章由 kylenix 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 kylenix 所有!转贴必须注明作者、出处和本声明,并保持内容完整
用c++是这样的了,c/c++的库包括stl还远远不能跟java/.net等的库相比。应该有很多第三方的开源的库可以用,多积累点是做c/c++的本分

发表于 2011-7-21 15:13 |显示全部楼层
此文章由 菜地一块 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 菜地一块 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 kylenix 于 2011-7-21 14:00 发表
用c++是这样的了,c/c++的库包括stl还远远不能跟java/.net等的库相比。应该有很多第三方的开源的库可以用,多积累点是做c/c++的本分

您这番话基本可以挂在任何一篇讨论C++问题的楼下
语言之争就不在这里谈了吧 ;-)
Advertisement
Advertisement

发表于 2011-7-21 15:15 |显示全部楼层
此文章由 Traverse 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 Traverse 所有!转贴必须注明作者、出处和本声明,并保持内容完整
楼主看下strftime的用法吧。

发表于 2011-7-21 16:01 |显示全部楼层
此文章由 菜地一块 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 菜地一块 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 Traverse 于 2011-7-21 14:15 发表
楼主看下strftime的用法吧。

The strftime and wcsftime functions format the tm time value in timeptr according to the supplied format argument and store the result in the buffer strDest.

这个函数是用来改输出格式,以便符合用户的阅读习惯的吧(例如,是月-日-年还是日-月-年等)。你能否说的详细一点或者举个具体例子?

发表于 2011-7-21 17:22 |显示全部楼层
此文章由 cppbug 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 cppbug 所有!转贴必须注明作者、出处和本声明,并保持内容完整
lz说的这个问题的确没有非常简单的,用一条语句就能解决的方法,除了标准库以外,可以考虑用c++ boost
解决,这里有一些讨论:http://stackoverflow.com/questio ... sing-boostdate-time

评分

参与人数 1积分 +2 收起 理由
菜地一块 + 2 终于可以评分了,谢谢您的思考,一起进步!

查看全部评分

发表于 2011-7-22 17:25 |显示全部楼层
此文章由 Traverse 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 Traverse 所有!转贴必须注明作者、出处和本声明,并保持内容完整
刚刚又看了一下C++有关时间的几个函数,使用localtime可以很容易的将时间转换为本地时间,我写了个例子,
-------------------------------------------
include <time.h>
#include <iostream>
using namespace std;
int main()
{
        time_t rawtime;
        struct tm *ts;

        time(&rawtime);

        printf("GMT time is %s\n", asctime(gmtime(&rawtime)));

        tzset();
        ts = localtime(&rawtime);
        printf("Time zone is %s\n", getenv("TZ"));
        printf("Local time time is %s\n", asctime(ts));

        putenv("TZ=Australia/Perth");
        tzset();
        ts = localtime(&rawtime);
        printf("Time zone is %s\n", getenv("TZ"));
        printf("Local time time is %s\n", asctime(ts));

        putenv("TZ=Australia/Sydney");
        tzset();
        ts = localtime(&rawtime);
        printf("Time zone is %s\n", getenv("TZ"));
        printf("Local time time is %s\n", asctime(ts));

        return 0;
}
-----------------------
在我机子上的输出如下:
~$ ./a.out
GMT time is Fri Jul 22 06:19:00 2011

Time zone is EST
Local time time is Fri Jul 22 01:19:00 2011

Time zone is Australia/Perth
Local time time is Fri Jul 22 14:19:00 2011

Time zone is Australia/Sydney
Local time time is Fri Jul 22 16:19:00 2011

需要注意的是一定要检查本地的环境参数TZ是否设置正确,good luck.

评分

参与人数 1积分 +2 收起 理由
菜地一块 + 2 谢谢您的思考,一起进步!

查看全部评分

发表于 2011-7-22 22:00 |显示全部楼层
此文章由 pecan78 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 pecan78 所有!转贴必须注明作者、出处和本声明,并保持内容完整
boost的date_time库有此功能
Advertisement
Advertisement

发表于 2011-7-22 22:07 |显示全部楼层
此文章由 菜地一块 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 菜地一块 所有!转贴必须注明作者、出处和本声明,并保持内容完整
LS的朋友,您的方法可能不是我说的意思,您实际上是在对一个timet_t调用gmtime和localtime两个函数,这样就得到了两个tm结构。您的time_t的值已经是本地时间距离那个1970年……之间的差值了。
这时候自然是比较容易的。可是如果是一个字符串呢?
比如就说GMT时间Fri Jul 22 06:19:00 2011,你是怎么才能先把它转成time_t呢?
您例子中的GMT时间是用time()函数得到的,呵呵。

假如我给您int iYear=2011, iMon=7, iDate=22, iHr=6, iMin=19, iSec=0;这样6个整数,您打算怎么做呢?
这就完完全全是我当年遇到的情况了。因为我们下层给我们报了GMT时间,我们本来什么也不做就给客户就完了。结果有些客户有要求本地时间。折腾了好久。。

发表回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Advertisement
Advertisement
返回顶部