我有印度股市的价格数据,但上面的时间和日期戳是GMT,所以我可以使用表示正确日期和时间的数据。
我需要将DB中一些记录的日期和时间从GMT(我当前的时区)转换为IST。
mysql> desc price_hist;
+---------------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-----------------------+------+-----+---------+----------------+
| trade_id | int(11) | NO | PRI | NULL | auto_increment |
| contract_name | varchar(14) | NO | MUL | NULL | |
| trade_date | date | NO | | NULL | |
| trade_time | varchar(6) | NO | | NULL | |
| trade_price | decimal(10,4) | NO | | NULL | |
| trade_volume | bigint(20) | NO | | NULL | |
+---------------+-----------------------+------+-----+---------+----------------+
8 rows in set (0.02 sec)
我试图通过运行来更改数据库中的时区,但没有成功:
select convert_tz("2010-06-30 19:00:00",'GMT','IST');
+-----------------------------------------------+
| convert_tz("2011-06-30 09:00:00",'GMT','IST') |
+-----------------------------------------------+
| NULL |
+-----------------------------------------------+
1 row in set (0.01 sec)
我是Boost的新手,但有人建议我在代码中使用Boost日期来处理这一问题。
我在一些帖子中搜索了日期时间转换,但没有找到能回答我特定问题的帖子。
如果有一个特定的链接,或者更好的是,例如某人可以分享的增强代码,这对像我这样的核心来说将是一个很好的开始。:-)
我使用@Karison提供的参考来编写以下代码:
#include "boost/date_time/local_time/local_time.hpp"
#include <iostream>
int main()
{
using namespace boost::posix_time;
using namespace boost::gregorian;
using namespace boost::local_time;
tz_database tz_db;
time_zone_ptr chi_tz=tz_db.time_zone_from_region("America/Chicago");
time_zone_ptr jst_tz(new posix_time_zone("EST+5:00:00"));
local_date_time jpn_time(date(2012,Jan,3), hours(16), jst_tz,local_date_time::NOT_DATE_TIME_ON_ERROR);
local_date_time osaka_time = jpn_time.local_time_in(chi_tz);
std::cout<<"osaka_time: "<<osaka_time<<std::endl;
return 0;
}
首先让我们更改语法并将问题分开,因为我可以看到有3个问题。
convert_tz
的第一个语法采用一个字符串,调用应该是这样的:
select convert_tz('2011-06-30 09:00:00','GMT','IST')
单引号而非双引号。
第二。如果你的机器位于同一时区,并且你在符合POSIX的系统上运行,你可以获得代表日期的字符串,并执行:
struct tm result;
strptime(<time string>, <format string>, &result);
time_t epoch_time = mktime(&result);
这将为您提供标准的UNIX时间,然后您可以使用它来执行任何需要的操作。
最后但并非最不重要的助推。可以肯定的是,这是一个强大的库,但我不认为对于这个项目,你现在需要增加它的复杂性。如果你仍然想尝试一下,或者你不在符合POSIX的系统上,你可以看看http://www.boost.org/doc/libs/1_48_0/doc/html/date_time.html,您仍然需要根据从数据库返回的字符串创建ptime
,然后根据需要对其进行操作。使用local_time
部分根据需要创建时区对象,然后对照它检查从数据库中获得的时间http://www.boost.org/doc/libs/1_48_0/doc/html/date_time/examples/general_usage_examples.html
尤其是最后一个。因此,对于您的示例,它将是:
time_zone_ptr src_zone(new posix_time_zone("IST+05:30:00"));
time_zone_ptr dst_zone(new posix_time_zone("CST"));
local_date_time trd_time(date(....), hours(...), src_zone,
local_date_time::NOT_DATE_TIME_ON_ERROR);
local_date_time res_time = trd_time.local_time_in(dst_zone);
不能保证它会100%正确,但你明白了。
示例:
#include "boost/date_time/local_time/local_time.hpp"
#include <iostream>
int main()
{
using namespace boost::posix_time;
using namespace boost::gregorian;
using namespace boost::local_time;
tz_database tz_db;
time_zone_ptr chi_tz(new posix_time_zone("CST-06:00:00");
time_zone_ptr jst_tz(new posix_time_zone("JST+09:00:00"));
local_date_time jpn_time(date(2012,Jan,3), hours(16),
chi_tz,local_date_time::NOT_DATE_TIME_ON_ERROR);
local_date_time osaka_time = jpn_time.local_time_in(jst_tz);
std::cout<<"osaka_time: "<<osaka_time<<std::endl;
return 0;
}
以下是解决此问题的几种方法:
1) Windows:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <string>
#include <locale>
#include <time.h>
#include <vector>
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
using namespace boost::posix_time;
using namespace boost::gregorian;
using namespace boost::local_time;
//***********
// U T I L S
//***********
std::string WCHAR2StdString(WCHAR* wchar_buf)
{
char narrow_buf[260];
char DefChar = ' ';
WideCharToMultiByte(CP_ACP,0,wchar_buf,-1, narrow_buf,260,&DefChar, NULL);
return std::string (narrow_buf);
}
std::string LocalTimeZone(TIME_ZONE_INFORMATION & tzi)
{
short int tz_bias = tzi.Bias;
std::string tzName(WCHAR2StdString(tzi.StandardName));
// Get acronym for X_(Zone) Standard Time: 'X_ST'
std::vector<std::string> vec;
boost::split(vec, tzName, boost::is_any_of(" "));
std::string result;
for(std::vector<std::string>::iterator i = vec.begin(); i != vec.end(); ++i)
{
std::string s = *i;
char c = s.c_str()[0];
result += c;
}
return result;
}
//**********
// M A I N
//**********
int _tmain(int argc, _TCHAR* argv[])
{
using namespace boost::posix_time;
using namespace boost::gregorian;
using namespace boost::local_time;
// Windows Timezone info.
TIME_ZONE_INFORMATION tzi;
DWORD res = GetTimeZoneInformation(&tzi);
// Timezone string
std::string local_tz_str = LocalTimeZone(tzi);
// Hour Bias
std::stringstream ss;
ss << (abs(tzi.Bias)/60);
std::string bias_hrs(ss.str());
// Build string: e.g. CST+08:00:00
short int sign = 0;
tzi.Bias > 0 ? sign = -1 : sign = 1;
// Pad with zeros as necessray
if(abs(tzi.Bias/60) < 10) bias_hrs = ("0" + bias_hrs);
bias_hrs += ":00:00";
(sign > 0) ? (bias_hrs = local_tz_str + "+" + bias_hrs) : (bias_hrs = local_tz_str + "-" + bias_hrs);
local_tz_str = bias_hrs; // local_tz_str is a better name to continue with
std::string formatted_tz_desc(bias_hrs);
// Construct local_date_time and time_zone etc.
long long ticksFromEpoch = 1329122250168; // !!! (assumed input format) milliseconds from 1970-01-01 00:00:00
std::time_t tt = static_cast<time_t>(ticksFromEpoch/1000); // (ticksFromEpoch/1000) gives seconds since epoch
ptime pt = from_time_t(tt);
time_zone_ptr zone(new boost::local_time::posix_time_zone(formatted_tz_desc));
local_date_time locally_adjusted_date_time(pt, zone);
// Format stringstream: YYYY-Mmm-dd HH:MM:SS
std::stringstream strm;
strm.imbue(std::locale(std::cout.getloc(), new local_time_facet("%Y-%m-%d %H:%M:%S")));
strm << locally_adjusted_date_time;
// Print adjusted result
std::cout << strm.str() << std::endl << std::endl;
return 0;
}
您可以从std库中获取时区信息,如下所示:
2) Posix:
#include <stdio.h>
#include <time.h>
#include <string>
#include <iostream>
#include <vector>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
std::string LocalTimeZone();
int main() {
std::cout << LocalTimeZone() << std::endl;
return 0;
}
std::string LocalTimeZone()
{
time_t now = time(NULL);
struct tm tnow = *localtime(&now);
std::string tz = tnow.tm_zone;
// Format the struct:
char buff[100];
strftime( buff, sizeof buff, "%a %b %d %Y %T %Z%z", &tnow );
// Parse the bits you want:
std::vector<std::string> vec;
const std::string s(buff);
boost::split(vec, s, boost::is_any_of(" "));
std::vector<std::string>::iterator i = vec.end();
return *--i;
}
一旦您格式化了时区字符串,例如CST+08:00:00
,您就可以继续使用上面显示的boost方法。
HTH