联系方式

d2FuZ0B5dWVtYWlsLmNvbQ==

解决C++和PHP的时间函数因时差引起的衔接问题

by 猫小星经济人

发布时间:2014-05-22 02:04本文标签:gmtimemktimePHPUTCWin32时间

最近有这么一个需求:

  1. 通过C++的时间函数将给定的日期转换成time_t类型的的Unix Timestamp
  2. 通过C++的时间函数将上述time_t类型的Unix Timestamp还原成可阅读的时间
  3. 通过C++在数据库中找到上述time_t附近的其他记录(通过比较存放time_t类型数据的INT字段)
  4. 通过PHP构建上述数据库

分别实现上述需求:

1. 通过C++的时间函数将给定的日期转换成time_t类型的的Unix Timestamp

很简单的想到了使用mktime函数。mktime函数接受一个struct tm*的参数,手工设置好tm参数的值,交给mktime既可以得到一个time_t。

//比如获得2013年10月18日 16:00:00的timestamp:

struct tm time;

time.tm_year = 2013 - 1900;

time.tm_mon = 10 - 1;

time.tm_mday = 18;

time.tm_hour = 16;

time.tm_min = 0;

time.tm_sec = 0;

time_t timestamp = mktime(&time);

上述代码在我的PC上获得一个值为1382083200的timestamp。

2. 通过C++的时间函数将上述time_t类型的Unix Timestamp还原成可阅读的时间

C++有两个函数可以将Unix Timestamp还原成可以阅读的时间(struct tm),分别是gmtimelocaltime。下面是分别使用这两个函数获得的struct tm结果:

time_t test = 1382083200; //直接拿上面的结果做测试

struct tm *time1 = gmtime(&test);

struct tm *time2 = localtime(&test);

获得的time1和time2结果分别如下:

time1.tm_sec = 0;

time1.tm_min = 0;

time1.tm_hour = 8;

time1.tm_mday = 18;

time1.tm_mon = 9;

time1.tm_year = 113;

time2.tm_sec = 0;

time2.tm_min = 0;

time2.tm_hour = 16;

time2.tm_mday = 18;

time2.tm_mon = 9;

time2.tm_year = 113;

使用localtime返回的结果才是正确的结果。 即mktime函数制作的运行程序的机器上的本地时间。

3. 通过C++在数据库中找到上述time_t附近的其他记录(通过比较存放time_t类型数据的INT字段)

使用C++执行MySQL的查询语句,查找1382083200接近的记录,却发现返回的结果是空集。显然数据库的timestamp字段内容有误。

4. 通过PHP构建上述数据库

使用PHP构建数据的timestamp字段(INT类型)只有一个函数,即PHP的mktime函数,代码如下:

<?php

$timestamp = mktime(16, 0, 0, 10, 18, 2013);

输出结果为:1382126400,和 C++的mktime函数的结果1382083200不同。

原因何在:

通过阅读PHP的mktime函数文档,可以得知该函数和C++的mktime函数一样,都是制作运行程序的机器上的本地时间,两个函数返回结果不同必然因为两个环境的本地时间不同。为了测试在php中执行如下代码:

<?php

echo date_default_timezone_get();

输出结果是:America/New_York

解决方案:

最显而易见的解决方案是将PHP和电脑的timezone统一。但这不是一个好办法,虽然这个程序是我自己在实用,但很难保证以后会记得这个细节。

最佳的解决方案是使用UTC time(Coordinated Universal Time),即上述C++的gmtime函数维护的那个时区。使用UTC的条件就是找到C++和PHP的UTC相关函数:

  1. Win32 平台使用_mkgmtime代替mktime。_mkgmtime函数将返回一个UTC的Unix Timestamp
  2. C++中使用gmtime还原UTC的timestamp
  3. PHP中没有独立的制作UTC timestamp的函数,但是可以暂时把timezone设置为UTC,方法是调用date_default_timezone_set函数把时区设为UTC:

<?php

date_default_timezone_set("UTC");

echo mktime(16, 0, 0, 10, 18, 2013);

使用上述解决方案无论是Win32平台的C++还是PHP,都将生成值为11382112000的Timestamp。

分享到: