在C++/boost中将日期时间转换为不同的时区



我有印度股市的价格数据,但上面的时间和日期戳是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

相关内容

  • 没有找到相关文章

最新更新